qbs-src-1.4.5/000077500000000000000000000000001266132464200131015ustar00rootroot00000000000000qbs-src-1.4.5/LGPL_EXCEPTION.txt000066400000000000000000000022501266132464200160150ustar00rootroot00000000000000The Qt Company LGPL Exception version 1.1 As an additional permission to the GNU Lesser General Public License version 2.1, the object code form of a "work that uses the Library" may incorporate material from a header file that is part of the Library. You may distribute such object code under terms of your choice, provided that: (i) the header files of the Library have not been modified; and (ii) the incorporated material is limited to numerical parameters, data structure layouts, accessors, macros, inline functions and templates; and (iii) you comply with the terms of Section 6 of the GNU Lesser General Public License version 2.1. Moreover, you may apply this exception to a modified version of the Library, provided that such modification does not involve copying material from the Library into the modified Library's header files unless such material is limited to (i) numerical parameters; (ii) data structure layouts; (iii) accessors; and (iv) small macros, templates and inline functions of five lines or less in length. Furthermore, you are not required to apply this additional permission to a modified version of the Library. qbs-src-1.4.5/LICENSE.LGPLv21000066400000000000000000000635021266132464200152020ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 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. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, 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 and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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 with this License. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. 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. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; 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. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! qbs-src-1.4.5/LICENSE.LGPLv3000066400000000000000000000175601266132464200151250ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE The Qt Toolkit is Copyright (C) 2015 The Qt Company Ltd. Contact: http://www.qt.io/licensing You may use, distribute and copy the Qt GUI Toolkit under the terms of GNU Lesser General Public License version 3, which is displayed below. ------------------------------------------------------------------------- GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright © 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this licensedocument, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, “this License” refers to version 3 of the GNU Lesser General Public License, and the “GNU GPL” refers to version 3 of the GNU General Public License. “The Library” refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An “Application” is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A “Combined Work” is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the “Linked Version”. The “Minimal Corresponding Source” for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The “Corresponding Application Code” for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser 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 Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. qbs-src-1.4.5/README000066400000000000000000000014001266132464200137540ustar00rootroot00000000000000Qt Build Suite ============== Qbs is a cross-platform build tool. The project's homepage is http://wiki.qt.io/qbs Supported Platforms =================== Windows XP SP2 or later OS X 10.6 or later Linux (tested on Debian 6/7 and Ubuntu 13) Building the sources requires Qt 5.1.0 or later. Build Instructions ================== Prerequisites: * Qt 5.1.0 or later * On Windows: - MinGW or Visual Studio * On OS X: Xcode The installed toolchains have to match the one Qt was compiled with. You can build qbs with cd $SOURCE_DIRECTORY qmake -r make (or mingw32-make or nmake or jom, depending on your platform) Installation ("make install") is not needed. It is however possible, using make install INSTALL_ROOT=$INSTALL_DIRECTORY qbs-src-1.4.5/bin/000077500000000000000000000000001266132464200136515ustar00rootroot00000000000000qbs-src-1.4.5/bin/ibmsvc.xml000066400000000000000000000011221266132464200156520ustar00rootroot00000000000000 qbs-src-1.4.5/bin/ibqbs.bat000066400000000000000000000000751266132464200154430ustar00rootroot00000000000000@xgConsole /profile=%~dp0\ibmsvc.xml /command="qbs -j 20 %*" qbs-src-1.4.5/doc/000077500000000000000000000000001266132464200136465ustar00rootroot00000000000000qbs-src-1.4.5/doc/classic.css000066400000000000000000000103201266132464200157750ustar00rootroot00000000000000BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { font-family: Arial, Geneva, Helvetica, sans-serif; } H1 { text-align: center; font-size: 160%; } H2 { font-size: 120%; } H3 { font-size: 100%; } h3.fn,span.fn { background-color: #eee; border-width: 1px; border-style: solid; border-color: #ddd; font-weight: bold; padding: 6px 0px 6px 10px; margin: 42px 0px 0px 0px; } hr { border: 0; color: #a0a0a0; background-color: #ccc; height: 1px; width: 100%; text-align: left; margin: 34px 0px 34px 0px; } table.valuelist { border-width: 1px 1px 1px 1px; border-style: solid; border-color: #dddddd; border-collapse: collapse; background-color: #f0f0f0; } table.indextable { border-width: 1px 1px 1px 1px; border-collapse: collapse; background-color: #f0f0f0; border-color:#555; font-size: 110%; } table td.largeindex { border-width: 1px 1px 1px 1px; border-collapse: collapse; background-color: #f0f0f0; border-color:#555; font-size: 120%; } table.valuelist th { border-width: 1px 1px 1px 2px; padding: 4px; border-style: solid; border-color: #666; color:white; background-color:#666; } th.titleheader { border-width: 1px 0px 1px 0px; padding: 4px; border-style: solid; border-color: #444; color:white; background-color:#555555; font-size: 110%; } th.largeheader { border-width: 1px 0px 1px 0px; padding: 4px; border-style: solid; border-color: #444; color:white; background-color:#555555; font-size: 120%; } p { margin-left: 4px; margin-top: 8px; margin-bottom: 8px; } a:link { color: #0046ad; text-decoration: none } a:visited { color: #672967; text-decoration: none } a.obsolete { color: #661100; text-decoration: none } a.compat { color: #661100; text-decoration: none } a.obsolete:visited { color: #995500; text-decoration: none } a.compat:visited { color: #995500; text-decoration: none } body { background: #ffffff; color: black } table.generic, table.annotated { border-width: 1px; border-color:#bbb; border-style:solid; border-collapse:collapse; } table td.memItemLeft { width: 180px; padding: 2px 0px 0px 8px; margin: 4px; border-width: 1px; border-color: #E0E0E0; border-style: none; font-size: 100%; white-space: nowrap } table td.memItemRight { padding: 2px 8px 0px 8px; margin: 4px; border-width: 1px; border-color: #E0E0E0; border-style: none; font-size: 100%; } table tr.odd { background: #f0f0f0; color: black; } table tr.even { background: #e4e4e4; color: black; } table.annotated th { padding: 3px; text-align: left } table.annotated td { padding: 3px; } table tr pre { padding-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; border: none; background: none } tr.qt-style { background: #96E066; color: black } body pre { padding: 0.2em; border: #e7e7e7 1px solid; background: #f1f1f1; color: black } table tr.qt-code pre { padding: 0.2em; border: #e7e7e7 1px solid; background: #f1f1f1; color: black } span.preprocessor, span.preprocessor a { color: darkblue; } span.comment { color: darkred; font-style: italic } span.string,span.char { color: darkgreen; } .title { text-align: center } .subtitle { font-size: 0.8em } .small-subtitle { font-size: 0.65em } .qmlitem { padding: 0; } .qmlname { white-space: nowrap; font-weight: bold; font-size: 125%; } .qmltype { font-weight: bold; font-size: 125%; } .qmlproto, .qmldoc { // border-top: 1px solid #84b0c7; } .qmlproto { padding: 0; //background-color: #e4e4e4;//#d5e1e8; //font-weight: bold; //-webkit-border-top-left-radius: 8px; //-webkit-border-top-right-radius: 8px; //-moz-border-radius-topleft: 8px; //-moz-border-radius-topright: 8px; } .qmldoc { border-top: 1px solid #e4e4e4; //padding: 2px 5px; //background-color: #eef3f5; //border-top-width: 0; //-webkit-border-bottom-left-radius: 8px; //-webkit-border-bottom-right-radius: 8px; //-moz-border-radius-bottomleft: 8px; //-moz-border-radius-bottomright: 8px; } .qmldoc p, .qmldoc dl, .qmldoc ul { //margin: 6px 0; } *.qmlitem p { //margin-top: 0px; //margin-bottom: 0px; } qbs-src-1.4.5/doc/config/000077500000000000000000000000001266132464200151135ustar00rootroot00000000000000qbs-src-1.4.5/doc/config/macros.qdocconf000066400000000000000000000001071266132464200201130ustar00rootroot00000000000000macro.QBS = "Qbs" macro.qbsversion = $QBS_VERSION qbs-src-1.4.5/doc/config/qbs-project.qdocconf000066400000000000000000000023161266132464200210640ustar00rootroot00000000000000include($QT_INSTALL_DOCS/global/macros.qdocconf) include($QT_INSTALL_DOCS/global/qt-cpp-defines.qdocconf) include($QT_INSTALL_DOCS/global/compat.qdocconf) include($QT_INSTALL_DOCS/global/fileextensions.qdocconf) project = "Qt Build Suite" description = "QBS Manual" headerdirs = sourcedirs = $SRCDIR imagedirs = $SRCDIR/images $SRCDIR/templates/images outputdir = $OUTDIR exampledirs = $SRCDIR include(macros.qdocconf) sources.fileextensions = "*.qdoc" qhp.projects = Qbs qhp.Qbs.file = qbs.qhp qhp.Qbs.namespace = org.qt-project.qbs.$QBS_VERSION_TAG qhp.Qbs.virtualFolder = doc qhp.Qbs.indexTitle = Qt Build Suite qhp.Qbs.filterAttributes = qbs $QBS_VERSION qhp.Qbs.customFilters.Qbs.name = Qt Build Suite $QBS_VERSION qhp.Qbs.customFilters.Qbs.filterAttributes = qbs $QBS_VERSION qhp.Qbs.indexRoot = qhp.Qbs.subprojects = manual qhp.Qbs.subprojects.manual.title = Qbs Manual qhp.Qbs.subprojects.manual.indexTitle = Qbs Manual qhp.Qbs.subprojects.manual.type = manual # Doxygen compatibility commands macro.see = "\\sa" macro.function = "\\fn" navigation.homepage = "Qbs Manual" buildversion = "Qt Build Suite $QBS_VERSION" qbs-src-1.4.5/doc/config/style/000077500000000000000000000000001266132464200162535ustar00rootroot00000000000000qbs-src-1.4.5/doc/config/style/qt5-sidebar.html000066400000000000000000000007111266132464200212600ustar00rootroot00000000000000

Qbs Manual

qbs-src-1.4.5/doc/doc.pri000066400000000000000000000045241266132464200151340ustar00rootroot00000000000000include(../src/install_prefix.pri) defineReplace(targetPath) { return($$replace(1, /, $$QMAKE_DIR_SEP)) } QDOC_BIN = $$targetPath($$[QT_INSTALL_BINS]/qdoc) QDOC_MAINFILE = $$PWD/qbs.qdocconf HELPGENERATOR = $$targetPath($$[QT_INSTALL_BINS]/qhelpgenerator) VERSION_TAG = $$replace(QBS_VERSION, "[-.]", ) HTML_DOC_PATH=$$OUT_PWD/doc/html equals(QMAKE_DIR_SEP, /) { # unix, mingw+msys QDOC = SRCDIR=$$PWD OUTDIR=$$HTML_DOC_PATH QBS_VERSION=$$QBS_VERSION QBS_VERSION_TAG=$$VERSION_TAG QT_INSTALL_DOCS=$$[QT_INSTALL_DOCS] $$QDOC_BIN } else:win32-g++* { # just mingw # The lack of spaces in front of the && is necessary! QDOC = set SRCDIR=$$PWD&& set OUTDIR=$$HTML_DOC_PATH&& set QBS_VERSION=$$QBS_VERSION&& set QBS_VERSION_TAG=$$VERSION_TAG&& set QT_INSTALL_DOCS=$$[QT_INSTALL_DOCS]&& $$QDOC_BIN } else { # nmake QDOC = set SRCDIR=$$PWD $$escape_expand(\\n\\t) \ set OUTDIR=$$HTML_DOC_PATH $$escape_expand(\\n\\t) \ set QBS_VERSION=$$QBS_VERSION $$escape_expand(\\n\\t) \ set QBS_VERSION_TAG=$$VERSION_TAG $$escape_expand(\\n\\t) \ set QT_INSTALL_DOCS=$$[QT_INSTALL_DOCS] $$escape_expand(\\n\\t) \ $$QDOC_BIN } QHP_FILE = $$HTML_DOC_PATH/qbs.qhp QCH_FILE = $$OUT_PWD/doc/qbs.qch HELP_DEP_FILES = $$PWD/qbs.qdoc \ $$QDOC_MAINFILE html_docs.commands = $$QDOC $$PWD/qbs.qdocconf html_docs.depends += $$HELP_DEP_FILES html_docs_online.commands = $$QDOC $$PWD/qbs-online.qdocconf html_docs_online.files = $$QHP_FILE qch_docs.commands = $$HELPGENERATOR -o $$shell_quote($$QCH_FILE) $$QHP_FILE qch_docs.depends += html_docs docs_online.depends = html_docs_online QMAKE_EXTRA_TARGETS += html_docs_online docs_online inst_qch_docs.files = $$QCH_FILE inst_qch_docs.path = $${QBS_INSTALL_PREFIX}/share/doc/qbs inst_qch_docs.CONFIG += no_check_exist no_default_install INSTALLS += inst_qch_docs inst_html_docs.files = $$HTML_DOC_PATH inst_html_docs.path = $$inst_qch_docs.path inst_html_docs.CONFIG += no_check_exist no_default_install directory INSTALLS += inst_html_docs install_docs.depends = install_inst_qch_docs install_inst_html_docs QMAKE_EXTRA_TARGETS += install_docs docs.depends = qch_docs QMAKE_EXTRA_TARGETS += html_docs qch_docs docs fixnavi.commands = \ cd $$targetPath($$PWD) && \ perl fixnavi.pl -Dqcmanual -Dqtquick \ qbs.qdoc QMAKE_EXTRA_TARGETS += fixnavi qbs-src-1.4.5/doc/doc.qbs000066400000000000000000000014411266132464200151220ustar00rootroot00000000000000import qbs 1.0 import QbsFunctions Product { name: "documentation" builtByDefault: false type: "qch" Depends { name: "Qt.core" } files: [ "qbs.qdoc", "config/*.qdocconf", "reference/**/*", ] Group { name: "main qdocconf file" files: "qbs.qdocconf" fileTags: "qdocconf-main" } property string versionTag: QbsFunctions.qbsVersion().replace(/\.|-/g, "") Qt.core.qdocQhpFileName: "qbs.qhp" Qt.core.qdocEnvironment: [ "QBS_VERSION=" + QbsFunctions.qbsVersion(), "SRCDIR=" + path, "QT_INSTALL_DOCS=" + Qt.core.docPath, "QBS_VERSION_TAG=" + versionTag ] Group { fileTagsFilter: "qdoc-html" qbs.install: true qbs.installDir: "share/doc/qbs" } } qbs-src-1.4.5/doc/fixnavi.pl000066400000000000000000000111761266132464200156550ustar00rootroot00000000000000#! /usr/bin/perl -w use strict; my @files = (); my %defines = (); for (@ARGV) { if (/^-D(.*)$/) { $defines{$1} = 1; } elsif (/^-/) { printf STDERR "Unknown option '".$_."'\n"; exit 1; } else { push @files, $_; } } int(@files) or die "usage: $0 [-D]... \n"; my @toc = (); my %title2page = (); my $doctitle = ""; my $curpage = ""; my $intoc = 0; my %prev_skips = (); my %next_skips = (); my %define_skips = (); my %polarity_skips = (); my $prev_skip = ""; my $next_skip = ""; my $define_skip = ""; my $polarity_skip = 0; for my $file (@files) { my $skipping = 0; # no nested ifs! open FILE, $file or die "File $file cannot be opened.\n"; while () { if (/^\h*\\if\h+defined\h*\(\h*(\H+)\h*\)/) { $skipping = !defined($defines{$1}); if (!$intoc) { $define_skip = $1; $polarity_skip = $skipping; } } elsif (/^\h*\\else/) { $skipping = 1 - $skipping; } elsif (/^\h*\\endif/) { $skipping = 0; } elsif (keys(%title2page) == 1 && /^\h*\\list/) { $intoc++; } elsif (!$intoc) { if ($skipping && /^\h*\\previouspage\h+(\H+)/) { $prev_skip = $1; } elsif ($skipping && /^\h*\\nextpage\h+(\H+)/) { $next_skip = $1; } elsif (/^\h*\\page\h+(\H+)/) { $curpage = $1; } elsif (/^\h*\\title\h+(.+)$/) { if ($curpage eq "") { die "Title '$1' appears in no \\page.\n"; } if (length($define_skip)) { $define_skips{$1} = $define_skip; $polarity_skips{$1} = $polarity_skip; $prev_skips{$1} = $prev_skip; $next_skips{$1} = $next_skip; $define_skip = $prev_skip = $next_skip = ""; } $title2page{$1} = $curpage; $doctitle = $1 if (!$doctitle); $curpage = ""; } } else { if (/^\h*\\endlist/) { $intoc--; } elsif (!$skipping && /^\h*\\(?:o|li)\h+\\l\h*{(.*)}$/) { push @toc, $1; } } } close FILE; } my %prev = (); my %next = (); my $last = $doctitle; for my $title (@toc) { $next{$last} = $title2page{$title}; $prev{$title} = $title2page{$last}; $last = $title; } for my $file (@files) { open IN, $file or die "File $file cannot be opened a second time?!\n"; open OUT, '>'.$file.".out" or die "File $file.out cannot be created.\n"; my $cutting = 0; while () { if (!$cutting) { if (/^\h*\\contentspage/) { $cutting = 1; } } else { if (/^\h*\\title\h+(.+)$/) { if (defined($define_skips{$1})) { print OUT " \\if defined(".$define_skips{$1}.")\n"; if ($polarity_skips{$1}) { print OUT " \\previouspage ".$prev_skips{$1} if ($prev_skips{$1}); print OUT " \\else\n"; } } print OUT " \\previouspage ".$prev{$1} if ($prev{$1}); if (defined($define_skips{$1})) { if (!$polarity_skips{$1}) { print OUT " \\else\n"; print OUT " \\previouspage ".$prev_skips{$1} if ($prev_skips{$1}); } print OUT " \\endif\n"; } print OUT " \\page ".$title2page{$1}; if (defined($define_skips{$1})) { print OUT " \\if defined(".$define_skips{$1}.")\n"; if ($polarity_skips{$1}) { print OUT " \\nextpage ".$next_skips{$1} if ($next_skips{$1}); print OUT " \\else\n"; } } print OUT " \\nextpage ".$next{$1} if ($next{$1}); if (defined($define_skips{$1})) { if (!$polarity_skips{$1}) { print OUT " \\else\n"; print OUT " \\nextpage ".$next_skips{$1} if ($next_skips{$1}); } print OUT " \\endif\n"; } print OUT "\n"; $cutting = 0; } else { next; } } print OUT $_; } close OUT; close IN; rename($file.".out", $file) or die "Cannot replace $file with new version.\n"; } qbs-src-1.4.5/doc/qbs-online.qdocconf000066400000000000000000000017071266132464200174400ustar00rootroot00000000000000include(config/qbs-project.qdocconf) HTML.footer = \ "
\n" \ "

\n" \ " © 2015 The Qt Company Ltd.\n" \ " Documentation contributions included herein are the copyrights of\n" \ " their respective owners. " \ " The documentation provided herein is licensed under the terms of the" \ " GNU Free Documentation" \ " License version 1.3 as published by the Free Software Foundation. " \ " Qt and respective logos are trademarks of The Qt Company Ltd " \ " in Finland and/or other countries worldwide. All other trademarks are property\n" \ " of their respective owners.

\n" include($QT_INSTALL_DOCS/global/qt-html-templates-online.qdocconf) # Add an .html file with sidebar content, used in the online style HTML.stylesheets += config/style/qt5-sidebar.html qbs-src-1.4.5/doc/qbs.qdoc000066400000000000000000000630321266132464200153070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ // ********************************************************************** // NOTE: the sections are not ordered by their logical order to avoid // reshuffling the file each time the index order changes (i.e., often). // Run the fixnavi.pl script to adjust the links to the index order. // ********************************************************************** /*! \contentspage{index.html}{Qt Build Suite} \page index.html \nextpage overview.html \title Qbs Manual \section1 Version \qbsversion Qt Build Suite (\QBS) is a tool that helps simplify the build process for developing projects across multiple platforms. \QBS can be used for any software project, whether it is written in Qt or not. \QBS is an all-in-one tool that generates a build graph from a high-level project description (like qmake or cmake) and additionally undertakes the task of executing the commands in the low-level build graph (like make). \note Please report bugs and suggestions to the \l{http://bugreports.qt.io/}{Qt Bug Tracker}. \list \li \l{Introduction} \li \l{Setup} \list \li \l{System Requirements} \li \l{Building} \li \l{Configuring} \li \l{Managing Qt Versions} \endlist \li \l{Usage} \list \li \l{Language Introduction} \li \l{Building Applications} \li \l{Running Applications} \li \l{Installing Files} \li \l{Using the Shell} \li \l{Custom Modules and Items} \endlist \li \l{Reference} \endlist */ /*! \contentspage index.html \previouspage index.html \page overview.html \nextpage setup.html \title Introduction \QBS builds applications based on the information in a project file that you specify in a QML dialect. Each project file specifies one project that can contain several \l{Product Item}{products}. You specify the type of the product: application, library, and so on. */ /*! \contentspage index.html \previouspage overview.html \page setup.html \nextpage system-requirements.html \title Setup \list \li \l{System Requirements} \li \l{Building} \li \l{Configuring} \li \l{Managing Qt Versions} \endlist */ /*! \contentspage index.html \previouspage setup.html \page system-requirements.html \nextpage building.html \title System Requirements To build \QBS from the source, you need the following: \list \li Qt >= 5.1.0 \endlist */ /*! \contentspage index.html \previouspage system-requirements.html \page building.html \nextpage configuring.html \title Building To build \QBS, enter the following command: \code qmake -r qbs.pro && make \endcode \section1 Configure Options \QBS recognizes the following qmake CONFIG options to customize the build: \table \header \li Option \li Notes \row \li qbs_enable_unit_tests \li Enable additional autotests. \row \li qbs_disable_rpath \li Disable the use of rpath. This can be used when packaging \QBS for distributions which do not permit the use of rpath, such as Fedora. \row \li qbs_no_dev_install \li Exclude header files from installation, that is, perform a non-developer build. \row \li qbs_enable_project_file_updates \li Enable API for updating project files. This implies a dependency to the Qt GUI module. \endtable */ /*! \contentspage index.html \previouspage building.html \page configuring.html \nextpage qt-versions.html \title Configuring Open a build shell (on Windows open an MSVC command prompt, on other platforms you can usually open the default shell): \code qbs setup-toolchains --detect \endcode The tool chain detector automatically sets up a profile for each detected tool chain. You can list the existing profiles by running: \code qbs config --list profiles \endcode Now you should be ready to build your first project with \QBS. Go into qbs/tests/manual/hello and type: \code qbs profile: \endcode If you want to build projects that use Qt, additional steps are necessary. Please refer to \l{Managing Qt Versions} for more information. */ /*! \contentspage index.html \previouspage configuring.html \page qt-versions.html \nextpage usage.html \title Managing Qt Versions \section1 Introduction To let \QBS know where the Qt build or Qt version is that you want to use, you must register it. Register a Qt version like this: \code qbs setup-qt /usr/bin/qmake myqt \endcode This will create the \c myqt profile which can then be used on the command line: \code qbs profile:myqt \endcode \note If the \c setup-toolchains command has found more than one toolchain, you will need to manually link your Qt profile to one of them, like this: \code qbs config profiles.myqt.baseProfile \endcode \section1 Multiple Qt Builds To support multiple Qt builds, or in fact any combination of related settings, you need to create several profiles. The following example illustrates how to set up three different profiles, each for a different Qt build: \code qbs setup-qt ~/dev/qt/4.7/bin/qmake qt47 qbs setup-qt ~/dev/qt/4.8/bin/qmake qt48 qbs setup-qt ~/dev/qt/5.0/qtbase/bin/qmake qt5 \endcode You can set the default Qt build like this: \code qbs config defaultProfile qt5 \endcode To choose a Qt build that is different from the default, use: \code qbs build profile:qt48 \endcode You can set other properties in a profile (not just Qt ones), in the same way you override them from the command line. For example: \code qbs setup-qt C:\Qt\5.0.0\qtbase\bin\qmake.exe qt5 qbs config profiles.qt5.qbs.architecture x86_64 qbs config profiles.qt5.baseProfile msvc2010 \endcode The last example uses the inheritance feature of profiles. All settings in the profile set as \c baseProfile are known in the derived profile as well. They can of course be overridden there. */ /*! \contentspage index.html \previouspage qt-versions.html \page usage.html \nextpage language-introduction.html \title Usage \list \li \l{Language Introduction} \li \l{Building Applications} \li \l{Running Applications} \li \l{Installing Files} \li \l{Using the Shell} \li \l{Custom Modules and Items} \endlist */ /*! \contentspage index.html \previouspage usage.html \page language-introduction.html \nextpage building-applications.html \title Language Introduction \QBS uses project files (*.qbs) to describe the contents of a project. A project contains one or more \l{Product Item}{products}. A product is the target of a build process, typically an application, library or maybe a tar ball. \section1 The Obligatory Hello World Example \QBS project files are written using a QML dialect. A very simple C++ hello world project looks like this: \code ---helloworld.qbs--- import qbs 1.0 Application { name: "helloworld" files: "main.cpp" Depends { name: "cpp" } } \endcode The import statement gives us access to some built-in types and specifies the used language version. \a Application describes the product we want to build. In this case, an application. This is just a shortcut for writing \code Product { type: "application" // ... } \endcode The \a name is the name of the product. In this case it is also the name of the produced executable (on Windows, the ".exe" extension is added by default). In the property \a files, we specify the source files for our product. Unlike QML, the right-hand side can be either a string or a string list. A single string is converted to a stringlist containing just one element. \a Depends adds the dependency to the module \l{Module cpp}{cpp}. This is necessary to let \QBS know that we have a C++ project and want to compile main.cpp with a C++ compiler. For more information about \QBS modules, see \l{Modules}. \section1 Reusing Project File Code QML-like inheritance works also in \QBS. \code ---CrazyProduct.qbs--- import qbs 1.0 Product { property string craziness: "low" } ---hellocrazyworld.qbs--- import "CrazyProduct.qbs" as CrazyProduct CrazyProduct { craziness: "enormous" name: "hellocrazyworld" // ... } \endcode You can put JS code into separate \c{.js} files and then import them. \code ---helpers.js--- function planetsCorrectlyAligned() { // implementation } ---myproject.qbs--- import qbs 1.0 import "helpers.js" as Helpers Product { name: "myproject" Group { condition: Helpers.planetsCorrectlyAligned() file: "magic_hack.cpp" } // ... } \endcode \section1 Modules A \e module is a collection of properties and language items that are used for building a product if the product depends on (or loads) the module. For example, the \a cpp module looks like this (simplified): \code Module { name: "cpp" property string warningLevel property string optimization property bool debugInformation property path precompiledHeader // ... FileTagger { patterns: "*.cpp" fileTags: ["cpp"] } Rule {...} // compiler Rule {...} // application linker Rule {...} // static lib linker Rule {...} // dynamic lib linker } \endcode The properties that can be set for the \a cpp module are used to control the behavior of your C++ tool chain. In addition, you can use FileTaggers and Rules that are explained later. As soon as your product depends on a module, it can set the properties of the module. You specify the optimization level for your product (and all build variants) like this: \code ---helloworld.qbs--- import qbs 1.0 Application { name: "helloworld" files: ["main.cpp"] cpp.optimization: "ludicrousSpeed" Depends { name: "cpp" } } \endcode A module can implicitly depend on other modules. For example, the \c Qt.core module depends on \c{cpp}. But to set the properties of a module you must make the dependency explicit. \code // THIS DOES NOT WORK Application { name: "helloworld" files: ["main.cpp"] Depends { name: "Qt.core" } cpp.optimization: "ludicrousSpeed" // ERROR! We do not know about "cpp" here, // though "Qt.core" depends on "cpp". } // THIS WORKS Application { name: "helloworld" files: ["main.cpp"] Depends { name: "Qt.core" } Depends { name: "cpp" } cpp.optimization: "ludicrousSpeed" } \endcode \section2 Different Properties for a Single File Not only the product, but all the source files of the product can have their own set of module properties. For example, assume you have some files that are known to crash your compiler if you turn on optimizations. You want to turn off optimizations for just these files and this is how you do it: \code Application { name: "helloworld" files: "main.cpp" Group { files: ["bad_file.cpp", "other_bad_file.cpp"] cpp.optimization: "none" } Depends { name: "cpp" } } \endcode \section2 Selecting Files by Properties Sometimes you have a file that is only going to be compiled on a certain platform. This is how you do it: \code Group { condition: qbs.targetOS.contains("windows") files: [ "harddiskdeleter_win.cpp", "blowupmonitor_win.cpp", "setkeyboardonfire_win.cpp" ] } Group { condition: qbs.targetOS.contains("linux") files: [ "harddiskdeleter_linux.cpp", "blowupmonitor_linux.cpp", "setkeyboardonfire_linux.cpp" ] } \endcode In the above example, \a qbs.targetOS is a property of the \a target of the the \a qbs module. The \a qbs module is always implicitly loaded. Its main properties are: \table \header \li Property \li Type \li Default \li Description \row \li buildVariant \li string \li "debug" \li Name of the current build variant. By default, "debug" and "release" are valid values but the user can add more in a project file. \row \li hostOS \li stringlist \li platform-dependent \li The host operating system. May contain "windows", "linux", "osx", "darwin", "unix", etc. \note Do not confuse this with the \c{qbs.targetOS} property, which represents the operating system on which the binaries produced by \QBS will run. \row \li targetOS \li stringlist \li platform-dependent \li The target operating system. May contain "windows", "linux", "osx", "darwin", "unix", "ios", "android", "blackberry", "qnx", etc. \endtable You can set these properties on the command line or by using a profile. The property \a qbs.buildVariant is handled in a special way. \code $ qbs # qbs.buildVariant:debug, profile: $ qbs release # qbs.buildVariant:release, profile: $ qbs profile:Maemo # qbs.buildVariant:debug, profile:Maemo $ qbs debug release # builds two variants of the project \endcode To select files by build variant: \code Group { condition: qbs.buildVariant == "debug" files: "debughelper.cpp" } \endcode To set properties for a build variant: \code Properties { condition: qbs.buildVariant == "debug" cpp.debugInformation: true cpp.optimization: "none" } \endcode Or, to use a more QML-like style: \code cpp.debugInformation: qbs.buildVariant == "debug" ? true : false cpp.optimization: qbs.buildVariant == "debug" ? "none" : "fast" \endcode \section1 File Tags and Taggers \QBS itself knows nothing about C++ files or file extensions. All source files in a product are handled equally. However, you can assign \a{file tags} to an artifact to act as a marker or to specify a file type. An artifact can have multiple file tags. For example, you can use the \a Group item to group files with the same file tags (or a set of properties). \code Product { Group { files: ["file1.cpp", "file2.cpp"] fileTags: ["cpp"] } Group { files: "mydsl_scanner.l" fileTags: ["flex", "foobar"] } // ... } \endcode When you load the \a cpp module, you also load the following item: \code FileTagger { patterns: "*.cpp" fileTags: ["cpp"] } \endcode This construct means that each source file that matches the pattern \c{*.cpp} (and has not explicitly set a file tag) gets the file tag \c{cpp}. The above example can be simplified to \code Product { Depends: "cpp" files: ["file1.cpp", "file2.cpp"] Group { files: "mydsl_scanner.l" fileTags: ["flex", "foobar"] } // ... } \endcode The \a FileTagger from the \a cpp module automatically assigns the \c cpp file tag to the source files. Groups that just contain the \a files property can be more simply expressed by using the \a files property of the product. File tags are used by \a rules to transform one type of artifact into another. For instance, the C++ compiler rule transforms artifacts with the file tag \c cpp to artifacts with the file tag \c{obj}. In addition, it is possible to use file taggers to tag files and specify custom file tags: \code Product { Depends: "cpp" Group { overrideTags: false // The overrideTags property defaults to true. fileTags: ["foobar"] files: ["main.cpp"] // Gets the file tag "cpp" through a FileTagger item and // "foobar" from this group's fileTags property. } // ... } \endcode \section1 Rules \QBS applies a \e rule to a pool of artifacts (in the beginning it is just the set of source files of the project) and chooses the ones that match the input file tags specified by the rule. Then it creates output artifacts in the build graph that have other filenames and file tags. It also creates a script that transforms the input artifact into the output artifact. For examples of rules, see the share/qbs/modules directory in the \QBS repository. You can define rules in your own module to be provided along with your project. Or you can put a rule directly into your project file. For more information, see \l{Rule Item}. */ /*! \contentspage index.html \previouspage language-introduction.html \page building-applications.html \nextpage running-applications.html \title Building Applications To build applications from the command line, enter the following commands: \code cd tests/manual/collidingmice qbs \endcode The application is built using the default build profile that is set up in your \QBS configuration. To build with other profiles, specify options for the build command. For example, to build debug and release configurations with a profile named "Android", enter the following command: \code qbs build profile:Android debug release \endcode The position of the property assignment is important. In the example above, the profile property is set for all build variants that come afterwards. To set a property just for one build variant, place the assignment after the build variant name. In the following example, the property \c cpp.treatWarningsAsErrors is set to \c true for debug only and \c cpp.optimization is set to \c small for release only. \code qbs build debug cpp.treatWarningsAsErrors:true release cpp.optimization:small \endcode */ /*! \contentspage index.html \previouspage running-applications.html \page installing-files.html \nextpage shell.html \title Installing Files To install your project, specify the necessary information in the project file: \code Application { Group { name: "Runtime resources" files: "*.qml" qbs.install: true qbs.installDir: "share/myproject" } Group { name: "The App itself" fileTagsFilter: "application" qbs.install: true qbs.installDir: "bin" } } \endcode In this example, we want to install a couple of QML files and an executable. The actual installation is then done like this (using the default profile): \code qbs --clean-install-root qbs.installRoot:/tmp/myProjectRoot \endcode Here, we want the installDir properties from the project file to be interpreted relative to the directory \c{/tmp/myProjectRoot}, and we want that directory to be removed first. If the \c{qbs.installRoot} property is not given, a default is used, namely \c{/install-root}. */ /*! \contentspage index.html \previouspage building-applications.html \page running-applications.html \nextpage installing-files.html \title Running Applications Running ./targets/debug/CollidingMice fails if Qt 4.8 is not in your PATH (in Windows) or LD_LIBRARY_PATH (in Linux). Therefore, enter the following command to run an application: \code qbs run --products CollidingMice \endcode This command also builds and installs the given product, if necessary. */ /*! \contentspage index.html \previouspage installing-files.html \page shell.html \nextpage custom-modules.html \title Using the Shell To use the \QBS shell, enter the following command: \code qbs shell \endcode This is mainly a debugging tool. It opens a shell with the same environment that qbs uses when building the project, so you can, for example, inspect which environment variables will be set up. */ /*! \contentspage index.html \previouspage shell.html \page custom-modules.html \nextpage reference.html \title Custom Modules and Items Users of \QBS are not limited to the pre-defined \l{List of Modules}{modules} and \l{List of Language Items}{items}, they can also create their own. Here we describe how to set up custom modules and items so that \QBS will find them. \section1 File System Layout Items and modules are located under a common base directory, whose name and location is completely arbitrary. We will refer to it as \c search-path here. This directory has two subdirectories \c modules and \c imports, which contain \QBS modules and items, respectively. \section1 Custom Modules To introduce a custom module \c mymodule, create a directory \c{search-path/modules/mymodule/}. \note Module names are case-sensitive, and this also goes for the corresponding directory name. Then, put a file containing an instance of the \l{Module Item} in there and give it the \c{.qbs} extension. This module will be pulled in if a \l{Product Item}{product} declares a \l{Depends Item}{dependency} on \c mymodule. \section1 Custom Items To introduce a custom item \c MyItem, create the file \c{search-path/imports/MyItem.qbs}. \section1 Making \QBS Aware of Custom Modules and Items To be able to use your custom modules and items, you need to make them known to \QBS. You can do this per project or globally. \section2 Project-specific Modules and Items Let's assume you have a project that is located in \c{project_dir} and you have created some modules in \c{project_dir/custom-stuff/modules/} as well as some items in \c{project_dir/custom-stuff/imports/} that you want to use in the project. To achieve this, your top-level project file should look like this: \code // ... Project { // .. qbsSearchPaths: "custom-stuff" // .. } \endcode \note For technical reasons, the custom modules and items will not be available in the file that contains the \c qbsSearchPaths property. Any product that wants to make use of them needs to be in a different file that is pulled in via the \c references property, for example. This is not a serious limitation, since every well-structured project will be split up in this manner. \section2 Making Custom Modules and Items Available Across Projects What if your modules and items are generally useful and you want to access them in several projects? In this case, it's best to add the location to your preferences. For example: \code qbs config preferences.qbsSearchPaths /usr/local/share/custom-qbs-extensions \endcode */ qbs-src-1.4.5/doc/qbs.qdocconf000066400000000000000000000001511266132464200161460ustar00rootroot00000000000000include(config/qbs-project.qdocconf) include($QT_INSTALL_DOCS/global/qt-html-templates-offline.qdocconf) qbs-src-1.4.5/doc/reference/000077500000000000000000000000001266132464200156045ustar00rootroot00000000000000qbs-src-1.4.5/doc/reference/commands.qdoc000066400000000000000000000173771266132464200202740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ // TODO: "\c" markup is used for all properties in table due to QTBUG-35505. /*! \contentspage reference.html \page commands.html \title Command and JavaScriptCommand \brief Types of commands to be used in rules and transformers A \e command is what \QBS executes at build time. It is represented in the language by an object of type \c Command, which runs a process, or \c JavaScriptCommand, which executes arbitrary JavaScript code. A command is always created in the prepare script of a \c Rule or \c Transformer. \section1 Command A \c Command represents a process that will be invoked at build time. Its constructor arguments are the binary to run and a list of command-line arguments. For instance: \code var insaneCommand = new Command("rm", ["-r", "/"]); \endcode The \l{Rule Item} documentation shows a \c Command in context. \section1 JavaScriptCommand A \c JavaScriptCommand represents a chunk of JavaScript code that is run at build time. For instance: \code var cmd = new JavaScriptCommand(); cmd.apology = "Sorry."; cmd.sourceCode = function() { print("I'm a rather pointless command."); print(apology); }; \endcode Within the source code, the special identifiers \c project and \c product (giving access to project and product properties, respectively) as well as \c inputs and \c outputs are available. As the example shows, arbitrary properties can be set on the command object and then used within the source code. This technique is typically used to forward values from the prepare script to the command. The \l{Transformer Item} documentation shows a \c JavaScriptCommand in context. \section1 Properties \section2 Common Properties The following properties are available in both \c Command and \c JavaScriptCommand. \table \header \li Property \li Type \li Default \li Description \row \li \c description \li string \li empty \li A message that is displayed when the command is executed. \row \li \c highlight \li string \li empty \li A tag that can be used to influence how the \c description is displayed. In principle, the values are arbitrary. The \QBS command-line tool understands the following values and maps them to different colors if the output device is a terminal: \list \li "compiler" indicates that the command processes source code \li "linker" indicates that the command links objects \li "codegen" indicates that the command generates source code \li "filegen" indicates that the command creates arbitrary files \endlist All other values are mapped to the default color. \row \li \c silent \li bool \li false \li A flag that controls whether the \c description is printed. Set it to \c true for commands that users need not know about. \note If this property is \c false, then \c description must not be empty. \endtable \section2 Command Properties \table \header \li Property \li Type \li Default \li Description \row \li \c arguments \li stringList \li empty \li The list of arguments to invoke the command with. Explicitly setting this property overrides an argument list provided when instantiating the object. \row \li \c environment \li stringList \li empty \li A list of environment variables that are added to the common build environment. They are provided as a list of strings in the form "varName=value". \row \li \c maxExitCode \li int \li 0 \li The maximum exit code from the process to interpret as success. Setting this should rarely be necessary, as all well-behaved applications use values other than zero to indicate failure. \row \li \c program \li string \li undefined \li The binary to invoke. Explicitly setting this property overrides a path provided when instantiating the object. \row \li \c responseFileThreshold \li int \li 32000 on Windows, -1 elsewhere \li If this value is greater than zero and less than the length of the full command line, and if \c responseFileUsagePrefix is not empty, the contents of the command line are moved to a temporary file, whose path becomes the entire contents of the argument list. The program is then supposed to read the full argument list from that file. This mechanism is mainly useful to work around Windows limitations regarding the maximum length of the command line and will only work with programs that explicitly support it. \row \li \c responseFileUsagePrefix \li string \li empty \li The prefix that informs \c program that the rest of the argument is a path to a file containing the actual command line. \row \li \c stderrFilterFunction \li function \li undefined \li A function that takes as input the command's actual standard error output and returns a string that is presented to the user as the command's standard error output. If it is not set, the output is shown unfiltered. \row \li \c stdoutFilterFunction \li function \li undefined \li A function that takes as input the command's actual standard output and returns a string that is presented to the user as the command's standard output. If it is not set, the output is shown unfiltered. \row \li \c workingDirectory \li string \li empty \li The program's working directory. \endtable \section2 JavaScriptCommand Properties \table \header \li Property \li Type \li Default \li Description \row \li \c sourceCode \li function \li undefined \li The JavaScript function to execute. \endtable */ qbs-src-1.4.5/doc/reference/items/000077500000000000000000000000001266132464200167255ustar00rootroot00000000000000qbs-src-1.4.5/doc/reference/items/androidapk.qdoc000066400000000000000000000077471266132464200217300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \page androidapk-item.html \nextpage application-item.html \ingroup list-of-items \title AndroidApk Item \brief Represents an Android application package. An \c AndroidApk item is a \c Product of type \e android.apk. It has a dependency on the \l{Module Android.sdk}{Android.sdk module}. The final build result is an Android application package (APK) file. Here is what the project file could look like for the BasicMediaDecoder example that comes with the Android SDK: \code import qbs AndroidApk { name: "Basic Media Decoder" packageName: "com.example.android.basicmediadecoder" property string sourcesPrefix: "Application/src/main/" resourcesDir: sourcesPrefix + "/res" sourcesDir: sourcesPrefix + "/java" manifestFile: sourcesPrefix + "/AndroidManifest.xml" } \endcode \section1 AndroidApk Properties The following properties are available in addition to the ones inherited from \c Product. \table \header \li Property \li Type \li Default \li Description \row \li assetsDir \li path \li \c "assets" \li The base directory for Android assets. \note Android requires that the file name of this directory is always "assets". \row \li automaticSources \li bool \li \c true \li If this is enabled, Java sources as well as Android resources, assets and the manifest file will be automatically included in the product via wildcards. Set this property to \c false if you want to specify these files manually. \row \li manifestFile \li path \li \c "AndroidManifest.xml" \li The file path to the Android manifest file. \note Android requires that the file name is always "AndroidManifest.xml". \row \li packageName \li string \li \c name \li The package name as given in the manifest file. \row \li resourcesDir \li path \li \c "res" \li The base directory for Android resources. \note Android requires that the file name of this directory is always "res". \row \li sourcesDir \li path \li \c "src" \li The base directory for Java sources. This property is only relevant if \c automaticSources is enabled. \endtable */ qbs-src-1.4.5/doc/reference/items/application.qdoc000066400000000000000000000040501266132464200220770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \page application-item.html \previouspage androidapk-item.html \nextpage applicationextension-item.html \ingroup list-of-items \title Application Item \brief Represents a product of application type. An \c Application item is a \c Product that has its type set to "application" It exists for the convenience of project file authors. \note On Android, an \c Application item instead builds a shared library for products whose \c consoleApplication property is set to \c false. */ qbs-src-1.4.5/doc/reference/items/applicationextension.qdoc000066400000000000000000000037521266132464200240440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \page applicationextension-item.html \previouspage application-item.html \nextpage artifact-item.html \ingroup list-of-items \title ApplicationExtension Item \brief Represents a product that is an OS X or iOS Application Extension. An \c ApplicationExtension item is a convenience item based on \c XPCService that sets some properties required for OS X and iOS Application Extensions. */ qbs-src-1.4.5/doc/reference/items/artifact.qdoc000066400000000000000000000054661266132464200214050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \page artifact-item.html \previouspage applicationextension-item.html \nextpage autotestrunner-item.html \ingroup list-of-items \title Artifact Item \brief Describes a file produced by a \c Rule or \c Transformer. An \c Artifact represents a single file produced by a \c Rule or \c Transformer. For example, if a rule produces three files, it needs to contain three Artifact items. \section1 Artifact Properties \table \header \li Property \li Type \li Default \li Description \row \li alwaysUpdated \li bool \li true \li Setting this to \c false means the file is not necessarily always written to by any command run by the rule. The timestamps of such artifacts are therefore not checked to find out whether they are up to date. Consequently, if all artifacts of a rule have this property set to \c false, the commands of the rule are always executed. \row \li filePath \li string \li undefined \li The file path of the target artifact. \row \li fileTags \li list \li empty list \li The tags to attach to the target file. These can then be matched by a rule. \endtable */ qbs-src-1.4.5/doc/reference/items/autotestrunner.qdoc000066400000000000000000000076331266132464200227100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \page autotestrunner-item.html \previouspage artifact-item.html \nextpage cppapplication-item.html \ingroup list-of-items \title AutotestRunner Item \brief A product that runs all autotests in the project. An \c AutotestRunner has a dependency to all products with the type "autotest". "Building" the \c AutotestRunner product will then run the respective executables. The \c builtByDefault property of an \c AutotestRunner is set to \c false by default, so running the autotests has to be explicitly requested. The default name of the product is "autotest-runner". To use this feature, do the following: \list A \li Attach the "autotest" type to your autotests: \code CppApplication { name: "tst_mytest" type: ["application", "autotest"] // ... } \endcode \li Instantiate exactly one \c AutotestRunner in your project, typically at the top level: \code Project { // ... AutotestRunner { } // ... } \endcode \li Trigger the autotest execution by "building" the product: \code qbs build -p autotest-runner \endcode \endlist \section1 AutotestRunner Properties \table \header \li Property \li Type \li Default \li Description \row \li arguments \li stringList \li empty \li The list of arguments to invoke the autotest with. \row \li environment \li stringList \li set internally \li A list of environment variables that are added to the run environment. They are provided as a list of strings in the form "varName=value". By default, DYLD_LIBRARY_PATH, DYLD_FRAMEWORK_PATH, and DYLD_ROOT_PATH are set on OS X and iOS, or an empty list for other platforms. \row \li limitToSubProject \li bool \li \c true \li By default, only those autotests are considered that are in the same sub-project that the \c AutotestRunner was instantiated in. If you want to run all autotests regardless of their location in the project hierarchy, set this property to \c false. \endtable */ qbs-src-1.4.5/doc/reference/items/cppapplication.qdoc000066400000000000000000000037131266132464200226070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \page cppapplication-item.html \previouspage autotestrunner-item.html \nextpage depends-item.html \ingroup list-of-items \title CppApplication Item \brief Represents a product of application type with a dependency to the cpp module. A \c CppApplication is a convenience item that is entirely equivalent to the following: \code Application { Depends { name: "cpp" } } \endcode */ qbs-src-1.4.5/doc/reference/items/depends.qdoc000066400000000000000000000112151266132464200212170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \previouspage cppapplication-item.html \page depends-item.html \nextpage dynamiclibrary-item.html \ingroup list-of-items \title Depends Item \brief Represents dependencies between products and modules. A \c Depends item can appear inside a \l{Product Item} or \l{Module Item}. For example, the following product will load the \c cpp module. In addition, it will try to load modules that may or may not exist, and in the latter case use a fallback. \code Product { Depends { name: "cpp" } Depends { name: "awesome_module" required: false } Depends { name: "adequate_module" condition: !awesome_module.present required: false } Depends { name: "crappy_module" condition: !awesome_module.present && !adequate_module.present } // ... } \endcode \section1 Depends Properties \table \header \li Property \li Type \li Default \li Description \row \li condition \li bool \li true \li Determines whether the dependency will actually be applied. \row \li productTypes \li stringList \li undefined \li A list of product types. Any enabled product in the project that has a matching type will become a dependency of the product containing the \c Depends item. This property is mutually exclusive with the \c name and \c submodules properties. The \c required and \c profiles properties are ignored if \c productTypes is set. \row \li required \li bool \li \c true \li Setting this property to \c false creates a \e{soft dependency}, meaning that it is not considered an error if the given module cannot be found. In such a case, an instance of the respective module will be created, but only the \c present property will be available for querying, and it will be set to \c false. \row \li name \li string \li undefined \li The name of the dependent product or module. \row \li profiles \li stringList \li \c{[product.profile]} \li If the dependency is on a product and that product is going to be built for more than one profile, then you can specify here which instance of the product the dependency is on. See the \c profiles property of the \c Product item for more information. An empty list means a dependency on all instances of the product with the given name, regardless of their profile. \row \li limitToSubProject \li bool \li \c false \li If \c productTypes is set and this property is \c true, then only products that are in the same sub-project as the product containing the \c Depends item are considered. \row \li submodules \li stringList \li undefined \li The submodules of \c module to depend on, if applicable. \endtable */ qbs-src-1.4.5/doc/reference/items/dynamiclibrary.qdoc000066400000000000000000000056231266132464200226140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \page dynamiclibrary-item.html \previouspage depends-item.html \nextpage export-item.html \ingroup list-of-items \title DynamicLibrary Item \brief Represents a product that is a dynamic library. A \c DynamicLibrary item is a \c Product that has its type set to "dynamiclibrary". It exists for the convenience of project file authors. For Android targets, the following applies: \list \li The product type contains "android.nativelibrary" in addition to "dynamiclibrary". \li There is a dependency on the \l{Module cpp}{cpp} and \l{Module Android.ndk}{Android.ndk} modules. \endlist \section1 DynamicLibrary Properties The following properties are available in addition to the ones inherited from \c Product. \table \header \li Property \li Type \li Default \li Description \row \li architectures \li stringList \li see below \li This property is only relevant for Android targets. There, it specifies for which architectures to build, with the default value \c{["armeabi"]}. This information influences the \c profiles property. \row \li bundleExtension \li string \li empty \li The extension to use for the product's bundle. Only relevant on Darwin systems. \endtable */ qbs-src-1.4.5/doc/reference/items/export.qdoc000066400000000000000000000057111266132464200211220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \previouspage dynamiclibrary-item.html \page export-item.html \nextpage filetagger-item.html \ingroup list-of-items \title Export Item \brief Exports dependencies and properties to other products. An \c Export item can appear inside a \l{Product Item}. It defines a Module with the product's name that can be depended on by other products. The properties attached to the Export item will take effect in all products that depend on the product inside which the Export item is defined. As an example, consider these two products: \code Product { name: "A" Export { Depends { name: "cpp" } cpp.includePaths: product.sourceDirectory cpp.defines: ["USING_" + product.name.toUpperCase()] } } Product { name: "B" Depends { name: "A" } } \endcode The sources in product B will be able to use headers from product A without specifiying the full path to them, because the include path has been made known to the compiler via A's Export item. Additionally, product B will be compiled with the define \c{USING_A}. \note This relationship is transitive, so a product C depending on product B will also get the include paths and preprocessor macros via A's Export item. In contrast to Module items, \c{product} within Export items refers to the product which defines the Export item. */ qbs-src-1.4.5/doc/reference/items/filetagger.qdoc000066400000000000000000000063451266132464200217160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \previouspage export-item.html \page filetagger-item.html \nextpage group-item.html \ingroup list-of-items \title FileTagger Item \brief Maps file patterns to tags. This item maps file patterns to tags. It can be attached to a product or a module. In the latter case, its effect is the same as if it had been attached to all products having a dependency on the respective module. For instance, the cpp module of \QBS has, among others, the following file tagger: \code FileTagger { patterns: "*.cpp" fileTags: ["cpp"] } \endcode As a result, the "cpp" tag is automatically attached to all files ending with ".cpp" in products depending on the cpp module. This causes them to be compiled, because a C++ compiler rule has "cpp" in its list of matching input tags. File taggers are disabled if file tags are set explicitly in a product or group. For example, the "cpp" tag is not attached to the cpp files in the following product: \code Product { Depends { name: "cpp" } Group { files: "*.cpp" fileTags: "other" } } \endcode \section1 FileTagger Properties \table \header \li Property \li Type \li Default \li Description \row \li patterns \li stringList \li none \li The patterns to match against. Supports the usual wildcards '*', '?' and '[]'. Neither the list itself nor any of its elements may be empty. \row \li fileTags \li list \li empty list \li Tags to attach to a product's files. These can then be matched by a rule. \endtable */ qbs-src-1.4.5/doc/reference/items/group.qbs000066400000000000000000000034671266132464200206020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs 1.0 Project { Product { //! [0] Group { name: "Word processing documents" files: ["*.doc", "*.rtf"] prefix: "**/" qbs.install: true qbs.installDir: "share" excludeFiles: "do_not_install_this_file.*" } //! [0] } } qbs-src-1.4.5/doc/reference/items/group.qdoc000066400000000000000000000126211266132464200207330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \previouspage filetagger-item.html \page group-item.html \nextpage installpackage-item.html \ingroup list-of-items \title Group Item \brief Groups files in a product. This item is attached to a product and used to group files that have something in common. For example: \code Application { Group { name: "common files" files: ["myclass.h", "myclass_common_impl.cpp"] } Group { name: "Windows files" condition: targetOS.contains("windows") files: "myclass_win_impl.cpp" } Group { name: "Linux files" condition: targetOS.contains("linux") files: "myclass_linux_impl.cpp" } Group { name: "Files to install" qbs.install: true qbs.installDir: "share" files: "runtime_resource.txt" } } \endcode When specifying files, you can use the wildcards "*", "?" and "[]", which have their usual meaning. By default, matching files are only picked up directly from the parent directory, but you can tell \QBS to consider the whole directory tree. It is also possible to exclude certain files from the list. The pattern ** used in a pathname expansion context will match all files and zero or more directories and subdirectories. For example: \snippet reference/items/group.qbs 0 A group can also be used to attach properties to build artifacts such as executables or libraries. In the following example, an application is installed to "/bin". \code Application { Group { fileTagsFilter: "application" qbs.install: true qbs.installDir: "bin" } } \endcode Groups may also appear in modules, which causes the respective sources to be added to the products depending on said module. \section1 Group Properties \table \header \li Property \li Type \li Default \li Description \row \li name \li string \li "Group x", where x is a unique number among all the groups in the product \li The name of the group. Not used internally; mainly useful for IDEs. \row \li files \li list \li empty list \li The files in the group. Mutually exclusive with fileTagsFilter. \row \li prefix \li string \li empty string \li A string to prepend to all files. Slashes are allowed and have directory semantics. \row \li fileTagsFilter \li list \li empty list \li Artifact file tags to match. Any properties set in this group will be applied to the product's artifacts whose file tags intersect with the ones listed here. Mutually exclusive with files. \row \li condition \li bool \li true \li Determines whether the files in the group are actually considered part of the project. \row \li fileTags \li list \li empty list \li Tags to attach to the group's files. These can then be matched by a rule. Note that file taggers are never applied to a file that has this property set. \row \li overrideTags \li bool \li true \li Determines how tags on files that are listed both at the top level of a product and a group are handled. If this property is true, then the file tags set via the group replace the ones set via the product. If it is false, the "group tags" are added to the "product tags". \row \li excludeFiles \li list \li empty list \li For use with wildcards; the files in this list are "subtracted" from the files list. \endtable */ qbs-src-1.4.5/doc/reference/items/installpackage.qdoc000066400000000000000000000061061266132464200225620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/licensing. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \page installpackage-item.html \previouspage group-item.html \nextpage javaclasscollection-item.html \ingroup list-of-items \title InstallPackage Item \brief Represents an archive of an installed project. An \c InstallPackage item is a product of type \c{archiver.archive}. It is used to produce an archive from a set of installable files via the \l{Module archiver}{archiver Module}. Consider the following example project: \code Project { CppApplication { name: "myapp" Depends { name: "mylib" } files: ["main.cpp"] Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "bin" } } DynamicLibrary { name: "mylib" files: ["mylib.cpp"] Group { name: "public headers" files: ["mylib.h"] qbs.install: true qbs.installDir: "include" } Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "lib" } } InstallPackage { archiver.type: "tar" name: "tar-package" Depends { name: "myapp" } Depends { name: "mylib" } } } \endcode Building the product "tar-package" on a Unix system will result in a tar file with these contents: \code include/mylib.h lib/libmylib.so bin/myapp \endcode */ qbs-src-1.4.5/doc/reference/items/javaclasscollection.qdoc000066400000000000000000000040621266132464200236220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \page javaclasscollection-item.html \previouspage installpackage-item.html \nextpage javajarfile-item.html \ingroup list-of-items \title JavaClassCollection Item \brief Represents a collection of Java class files not bundled in a jar file. A \c JavaClassCollection item is a convenience item that has a dependency on the \l{Module java}{Java module} and whose type is \c{["java.class"]}. If the files should end up in a jar file, you should use a \l{JavaJarFile Item}{JavaJarFile} instead. */ qbs-src-1.4.5/doc/reference/items/javajarfile.qdoc000066400000000000000000000042361266132464200220600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \page javajarfile-item.html \previouspage javaclasscollection-item.html \nextpage loadablemodule-item.html \ingroup list-of-items \title JavaJarFile Item \brief Represents a collection of Java class files bundled in a jar file. A \c JavaJarCollection item is product of type \c{java.jar}. It is used to produce a jar archive from a set of Java sources. \table \header \li Property \li Type \li Default \li Description \row \li entryPoint \li string \li undefined \li The entry point for an executable jar file. \endtable */ qbs-src-1.4.5/doc/reference/items/loadablemodule.qdoc000066400000000000000000000036731266132464200225570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \page loadablemodule-item.html \previouspage javajarfile-item.html \nextpage module-item.html \ingroup list-of-items \title LoadableModule Item \brief Represents a product that is a loadable module. A \c LoadableModule item is a \c Product that has its type set to "loadablemodule". It exists for the convenience of project file authors. */ qbs-src-1.4.5/doc/reference/items/module.qdoc000066400000000000000000000166721266132464200210760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \previouspage loadablemodule-item.html \page module-item.html \nextpage probe-item.html \ingroup list-of-items \title Module Item \brief Represents a collection of properties and items that can be loaded into a product. A \c Module item is a collection of properties and language items that are used for building a product if the product has a \l{Depends Item}{dependency} on the module. The following (somewhat artificial) module pre-processes text files by removing certain characters from them: \code import qbs import qbs.FileInfo import qbs.TextFile Module { property stringList unwantedCharacters: [] FileTagger { patterns: ["*.raw"] fileTags: ["raw-txt"] } Rule { inputs: ["raw-txt"] Artifact { filePath: FileInfo.relativePath(input.filePath, product.sourceDirectory) + "/" + input.fileName + ".processed" fileTags: ["processed-txt"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Processing " + input.fileName; cmd.sourceCode = function() { var inFile = new TextFile(input.filePath, TextFile.ReadOnly); var content = inFile.readAll(); inFile.close(); var unwantedChars = product.moduleProperty("txt_processor", "unwantedCharacters"); for (var c in unwantedChars) content = content.replace(unwantedChars[c], ""); var outFile = new TextFile(output.filePath, TextFile.WriteOnly); outFile.write(content); outFile.close(); }; return cmd; } } } \endcode And this is how a product would use the module: \code Product { type: "processed-txt" Depends { name: "txt_processor" } txt_processor.unwantedCharacters: ["\r"] files: [ "file1.raw", "file2.raw" ] } \endcode Of course, normally the pre-processed files would not be the target artifacts of the product, but rather serve as inputs to a different rule that will often come from a different module. How you make your own modules available to \QBS is explained \l{Custom Modules and Items}{here}. \section1 Special Property Values For every property defined in a module, \QBS provides the following special built-in values: \section2 \c base This value is useful when making use of inheritance. It stands for the value of the respective property in the item one level up in the inheritance chain. For instance: \code Product { // defined in MyProduct.qbs Depends { name: "mymodule" } mymodule.someProperty: ["value1"] } ------ some other file ------ MyProduct { mymodule.someProperty: base.concat(["value2"]) // => ["value1", "value2"] } \endcode \section2 \c original This is the value of the property in the module itself (possibly overridden from a profile or the command line). Use it to set a module property conditionally: \code Module { // This is mymodule property string aProperty: "z" } ---------- Product { Depends { name: "mymodule" } Depends { name: "myothermodule" } mymodule.aProperty: myothermodule.anotherProperty === "x" ? "y" : original // => "y" if myothermodule.anotherProperty is "x", "z" otherwise \endcode \section2 \c outer This value is used in nested items, where it refers to the value of the respective property in the surrounding item. It is often encountered in \l{Group Item}{groups}: \code Product { Depends { name: "mymodule" } mymodule.someProperty: ["value1"] Group { name: "special files" files: ["somefile1", "somefile2"] mymodule.someProperty: outer.concat(["value"]) // => ["value1", "value2"] } } \endcode \section1 Module Properties \table \header \li Property \li Type \li Default \li Description \row \li additionalProductTypes \li string list \li empty list \li The elements of this list will be added to the \c type property of a product that has a dependency on the module. \row \li condition \li bool \li \c true \li Controls whether the module is enabled. If this property is \c false, the surrounding \c Module item will not be considered in the module look-up. \row \li present \li bool \li \c true \li This property is read-only. Its value is \c false if and only if the respective \c Depends item had its \c required property set to \c false and the module was not found. \row \li setupBuildEnvironment \li script \li \c undefined \li Script for setting up the environment in which the project is built. Use the \c putEnv, \c getEnv, and \c unsetEnv functions to alter the environment. The return value of this script is ignored. \row \li setupRunEnvironment \li script \li \c setupBuildEnvironment \li Script for setting up the environment in which the project is run. \row \li validate \li script \li \c undefined \li Script that is run after the module is loaded. It can be used to check property values and throw errors in unexpected cases. The return value is ignored. \endtable */ qbs-src-1.4.5/doc/reference/items/probe.qdoc000066400000000000000000000050571266132464200207130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \previouspage module-item.html \page probe-item.html \nextpage product-item.html \ingroup list-of-items \title Probe Item \brief Locates files outside the project. A \c Probe item can appear inside a \l{Product Item} and is run prior to building products in order to locate dependent headers, libraries, and other files outside the project directory whose locations are not known ahead of time. \c Probes are similar to configure scripts. \section1 Probe Properties \table \header \li Property \li Type \li Default \li Description \row \li condition \li bool \li true \li Determines whether the probe will actually be run. \row \li found \li bool \li undefined \li Indicates whether the probe was run successfully. Set by \c configure. \row \li configure \li script \li undefined \li Script that is executed when the probe is run. \endtable */ qbs-src-1.4.5/doc/reference/items/product.qdoc000066400000000000000000000173321266132464200212630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \previouspage probe-item.html \page product-item.html \nextpage project-item.html \ingroup list-of-items \title Product Item \brief Represents the result of a build process. A \e product typically represents the result of a build process. It specifies a set of input and output files and a way to transform the former into the latter. For example, the following product sets up a very simple C++ application: \code Product { name: "helloworld" type: "application" files: "main.cpp" Depends { name: "cpp" } } \endcode The \c type property specifies what will be built (an executable). The \c files property specifies the input files (one C++ source file), and the \c Depends item pulls in the logic from the \c cpp module about how to do the necessary transformations. For some often-used types of products, \QBS pre-defines special derived items that save users some typing. These are: \list \li Application \li CppApplication \li DynamicLibrary \li StaticLibrary \endlist Therefore, the above example could also be written like this: \code CppApplication { name: "helloworld" files: "main.cpp" } \endcode Any property \c prop attached to this item is available in sub-items as \c product.prop, as well as in modules that are loaded from this product. \table \header \li Property \li Type \li Default \li Description \row \li builtByDefault \li bool \li true \li If false, the product will only be built if this is explicitly requested, either by listing the product name as an argument to \c --products or by giving the \c build command the \c --all-products option. \row \li condition \li bool \li true \li If false, the product will not be built. \row \li name \li string \li empty string \li The name of the product. Used to identify the product in a \c Depends item, for example. The value of this property must be a simple JavaScript expression that does not depend on module properties or values that are non-local to this product. \code CppApplication { name: "hello" + "world" // valid } CppApplication { name: "app_for_" + qbs.targetOS.join("_") // invalid } \endcode To change the name of your product's target artifact, modify \c{Product.targetName} instead. \row \li profiles \li stringList \li \c{[project.profile]} \li The profiles for which the product should be built. For each profile listed here, one instance of the product will be built according to the properties set in the respective profile. This property is only relevant for projects that require products being built for different architectures. Otherwise it can be left at its default value. \row \li type \li stringList \li empty list \li The file tags matching the product's target artifacts. \row \li targetName \li string \li \c{name} with illegal file name characters replaced by underscores \li The base file name of the product's target artifacts. \row \li destinationDirectory \li string \li product.buildDirectory \li The directory where the target artifacts will be located. If a relative path is given, the base directory will be \c project.buildDirectory. \row \li files \li stringList \li empty list \li A list of source files. Syntactic sugar to save a \c Group item for simple products. \row \li excludeFiles \li stringList \li empty list \li A list of source files not to include. Useful with wildcards. For more information, see \l {Group Item}. \row \li consoleApplication \li bool \li linker-dependent \li If true, a console application is generated. If false, a GUI application is generated. Only takes effect on Windows. This property also influences the default application type on OS X and iOS. If true, an application bundle is generated. If false, a normal executable is generated. \row \li qbsSearchPaths \li stringList \li project.qbsSearchPaths \li See the documentation of the \l {Project Item} property of the same name. The value set here will be merged with the one inherited from the project. \row \li version \li string \li undefined \li The version number of the product. Used in shared library filenames and generated Info.plist files in OS X and iOS application and framework bundles, for example. \endtable The following properties are automatically set by \QBS and cannot be changed by the user: \table \header \li Property \li Type \li Description \row \li buildDirectory \li path \li The build directory for this product. This is the directory where generated files are placed. \row \li profile \li string \li The profile for building this particular instance of the product. Derived automatically from the \c profiles property. \row \li sourceDirectory \li path \li The source directory for this product. This is the directory of the file where this product is defined. \endtable */ qbs-src-1.4.5/doc/reference/items/project.qdoc000066400000000000000000000110061266132464200212410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \previouspage product-item.html \page project-item.html \nextpage properties-item.html \ingroup list-of-items \title Project Item \brief Represents a collection of products and properties. A \c Project item represents a collection of of products. In a non-trivial project, these products are typically defined in their own files and referenced in the main project file: \code Project { references: [ "product1/product1.qbs", "product2/product2.qbs" ] } \endcode Any property \c prop attached to this item is available in sub-items as \c project.prop. While the root of the item hierarchy is always a \c Project, this kind of item can also appear further down the hierarchy. Such sub-projects are ususally introduced to group products. See the \l{SubProject Item} for details. \note If your project consists of only one product, the \c Project item can be omitted. \table \header \li Property \li Type \li Default \li Description \row \li buildDirectory \li path \li n/a \li The build directory of the top-level project. This property is read-only. \row \li name \li string \li basename of the file the project is defined in \li The project name. Only relevant for e.g. displaying a project tree in an IDE. \row \li profile \li string \li n/a \li The top-level profile for building the project. This property is read-only and is set by \QBS when the project is being set up. \row \li condition \li bool \li true \li Whether the project is enabled. If false, no products or sub-projects will be collected. \row \li qbsSearchPaths \li stringList \li empty \li These paths are searched for imports and modules in addition to the ones listed in \c{preferences.qbsSearchPaths}. The value set here is merged with the value inherited from the parent project, if there is one. The result is inherited by all products in the project. \row \li references \li path list \li empty \li A list of files from which to import products. This is equivalent to defining the respective \c Product items directly under this \c Project item. \row \li sourceDirectory \li path \li n/a \li The directory where the file containing the top-level \c Project item is located. This property is read-only. \row \li minimumQbsVersion \li string \li "1.3.0" \li The minimum version of qbs that is needed to build this project. \endtable */ qbs-src-1.4.5/doc/reference/items/properties.qdoc000066400000000000000000000077571266132464200220110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \previouspage project-item.html \page properties-item.html \nextpage propertyoptions-item.html \ingroup list-of-items \title Properties Item \brief Provides conditional setting of properties. \note This documents the \c Properties item in the context of products. Usage within a \c SubProject item is described \l{SubProject Item}{here}. The \c Properties item is an auxiliary item for setting multiple property values conditionally. In the following example, two properties are set if the project is built for Windows: \code Product { Properties { condition: qbs.targetOS.contains("windows") cpp.defines: ["ON_WINDOWS"] cpp.includePaths: ["extraWindowsIncludes"] } } \endcode Multiple \c Properties items can be specified to set properties dependent on different conditions. The order of appearance is important. Semantics are similar to if-else-chains. The following example \code Product { Properties { condition: qbs.targetOS.contains("windows") cpp.defines: ["ON_WINDOWS"] cpp.includePaths: ["myWindowsIncludes"] } Properties { condition: qbs.targetOS.contains("linux") cpp.defines: ["ON_LINUX"] cpp.includePaths: ["myLinuxIncludes"] } cpp.defines: ["ON_UNKNOWN_PLATFORM"] } \endcode is equivalent to \code Product { cpp.defines: { if (qbs.targetOS.contains("windows")) return ["ON_WINDOWS"]; if (qbs.targetOS.contains("linux")) return ["ON_LINUX"]; return ["ON_UNKNOWN_PLATFORM"]; } cpp.includePaths: { if (qbs.targetOS.contains("windows")) return ["myWindowsIncludes"]; if (qbs.targetOS.contains("linux")) return ["myLinuxIncludes"]; return base; } } \endcode We suggest to use the \c Properties item for mutually exclusive conditions only. It is especially useful if there are several properties to set, based on the same condition. \table \header \li Property \li Type \li Default \li Description \row \li condition \li bool \li none - must be specified \li The condition to be used for the other bindings in this item. \endtable */ qbs-src-1.4.5/doc/reference/items/propertyoptions.qdoc000066400000000000000000000050221266132464200230740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \previouspage properties-item.html \page propertyoptions-item.html \nextpage qtapplication-item.html \ingroup list-of-items \title PropertyOptions Item \brief Provides inline documentation for properties within product and module items. A \c PropertyOptions item can appear inside a \l{Product Item} or \l{Module Item} to provide inline documentation for properties. \section1 PropertyOptions Properties \table \header \li Property \li Type \li Default \li Description \row \li allowedValues \li stringList \li undefined \li A list of the values permitted by the property. \c{undefined} indicates that any value is permitted. \row \li description \li string \li undefined \li A brief description of the property. \row \li name \li string \li undefined \li The name of the property to document. \endtable */ qbs-src-1.4.5/doc/reference/items/qtapplication.qdoc000066400000000000000000000037441266132464200224550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \page qtapplication-item.html \previouspage propertyoptions-item.html \nextpage qtguiapplication-item.html \ingroup list-of-items \title QtApplication Item \brief Represents a product of application type with a dependency to the Qt Core module. A \c QtApplication is a convenience item that is entirely equivalent to the following: \code CppApplication { Depends { name: "Qt.core" } } } \endcode */ qbs-src-1.4.5/doc/reference/items/qtguiapplication.qdoc000066400000000000000000000046031266132464200231550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \page qtguiapplication-item.html \previouspage propertyoptions-item.html \nextpage rule-item.html \ingroup list-of-items \title QtGuiApplication Item \brief Represents a product of application type with a dependency to the Qt GUI module. A \c QtGuiApplication is a convenience item that extends the \c QtApplication item by loading the \c Qt.gui module and possibly also the default QPA plugin. \section1 QtGuiApplication Properties \table \header \li Property \li Type \li Default \li Description \row \li linkDefaultQpaPlugin \li bool \li Qt.core.staticBuild == true \li Whether or not to add a depencency to the default QPA plugin. The default is to do that in the case of a static build, where it is normally required. \endtable */ qbs-src-1.4.5/doc/reference/items/rule.qdoc000066400000000000000000000166271266132464200205600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \previouspage qtapplication-item.html \page rule-item.html \nextpage staticlibrary-item.html \ingroup list-of-items \title Rule Item \brief Creates transformers for input tags. A \e {multiplex rule} creates one \e transformer that takes all input artifacts with the matching input file tag and creates one or more artifacts (e.g. C++ linker). A \e {simplex rule} creates one transformer per matching input file (e.g. C++ compiler). As a real-world example of a simplex rule, here is a simplified version of \QBS' rule for transforming C++ sources into object files using gcc: \code Rule { id: compiler inputs: ['cpp'] auxiliaryInputs: ['hpp'] Artifact { fileTags: ['obj'] filePath: '.obj/' + qbs.getHash(input.baseDir) + '/' + input.fileName + '.o' } prepare: { var args = []; if (product.moduleProperty('cpp', 'debugInformation')) args.push('-g'); var warnings = product.moduleProperty('cpp', 'warningLevel') if (warnings === 'none') args.push('-w'); if (warnings === 'all') { args.push('-Wall'); args.push('-Wextra'); } if (product.moduleProperty('cpp', 'treatWarningsAsErrors')) args.push('-Werror'); var includePaths = product.moduleProperties('cpp', 'includePaths'); for (i in includePaths) args.push('-I' + includePaths[i]); var defines = product.moduleProperties('cpp', 'defines'); for (i in defines) args.push('-D' + defines[i]); args.push('-c'); args.push(input.filePath); args.push('-o'); args.push(output.filePath); var compilerPath = ModUtils.moduleProperty(product, 'compilerPath'); var cmd = new Command(compilerPath, args); cmd.description = 'compiling ' + input.fileName; cmd.highlight = 'compiler'; return cmd; } } \endcode \section1 Rule Properties \table \header \li Property \li Type \li Default \li Description \row \li multiplex \li bool \li false \li Determines whether this is a multiplex rule. \row \li inputs \li string list \li undefined \li File tags the input artifacts must match. All output artifacts will depend on all artifacts in the product with the given input file tags. Also these artifacts are available in the inputs variable of the prepare script. \row \li auxiliaryInputs \li string list \li undefined \li A list of file tags. This rule will be dependent on every other rule and transformer that produces artifacts that are compatible with \a{auxiliaryInputs}. Unlike \a{inputs}, the property \a{auxiliaryInputs} has no effect on the content of the \a{inputs} variable in the \a{prepare} script. \row \li excludedAuxiliaryInputs \li string list \li undefined \li A list of file tags. Connections to rules that produce these file tags are prevented. This property has no effect on the content of the \a{inputs} variable in the \a{prepare} script. \row \li inputsFromDependencies \li string list \li undefined \li File tags the artifacts of product dependencies must match. For example, the product \a foo might appear as follows in the current product: \code Depends { name: "foo" } \endcode All artifacts of \a foo that match the given file tags will appear in the \a inputs variable of the prepare script. Also, each output artifact of this rule will be dependent on those artifacts. \row \li outputArtifacts \li array of objects \li undefined \li An array of output artifacts, specified as JavaScript objects. Example: \code outputArtifacts: [{filePath: "myfile.txt", fileTags: ["foo", "bar"]}] \endcode For a description of the possible properties, see the documentation of the Artifact item. Output artifacts can be specified either by \c{Rule.outputArtifacts} or by \c{Artifact} items. Use \c{Rule.outputArtifacts} if the set of outputs is not fixed but dependent on the input's content. The user may set the property \c{explicitlyDependsOn} on artifact objects, which is similar to \c{Rule.explicitlyDependsOn}. \row \li outputFileTags \li string list \li undefined \li If output artifacts are specified by \c{Rule.outputArtifacts}, then \c{Rule.outputFileTags} must be a list of file tags the rule potentially produces. \row \li condition \li bool \li true \li If true, the rule is enabled, otherwise it does nothing. \row \li explicitlyDependsOn \li string list \li undefined \li Each artifact that matches the file tags in \a explicitlyDependsOn is added to the dependencies of each output node. \row \li prepare \li script \li undefined \li Script that prepares the commands to transform the inputs to outputs. The code in this script is treated as a function with the signature \c{function(project, product, inputs, outputs, input, output)}. The argument \c{input} is \c{undefined} if there's more than one input artifact for this rule. Similarly, \c{output} is only defined if there's exactly one output artifact. \endtable */ qbs-src-1.4.5/doc/reference/items/scanner.qdoc000066400000000000000000000063521266132464200212340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \page scanner-item.html \ingroup list-of-items \title Scanner Item \brief Creates custom dependency scanners in modules. An \c Scanner item can appear inside a \l{Module Item}, and allows to define artifacts dependency, according to the artifacts contents. For example scanner for "qrc" files: \code import qbs.Xml Module { Scanner { condition: true inputs: 'qrc' scan: { xml = XmlDomDocument(input.fileName); dependencies = []; // do something with the xml return dependencies; } } } \endcode \section1 Scanner Properties \table \header \li Property \li Type \li Default \li Description \row \li condition \li bool \li true \li If true, the scanner is enabled, otherwise it does nothing. \row \li inputs \li string list \li undefined \li File tags the input artifacts must match. \row \li recursive \li bool \li false \li Determines whether to scan dependencies recursively. \row \li searchPaths \li script \li undefined \li Script that returns paths to look for dependencies. The code in this script is treated as a function with the signature \c{function(project, product, input)}. \row \li scan \li script \li undefined \li Script that reads the input artifact and returns string list with dependencies. The code in this script is treated as a function with the signature \c{function(project, product, input)}. \endtable */ qbs-src-1.4.5/doc/reference/items/staticlibrary.qdoc000066400000000000000000000045351266132464200224600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \page staticlibrary-item.html \previouspage rule-item.html \nextpage subproject-item.html \ingroup list-of-items \title StaticLibrary Item \brief Represents a product that is a static library. A \c StaticLibrary item is a convenience item that is normally entirely equivalent to the following: \code Product { type: "staticlibrary" } \endcode For Android targets, the following applies: \list \li There is a dependency on the \l{Module cpp}{cpp} and \l{Module Android.ndk}{Android.ndk} modules. \li There is an additional list property "architectures" that specifies for which architectures to build, with the default value \c{["armeabi"]}. This information influences the \c profiles property. \endlist */ qbs-src-1.4.5/doc/reference/items/subproject.qdoc000066400000000000000000000057321266132464200217640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \previouspage staticlibrary-item.html \page subproject-item.html \nextpage transformer-item.html \ingroup list-of-items \title SubProject Item \brief Adds a project from a different file. A \c SubProject item is used to add a project defined in another file as a sub-project to the surrounding project: \code SubProject { filePath: "subdir/project.qbs" Properties { name: "A sub-project" } } \endcode If you don't need to set any properties on the sub-project, you can also use the \c references property, the same way you would do for a product: \code references: "subdir/project.qbs" \endcode It is also possible to nest \c Project items directly in the same file. \table \header \li Property \li Type \li Default \li Description \row \li filePath \li path \li empty \li The file path of the project to add as a sub-project. If the top-level item in this file is a \c Product, it gets wrapped automatically in a new project. \row \li inheritProperties \li bool \li true \li Whether the sub-project should inherit the properties of the surrounding project. You can use this feature to share "global" settings between (sub-)projects. \endtable */ qbs-src-1.4.5/doc/reference/items/transformer.qdoc000066400000000000000000000101051266132464200221340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \page transformer-item.html \previouspage subproject-item.html \nextpage xpcservice-item.html \ingroup list-of-items \title Transformer Item \brief Creates files, typically from other files. A \e transformer takes zero or more inputs and produces one or more output artifacts from them. The following transformer creates one output file from one input file: \code Transformer { inputs: "raw_input.txt" Artifact { filePath: "processed_input.txt" fileTags: "processed_file" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Processing '" + input.filePath + "'"; cmd.highlight = "codegen"; cmd.sourceCode = function() { var file = new TextFile(input.filePath); var content = file.readAll(); file.close() content = content.replace(/\r\n/g, "\n"); file = new TextFile(output.filePath, TextFile.WriteOnly); file.truncate(); file.write(content); file.close(); } return cmd; } } \endcode This example exhibits some interesting features of transformers: \list \li If there is only one input file, the property \c input is available as syntactic sugar for \c inputs[0]. \li The filenames of the output artifacts are available as \c outputs. If there is only one of these, it can be referred to it as \c output. \endlist A \c Transformer is always attached to a \c Product, possibly indirectly via a \c Module. \section1 Transformer Properties \table \header \li Property \li Type \li Default \li Description \row \li inputs \li stringList \li empty list \li The list of inputs to the transformer. \row \li prepare \li list of Javascript commands \li empty list \li The commands that the transformer runs. These typically read from the input files and write to the output files in some way. \row \li condition \li bool \li true \li If true, the transformer is enabled, otherwise it does nothing. \row \li explicitlyDependsOn \li stringList \li \c{undefined} \li A list of file tags. All output artifacts of this transformer will have a dependency to all artifacts with the given file tags. \endtable */ qbs-src-1.4.5/doc/reference/items/xpcservice.qdoc000066400000000000000000000036301266132464200217520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-items.html \page xpcservice-item.html \previouspage transformer-item.html \ingroup list-of-items \title XPCService Item \brief Represents a product that is an OS X or iOS XPC service. An \c XPCService item is a convenience item based on \c Application that sets some properties required for OS X and iOS XPC services. */ qbs-src-1.4.5/doc/reference/jsextensions/000077500000000000000000000000001266132464200203405ustar00rootroot00000000000000qbs-src-1.4.5/doc/reference/jsextensions/jsextension-file.qdoc000066400000000000000000000064501266132464200245030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage index.html \page jsextension-file.html \ingroup list-of-builtin-services \title File Service \brief Provides operations on the file system. The \c File service offers limited access to the file system for operations such as copying or removing files. \section1 Available Operations \section2 copy \code File.copy(sourceFilePath: string, targetFilePath: string): boolean \endcode Copies \c sourceFilePath to \c targetFilePath. Any directory components in \c targetFilePath that do not yet exist will be created. If \c sourceFilePath is a directory, a recursive copy will be made. If an error occurs, a JavaScript exception will be thrown. \note \c targetFilePath must be the counterpart of \c sourceFilePath at the new location, \b{not} the new parent directory. This allows the copy to have a different name and is true even if \c sourceFilePath is a directory. \section2 exists \code File.exists(filePath: string): boolean \endcode Returns true if and only if there is a file at \c filePath. \section2 lastModified \code File.lastModified(filePath: string): number \endcode Returns the time of last modification for the file at \c filePath. The concrete semantics of the returned value are platform-specific. You should only rely on the property that a smaller value indicates an older timestamp. \section2 makePath \code File.makePath(path: string): boolean \endcode Makes the directory at \c path, creating intermediate directories if necessary. Conceptually equivalent to \c{mkdir -p} \section2 remove \code File.remove(filePath: string): boolean \endcode Removes the file at \c filePath. In case of a directory, it will be removed recursively. */ qbs-src-1.4.5/doc/reference/jsextensions/jsextension-fileinfo.qdoc000066400000000000000000000076731266132464200253670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage index.html \page jsextension-fileinfo.html \ingroup list-of-builtin-services \title FileInfo Service \brief Provides operations on file paths. The \c FileInfo service offers various operations on file paths, such as turning absolute paths into relative ones, splitting a path into its components, and so on. \section1 Available Operations \section2 baseName \code FileInfo.baseName(filePath: string): string \endcode Returns the file name of \c filePath up to (but not including) the first '.' character. \section2 completeBaseName \code FileInfo.completeBaseName(filePath: string): string \endcode Returns the file name of \c filePath up to (but not including) the last '.' character. \section2 fileName \code FileInfo.fileName(filePath: string): string \endcode Returns the last component of \c filePath, that is, everything after the last '/' character. \section2 fromWindowsSeparators \code FileInfo.fromWindowsSeparators(filePath: string): string \endcode Returns \c filePath with all '\\' characters replaced by '/'. \section2 isAbsolutePath \code FileInfo.isAbsolutePath(filePath: string): boolean \endcode Returns true if \c filePath is an absolute path and false if it is a relative one. \section2 joinPaths \code FileInfo.joinPaths(...paths: string[]): string \endcode Concatenates the given paths using the '/' character. \section2 path \code FileInfo.path(filePath: string): string \endcode Returns the part of \c filePath that is not the file name, that is, everything up to (but not including) the last '/' character. If \c filePath is just a file name, then '.' is returned. If \c filePath ends with a '/' character, then the file name is assumed to be empty for the purpose of the above definition. \section2 relativePath \code FileInfo.relativePath(dirPath: string, filePath: string): string \endcode Returns a relative path so that joining \c dirPath and the returned path results in \c filePath. If necessary, '..' components are inserted. The function assumes \c dirPath and \c filePath to be absolute paths and \c dirPath to be a directory. \section2 toWindowsSeparators \code FileInfo.toWindowsSeparators(filePath: string): string \endcode Returns \c filePath with all '/' characters replaced by '\\'. */ qbs-src-1.4.5/doc/reference/jsextensions/jsextension-process.qdoc000066400000000000000000000134601266132464200252410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage index.html \page jsextension-process.html \ingroup list-of-builtin-services \title Process Service \brief Allows you to start external processes. The \c Process service allows you to start processes, track their output, and so on. \section1 Available Operations \section2 Constructor \code Process() \endcode Allocates and returns a new Process object. \section2 close \code close(): void \endcode Frees the resources associated with the process. It is recommended to always call this function as soon as you are finished with the process. \section2 exec \code exec(filePath: string, arguments: string[], throwOnError: boolean): number \endcode Executes the program at \c filePath with the given argument list and blocks until the process is finished. If an error occurs (for example, there is no executable file at \c filePath) and \c throwOnError is true, then a JavaScript exception will be thrown. Otherwise (the default), -1 will be returned in case of an error. The normal return code is the exit code of the process. \section2 exitCode \code exitCode(): number \endcode Returns the exit code of the process. This is needed for retrieving the exit code from processes started via \c start(), rather than \c exec(). \section2 getEnv \code getEnv(varName: string): string \endcode Returns the value of the variable \c varName in the process' environment. \section2 kill \code kill(): void \endcode Kills the process, causing it to exit immediately. \section2 readLine \code readLine(): string \endcode Reads and returns one line of text from the process output, without the newline character(s). \section2 readStdErr \code readStdErr(): string \endcode Reads and returns all data from the process' standard error channel. \section2 readStdOut \code readStdOut(): string \endcode Reads and returns all data from the process' standard output channel. \section2 setCodec \code setCodec(codec) \endcode Sets the text codec to \c codec. The codec is used for reading and writing from and to the process, respectively. The supported codecs are the same as for \c QTextCodec, for example: "UTF-8", "UTF-16", and "ISO 8859-1". \section2 setEnv \code setEnv(varName: string, varValue: string): string \endcode Sets the value of variable \c varName to \c varValue in the process environment. This only has an effect if called before the process is started. \section2 setWorkingDirectory \code setWorkingDirectory(path: string): void \endcode Sets the directory the process will be started in. This only has an effect if called before the process is started. \section2 start \code start(filePath: string, arguments: string[]): boolean \endcode Starts the program at \c filePath with the given list of arguments. Returns \c{true} if the process could be started and \c{false} otherwise. \note This call returns right after starting the process and should be used only if you need to interact with the process while it is running. Most of the time, you want to use \c exec() instead. \section2 terminate \code terminate(): void \endcode Tries to terminate the process. This is not guaranteed to make the process exit immediately; if you need that, use \c kill(). \section2 waitForFinished \code waitForFinished(timeout: number): boolean \endcode Blocks until the process has finished or \c timeout milliseconds have passed (default is 30000). Returns true if the process has finished and false if the operation has timed out. Calling this function only makes sense for processes started via \c start() (as opposed to \c exec()). \section2 workingDirectory \code workingDirectory(): string \endcode Returns the directory the process will be started in. \section2 write \code write(data: string): void \endcode Writes \c data into the process' input channel. \section2 writeLine \code writeLine(data: string): void \endcode Writes \c data, followed by the newline character(s), into the process' input channel. */ qbs-src-1.4.5/doc/reference/jsextensions/jsextension-propertylist.qdoc000066400000000000000000000120651266132464200263430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage index.html \page jsextension-propertylist.html \ingroup list-of-builtin-services \title PropertyList Service \brief Provides read, write and convert operations on property list files. The \c PropertyList service allows you to read and write property list files in all formats supported by the Core Foundation API: XML, binary, JSON, and OpenStep (read-only). This service is only available on Darwin platforms such as OS X and iOS. \section1 Available operations \section2 Constructor \code PropertyList() \endcode Allocates and returns a new PropertyList object. \section2 clear \code clear(): void \endcode Voids the property list by deleting its internal object reference. \section2 isEmpty \code isEmpty(): boolean \endcode Returns true if the property list has no internal object reference set, otherwise false. \section2 format \code format(): string \endcode Returns the data format that the property list data was deserialized from. This property is set after calling \c readFromString or \c readFromFile. Possible return values include: \c "binary1", \c "json", \c "openstep", and \c "xml1". If the property list object is empty or the input format could not be determined, returns \c undefined. \section2 readFromFile \code readFromFile(filePath: string): void \endcode Parses the file and stores the result in the property list. Throws an exception if an I/O error occurs or the input is in an invalid format. \section2 readFromObject \code readFromObject(obj: any): void \endcode Sets the given object as the property list's internal object. \c format() will return \c undefined as this method does not deserialize a storage format. \section2 readFromString \code readFromString(input: string): void \endcode Parses \c input and stores the result in the property list. This is most useful for initializing a property list object from the result of a \c JSON.stringify call. Throws an exception if the input is in an invalid format. \section2 toObject \code toObject(): any \endcode Returns an object representing the property list. \section2 toJSON \code toJSON(style: string = "compact"): string \endcode Returns a string representation of the property list in JSON format. Possible values for \c style include \c "pretty" and \c "compact". The default is compact. \section2 toString \code toString(format: string): string \endcode Returns a string representation of the property list in the specified format. Possible values for \c format include: \c "json" (compact), \c "json-compact", \c "json-pretty", and \c "xml1". Currently, the OpenStep format is not supported. Throws an exception if the object cannot be written in the given format. \section2 toXMLString \code toXMLString(): string \endcode Returns a string representation of the property list in XML format. This function is a synonym for \c toString("xml1"). \section2 writeToFile \code writeToFile(filePath: string, format: string): void \endcode Writes the property list to the file in the given format. Possible values for \c format include: \c "binary1", \c "json" (compact), \c "json-compact", \c "json-pretty", and \c "xml1". Currently, the OpenStep format is not supported for writing. Throws an exception if an I/O error occurs or the object cannot be written in the given format. */ qbs-src-1.4.5/doc/reference/jsextensions/jsextension-temporarydir.qdoc000066400000000000000000000050711266132464200263030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage index.html \page jsextension-temporarydir.html \ingroup list-of-builtin-services \title TemporaryDir Service \brief Creates a unique directory for temporary use. The \c PropertyList service creates a unique directory for temporary use. \section1 Available Operations \section2 Constructor \code TemporaryDir() \endcode Allocates and returns a new TemporaryDir object. This method creates the temporary directory. \section2 isValid \code isValid(): boolean \endcode Returns \c true if the temporary directory was created successfully. \section2 path \code path(): string \endcode Returns the path to the temporary directory. Empty if the temporary directory could not be created. \section2 remove \code remove(): boolean \endcode Removes the temporary directory, including all its contents. Returns \c true if removing was successful. It is recommended to always call this function as soon as you are finished with the temporary directory. */ qbs-src-1.4.5/doc/reference/jsextensions/jsextension-textfile.qdoc000066400000000000000000000072651266132464200254150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage index.html \page jsextension-textfile.html \ingroup list-of-builtin-services \title TextFile Service \brief Provides read and write operations on text files. The \c TextFile service allows you to read from and write into text files. \section1 Related Declarations \section2 TextFile.OpenMode \code enum TextFile.OpenMode { ReadOnly, WriteOnly, ReadWrite } \endcode List of modes that a file may be opened in. \section1 Available operations \section2 Constructor \code TextFile(filePath: string, openMode: OpenMode = TextFile.ReadOnly) \endcode Opens the file at \c filePath in the given mode and returns the object representing the file. \note The mode influences which of the operations listed below can actually be used on the file. \section2 atEof \code atEof(): boolean \endcode Returns \c{true} if no more data can be read from the file, \c{false} otherwise. \section2 close \code close(): void \endcode Closes the file. It is recommended to always call this function as soon as you are finished with the file, in order to keep the number of in-flight file descriptors as low as possible. \section2 readAll \code readAll(): string \endcode Reads all data from the file and returns it. \section2 readLine \code readLine(): string \endcode Reads one line of text from the file and returns it. The returned string does not contain the newline characters. \section2 setCodec \code setCodec(codec: string): void \endcode Sets the text codec to \c codec. The supported codecs are the same as for \c QTextCodec, for example: "UTF-8", "UTF-16", and "ISO 8859-1". \section2 truncate \code truncate(): void \endcode Truncates the file, that is, gives it the size of zero, removing all content. \section2 write \code write(data: string): void \endcode Writes \c data into the file at the current position. \section2 writeLine \code writeLine(data: string): void \endcode Writes \c data into the file at the current position and appends the newline character(s). */ qbs-src-1.4.5/doc/reference/jsextensions/jsextensions-general.qdoc000066400000000000000000000115421266132464200253620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage index.html \page jsextensions-general.html \ingroup list-of-builtin-services \title General Services \brief Provides various operations. These are operations that do not fit into any of the other categories. They are automatically available in any \QBS project file or JavaScript file. \section1 Available Operations \section2 qbs.currentEnv \code qbs.currentEnv(): { [key: string]: string; } \endcode Returns the environment of \QBS in the current context as an object whose properties are the environment variables. \section2 qbs.getEnv \code qbs.getEnv(key: string): string \endcode Tries to find a variable with the given name in the build environment and returns its value. If no such variable could be found, \c undefined is returned. \section2 qbs.getHash \code qbs.getHash(key: string): string \endcode Calculates a 16-byte hash of the input and returns it. Rules in modules should use this function to find unique locations for output artifacts in the build directory without duplicating the whole directory structure of the respective input file (to deal with the case of two files with the same name in different subdirectories of the same product). \section2 qbs.rfc1034Identifier \code qbs.rfc1034Identifier(str: string): string \endcode Returns an RFC 1034 compliant identifier based on the given string by replacing each character that is not Latin alphanumeric or \c{.} with \c{-}. \section2 loadFile \code loadFile(filePath: string): any \endcode Loads a JavaScript file and returns an object that contains the evaluated context of this file. This function is only available in JavaScript files. For example: \code var MyFunctions = loadFile("myfunctions.js"); MyFunctions.doSomething(); \endcode \section2 loadExtension \code loadExtension(extensionName: string): any \endcode Loads a \QBS extension and returns an object that contains all functions of that extension. This function is only available in JavaScript files. For example: \code var FileInfo = loadExtension("qbs.FileInfo"); var fileName = FileInfo.fileName(filePath); \endcode \section1 Extensions to JavaScript Built-in Objects \section2 Array.contains \code Array.contains(e: any): boolean \endcode Returns \c{true} if the array contains the element \c{e}. Returns \c{false} otherwise. \section2 Array.uniqueConcat \code Array.uniqueConcat(other: any[]): any[] \endcode Returns a copy of this array joined with the array \c{other}. Duplicates that would originate from the concatenation are removed. The order of elements is preserved. \section2 String.contains \code String.contains(s: string): boolean \endcode Returns \c{true} if the string contains the substring \c{s}. Returns \c{false} otherwise. \section2 startsWith \code String.startsWith(s: string): boolean \endcode Returns \c{true} if the string starts with the substring \c{s}. Returns \c{false} otherwise. \section2 endsWith \code String.endsWith(s: string): boolean \endcode Returns \c{true} if the string ends with the substring \c{s}. Returns \c{false} otherwise. */ qbs-src-1.4.5/doc/reference/list-of-tools.qdoc000066400000000000000000000051511266132464200211710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage reference.html \page list-of-tools.html \title List of Command-line Tools \brief Auxiliary tools In addition to the \c qbs command itself, a number of auxiliary tools are provided. Their file names follow the pattern \c{qbs-}, and they can be invoked either using that file name or as \c{qbs }. This page is intended to give a short overview of these tools. For the supported parameters, see the respective help screen, which you get by calling \c{qbs help }. \section1 config Manages \QBS settings like preferences and profiles. \section1 config-ui Like \c config, but with a graphical user interface. \section1 qmltypes Dumps information about the QML types supplied by \QBS. This is not intended as documentation for users, but as tooling support. \section1 setup-android Creates \QBS profiles for Android SDK and NDK installations. \section1 setup-qt Creates \QBS profiles for Qt installations. \section1 setup-toolchains Creates \QBS profiles for toolchains like GCC or MSVC. */ qbs-src-1.4.5/doc/reference/modules/000077500000000000000000000000001266132464200172545ustar00rootroot00000000000000qbs-src-1.4.5/doc/reference/modules/android-ndk-module.qdoc000066400000000000000000000101541266132464200236020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage index.html \page android-ndk-module.html \ingroup list-of-modules \title Module Android.ndk \since 1.4 \brief Provides support for building native Android libraries. The \c Android.ndk module contains the properties and rules to create native libraries for use in \l{AndroidApk Item}{Android application packages}. Normally, you will not use this module directly, but instead work with the \l{DynamicLibrary Item}{DynamicLibrary} and \l{StaticLibrary Item}{StaticLibrary} items that \QBS provides. Here is what the project file for the "hello-jni" example that comes with the NDK could look like: \code import qbs Project { DynamicLibrary { name: "hello-jni" architectures: ["mips", "x86"] files: ["jni/hello-jni.c"] } AndroidApk { name: "HelloJni" packageName: "com.example.hellojni" Depends { productTypes: ["android.nativelibrary"] } } } \endcode \section1 Android.ndk Properties These properties are set automatically when creating an Android profile via the \c setup-android tool. \table \header \li Property \li Type \li Since \li Default \li Description \row \li abi \li string \li 1.4 \li undefined \li The ABI name as it appears under "lib/" in the application package. Corresponds to APP_ABI in Android.mk. \row \li appStl \li string \li 1.4 \li \c{"system"} \li The library to use for C++. The possible values are: "system", "gabi++_static", "gabi++_shared", "stlport_static", "stlport_shared", "gnustl_static", "gnustl_shared", "c++_static", "c++_shared". \row \li hardFloat \li bool \li 1.4.2 \li undefined \li Whether to use the hard floating point variant of the armeabi-v7a ABI. \row \li enableExceptions \li bool \li 1.4 \li \c{appStl !== "system"} \li Whether to enable exceptions in C++ code. \row \li enableRtti \li bool \li 1.4 \li \c{appStl !== "system"} \li Whether to enable runtime type information in C++ code. \row \li ndkDir \li path \li 1.4 \li undefined \li The NDK base directory. \row \li platform \li string \li 1.4 \li \c{"android-9"} \li The versioned platform name. \endtable */ qbs-src-1.4.5/doc/reference/modules/android-sdk-module.qdoc000066400000000000000000000057721266132464200236210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage index.html \page android-sdk-module.html \ingroup list-of-modules \title Module Android.sdk \since 1.4 \brief Provides support for building Android packages. The \c Android.sdk module contains the properties and rules to create Android application packages from Java sources, resources and so on. Normally, you will not use this module directly, but instead work with the \l{AndroidApk Item}{AndroidApk item} that \QBS provides. \section1 Android.sdk Properties These properties are set automatically when creating an Android profile via the \c setup-android tool. \table \header \li Property \li Type \li Since \li Default \li Description \row \li buildToolsVersion \li string \li 1.4 \li undefined \li The version of the build tools such as aapt and dx. The \c setup-android tool sets this to the highest version available in the SDK. \row \li ndkDir \li string \li 1.4 \li undefined \li The NDK base directory, if an NDK is present. \row \li platform \li string \li 1.4 \li undefined \li The versioned platform name (e.g. "android-21"). The \c setup-android tool sets this to the highest version available in the SDK. \row \li sdkDir \li string \li 1.4 \li undefined \li The SDK base directory. \endtable */ qbs-src-1.4.5/doc/reference/modules/archiver-module.qdoc000066400000000000000000000102031266132464200232060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/licensing. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage index.html \page archiver-module.html \ingroup list-of-modules \title Module archiver \since 1.4 \brief Provides support for building archives. The \c archiver module contains the properties and rules for creating (compressed) archives. The output artifact has the file tag "archiver.archive". The sole input artifact is a text file containing the list of files to package, with one file path per line. The paths can be relative, in which case they will be looked for at \c{archiver.workingDirectory}. The file tag of this input artifact is "archiver.input-list". \section1 archiver Properties \table \header \li Property \li Type \li Since \li Default \li Description \row \li flags \li stringList \li 1.4 \li empty list \li Custom options not covered by any of the other properties. \row \li archiveBaseName \li string \li 1.4 \li \c{product.targetName} \li The base name of the archive file (in other words, the file name without any extensions). \row \li compressionLevel \li string \li 1.4 \li \c undefined \li How much effort to put into the compression of a 7-Zip or zip archive. Possible values are \c undefined, "0", "1", "2", "3", "4", "5", "6", "7", "8" and "9" Higher numbers result in a smaller archive, but the compressing process will take more time. 7-Zip only supports 0 and odd numbers. A value of \c undefined means to use the default compression level. \row \li compressionType \li string \li 1.4 \li \c{"gz"} for tar archives, otherwise \c undefined \li How to compress a tar or zip archive. Possible options are "none", "gz", "bz2", "Z", "xz", "deflate", "store". \c undefined uses the archiver's default compression type. \row \li outputDirectory \li string \li 1.4 \li \c{product.destinationDirectory} \li Where to put the archive file. \row \li type \li string \li 1.4 \li \c{undefined} \li Which kind of archiver to use. The currently supported values are: "tar", "7zip", "zip". \row \li workingDirectory \li string \li 1.4 \li undefined \li The directory in which to execute \c command. \row \li command \li string \li 1.4 \li Depends on \c{type}. \li The command with which to invoke the archiver. \endtable */ qbs-src-1.4.5/doc/reference/modules/bundle-module.qdoc000066400000000000000000000273651266132464200226750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage index.html \page bundle-module.html \ingroup list-of-modules \title Module bundle \since 1.4 \brief Provides Core Foundation bundle support. The \c bundle module contains properties and rules for building and working with Core Foundation bundles on Apple platforms (commonly known as CFBundles or simply "bundles"), directories with a standardized hierarchical structure that hold executable code and resources. Examples include applications, frameworks, and plugins. This module is available on all platforms but is currently only useful on Apple platforms. \note Core Foundation bundles are not to be confused with Mach-O loadable modules, which are also referred to as (loadable) "bundles" in Apple parlance. In \QBS, Core Foundation bundles are referred to as "bundles", while Mach-O loadable bundles are referred to as "loadable modules". \section1 General Properties \table \header \li Property \li Type \li Since \li Default \li Description \row \li isBundle \li \c{bool} \li 1.4 \li \c{true} for applications and dynamic libraries on Apple platforms, \c{false} otherwise \li Whether the product should actually be packaged as a bundle as opposed to a flat file. This allows a product indirectly dependent on the \c{bundle} module to retain control of whether it should actually be built as a bundle. \row \li isShallow \li \c{bool} \li 1.4 \li \c{true} for iOS applications \li Whether the bundle directory tree is "shallow", i.e. whether it lacks a Contents subdirectory. This is the default for iOS applications and should normally never be changed. \row \li identifierPrefix \li \c{string} \li 1.4 \li \c{org.example} \li Prefix for the product's bundle identifier. If \c{identifier} is left unset, the bundle identifier will be a concatenation of this value and the \c{identifier} property, separated by a '.'. This corresponds to the organization identifier in Xcode. \row \li identifier \li \c{string} \li 1.4 \li combination of \c{identifierPrefix} and the product's target name formatted as an RFC 1034 identifier \li The bundle's identifier. If left unset, the bundle identifier will be a concatenation of this value and the \c{identifierPrefix} property, separated by a '.'. \row \li extension \li \c{string} \li 1.4 \li \c{"app"} for \c{"APPL"} packages, \c{"framework"} for \c{"FMWK"} packages, \c{"bundle"} for \c{"BNDL"} and custom packages \li The extension of the bundle's wrapper directory (minus the leading '.'). This property should not normally need to be set unless creating a custom bundle type. \row \li packageType \li \c{string} \li 1.4 \li \c{"APPL"} for applications, \c{"FMWK"} for frameworks, \c{"BNDL"} for custom bundles \li The four-letter file type code of the bundle, specified in the bundle's PkgInfo file and in the bundle's Info.plist as the value for the CFBundlePackageType key. This property should almost never need to be changed, though specifying an alternative package type for custom bundles is allowed. \row \li signature \li \c{string} \li 1.4 \li \c{"????"} \li The four-letter signature specific to the bundle, also known as the creator code, specified in the bundle's PkgInfo file and in the bundle's Info.plist as the value for the CFBundleSignature key. This property should normally never need to be set. \row \li bundleName \li \c{string} \li 1.4 \li combination of the product's \c{targetName} and bundle's \c{extension} \li The file name of the bundle's wrapper directory. This property should not normally need to be changed. \row \li frameworkVersion \li \c{string} \li 1.4 \li \c{"A"} \li For framework bundles, the version of the framework. Unused for other package types. \row \li publicHeaders \li \c{pathList} \li 1.4 \li \c{undefined} \li List of public header files to copy to a framework bundle's Headers subdirectory. \row \li privateHeaders \li \c{pathList} \li 1.4 \li \c{undefined} \li List of private header files to copy to a framework bundle's PrivateHeaders subdirectory \row \li resources \li \c{pathList} \li 1.4 \li \c{undefined} \li List of resources to copy to a bundle's Resources subdirectory. Files will automatically be copied into lproj subdirectories corresponding to the input files' paths. \row \li infoPlistFile \li \c{path} \li 1.4 \li \c{undefined} \li Path to the Info.plist file used by the bundle. The contents of this file will be aggregated with the values in \c{infoPlist}. If \c{infoPlistFile} and \c{infoPlist} contain the same key, the latter will take precedence, but may also be overridden during postprocessing (see \c{processInfoPlist}). If undefined, will not be taken into account. \row \li infoPlist \li \c{object} \li 1.4 \li \c{undefined} \li Dictionary of key-value pairs to add to the bundle's Info.plist. The contents of this property will be aggregated with the values from \c{infoPlistFile}. If \c{infoPlist} and \c{infoPlistFile} contain the same key, the former will take precedence, but may also be overridden during postprocessing (see \c{processInfoPlist}). If undefined, will not be taken into account. \row \li processInfoPlist \li \c{bool} \li 1.4 \li \c{true} \li Whether to perform post-processing on the aggregated Info.plist contents. If this property is \c{true}, various post-processing operations will be applied to the bundle's property list dictionary after it has been aggregated from the contents of the file specified by the \c{infoPlistFile} property and the \c{infoPlist} property. First, values from a list of defaults will be added to the dictionary if they were not already present. Then, values from the AdditionalInfo key of the platform SDK's Info.plist file will be added to the dictionary if they were not already present, as well as some other miscellaneous keys, such as BuildMachineOSBuild and UIDeviceFamily (on iOS). Finally, variable expansions will be performed such that substrings of the form $(VAR) or ${VAR} will be replaced with their corresponding environment variables. \row \li embedInfoPlist \li \c{bool} \li 1.4 \li \c{true} if the product is a command line tool, otherwise \c{false}. \li Whether to create a __TEXT section in the product's executable containing the processed Info.plist. Only applies to command line applications. \row \li infoPlistFormat \li \c{string} \li 1.4 \li \c{"binary1"} for iOS; \c{"same-as-input"} or \c{"xml1"} for OS X depending on whether \c{infoPlistFile} is specified; undefined for all other operating systems. \li The file format to write the product's resulting Info.plist in. Possible values: \c{"xml1"}, \c{"binary1"}, \c{"json"}, \c{"same-as-input"} \endtable \section1 Path Specific Properties All properties in this section are read-only properties of type \c{string} specifying file paths relative to the directory containing the bundle. \table \header \li Property \li Since \li Description \row \li infoPlistPath \li 1.4 \li Path that the Info.plist file will be written to. If \c{embedInfoPlist} is \c{true}, this will point to a file in a temporary directory. \row \li infoPlistPath \li 1.4 \li Path that the PkgInfo file will be written to. \row \li versionPlistPath \li 1.4 \li Path that the version.plist file will be written to. \row \li executablePath \li 1.4 \li Path that the main executable file will be written to. \row \li executableFolderPath \li 1.4 \li Path of the directory where the main exectuable will be written. Not to be confused with \c{executablesFolderPath}. \row \li executablesFolderPath \li 1.4 \li Path of the directory where auxiliary executables will be copied. Not to be confused with \c{executableFolderPath}. \row \li frameworksFolderPath \li 1.4 \li Path of the directory where internal frameworks will be copied. \row \li pluginsFolderPath \li 1.4 \li Path of the directory where plugins will be copied. \row \li privateHeadersFolderPath \li 1.4 \li Path of the directory where private header files will be copied. \row \li publicHeadersFolderPath \li 1.4 \li Path of the directory where public headers files will be copied. \row \li scriptsFolderPath \li 1.4 \li Path of the directory where script files will be copied. \row \li sharedFrameworksFolderPath \li 1.4 \li Path of the directory where shared frameworks will be copied. \row \li sharedSupportFolderPath \li 1.4 \li Path of the directory where shared support files will be copied. \row \li unlocalizedResourcesFolderPath \li 1.4 \li Path of the directory where non-localized resource files will be copied. This is the same as the base resources path. \row \li contentsFolderPath \li 1.4 \li Path of the bundle's Contents subdirectory. \endtable */ qbs-src-1.4.5/doc/reference/modules/cpp-module.qdoc000066400000000000000000000501641266132464200221770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage index.html \page cpp-module.html \ingroup list-of-modules \title Module cpp \since 1.0 \brief Provides C/C++ support. The \c cpp module contains the properties and rules for toolchains of the C/C++ family. On OS X this includes support for Objective-C/C++. \section1 General Properties \table \header \li Property \li Type \li Since \li Default \li Description \row \li allowUnresolvedSymbols \li \c{bool} \li 1.2 \li \c{false} \li Switch this on if you want the linking step to succeed even if the resulting binary contains unresolved symbols. Normally this makes little sense, but in special cases it is possible that the respective symbols will be available at load time even if they are not present during linking. \row \li architecture \li \c{string} \li 1.0 \li \c{qbs.architecture} \li Target architecture. See \c{qbs.architecture}. \row \li debugInformation \li \c{bool} \li 1.0 \li \c{qbs.debugInformation} \li Generate debug information. See \c{qbs.debugInformation}. \row \li separateDebugInformation \li \c{bool} \li 1.4 \li \c{false} for gcc/clang, \c{true} for MSVC \li Whether to store debug information in an external file or bundle instead of within the binary. \row \li defines \li \c{stringList} \li 1.0 \li \c{undefined} \li List of preprocessor macros that gets passed to the compiler. To set macro values use the following syntax: \c{cpp.defines: ["USE_COLORS=1", 'COLOR_STR="blanched almond"']} \row \li platformDefines \li \c{stringList} \li 1.0 \li \c{undefined} \li List of preprocessor macros that are used for all projects that are built for the current target platform. User project files usually do not set this property. \row \li compilerDefines \li \c{stringList} \li 1.0 \li \c{undefined} \li List of preprocessor macros that are used for all projects that are using the current toolchain. User project files usually do not set this property. \row \li includePaths \li \c{pathList} \li 1.0 \li \c{undefined} \li List of include paths. Relative paths are considered to be relative to the .qbs product file they are used in. \row \li systemIncludePaths \li \c{pathList} \li 1.0 \li \c{undefined} \li List of include paths that are passed as system include paths to the compiler. For header files in those paths warnings will be ignored. Relative paths are considered to be relative to the .qbs product file they are used in. \row \li libraryPaths \li \c{pathList} \li 1.0 \li \c{undefined} \li List of library search paths. Relative paths are considered to be relative to the .qbs product file they are used in. \row \li dynamicLibraries \li \c{stringList} \li 1.0 \li \c{undefined} \li List of dynamic libraries to be linked. If the library is part of your project, consider using a Depends item instead. \row \li staticLibraries \li \c{stringList} \li 1.0 \li \c{undefined} \li List of static libraries to be linked. If the library is part of your project, consider using a Depends item instead. \row \li prefixHeaders \li \c{pathList} \li 1.0.1 \li \c{undefined} \li List of files to automatically include at the beginning of each source file in the product. \row \li precompiledHeader \li \c{path} \li 1.0 \li \c{undefined} \li Name of the header file to be precompiled. If you want to use the same precompiled header for all languages (C, C++, Objective-C and Objective-C++), set this property and ensure that the header contains appropriate ifdefs. Otherwise, use the \c{cPrecompiledHeader}, \c{cppPrecompiledHeader}, \c{objcPrecompiledHeader} and \c{objcppPrecompiledHeader} to specify precompiled headers per-language. \row \li cPrecompiledHeader \li \c{path} \li 1.1 \li \c{precompiledHeader} \li Name of the C header file to be precompiled. \row \li cxxPrecompiledHeader \li \c{path} \li 1.1 \li \c{precompiledHeader} \li Name of the C++ header file to be precompiled. \row \li objcPrecompiledHeader \li \c{path} \li 1.1 \li \c{precompiledHeader} \li Name of the Objective-C header file to be precompiled. \row \li objcxxPrecompiledHeader \li \c{path} \li 1.1 \li \c{precompiledHeader} \li Name of the Objective-C++ header file to be precompiled. \row \li precompiledHeaderDir \li \c{path} \li 1.0 \li \c{product.buildDirectory} \li The directory that will contain the precompiled header files. Usually you won't need to set this. \row \li optimization \li \c{string} \li 1.0 \li \c{qbs.optimization} \li Optimization level. See \c{qbs.optimization}. \row \li treatWarningsAsErrors \li \c{bool} \li 1.0 \li \c{false} \li Warnings will be handled as errors and cause the build to fail. \row \li warningLevel \li \c{string} \li 1.0 \li \c{"all"} \li Specifies the warning level for the compiler - \c{"none"} or \c{"all"}. \row \li commonCompilerFlags \li \c{stringList} \li 1.0.1 \li undefined \li Flags that are added to all compilation commands independently of the language. \row \li compilerVersionMajor \li \c{int} \li 1.4 \li undefined \li The major version of the compiler. \row \li compilerVersionMinor \li \c{int} \li 1.4 \li undefined \li The minor version of the compiler. \row \li compilerVersionPatch \li \c{int} \li 1.4 \li undefined \li The patch level component of the compiler version. \row \li cppFlags \li \c{stringList} \li 1.0 \li undefined \li Additional flags for the C preprocessor. \row \li cFlags \li \c{stringList} \li 1.0 \li undefined \li Additional flags for the C compiler. \row \li cxxFlags \li \c{stringList} \li 1.0 \li undefined \li Additional flags for the C++ compiler. \row \li cLanguageVersion \li \c{string} \li 1.4 \li undefined \li The version of the C standard with which the code must comply. If this property is set, corresponding compiler and/or linker flags will be added, depending on the toolchain. If the value is left undefined, the compiler default will be used. Possible values include: \c{"c89"}, \c{"c99"}, \c{"c11"} \row \li cxxLanguageVersion \li \c{string} \li 1.4 \li undefined \li The version of the C++ standard with which the code must comply. If this property is set, corresponding compiler and/or linker flags will be added, depending on the toolchain. If the value is left undefined, the compiler default will be used. Possible values include: \c{"c++98"}, \c{"c++11"}, \c{"c++14"} \row \li cxxStandardLibrary \li \c{string} \li 1.4 \li undefined \li The C++ standard library to link to. If this property is set, corresponding compiler and/or linker flags will be added, assuming the value is valid for the current toolchain. If the value is left undefined, the compiler default will be used. Possible values include: \c{"libstdc++"}, \c{"libc++"} \row \li objcFlags \li \c{stringList} \li 1.0 \li undefined \li Additional flags for the Objective-C compiler. \row \li objcxxFlags \li \c{stringList} \li 1.0 \li undefined \li Additional flags for the Objective-C++ compiler. \row \li linkerFlags \li \c{stringList} \li 1.0 \li undefined \li Additional flags for the linker. \row \li linkerScripts \li \c{pathList} \li 1.2 \li \c{undefined} \li List of linker script files. \row \li compilerName \li \c{string} \li 1.0 \li determined by qbs-setup-toolchains \li Name of the main compiler binary. This is set in the build profile. \row \li compilerPath \li \c{string} \li 1.0 \li determined by qbs-setup-toolchains \li Full path of the main compiler binary. This is set in the build profile. If the toolchain provides different compilers for different languages, then \c{compilerPathByLanguage} is used. \row \li compilerPathByLanguage \li \c{string} to \c{string} map \li 1.3 \li determined by qbs-setup-toolchains \li Maps file tags to full paths of compiler binaries. This is set in the build profile. \row \li compilerWrapper \li \c{stringList} \li 1.1 \li \c{undefined} \li Wrapper binary and its arguments for wrapping compiler calls. This is useful for compiler wrappers like ccache and alike. \row \li linkerName \li \c{string} \li 1.1.1 \li determined by qbs-setup-toolchains \li Name of the linker binary. This is set in the build profile. \row \li linkerPath \li \c{string} \li 1.1.1 \li determined by qbs-setup-toolchains \li Full path of the linker binary. This is set in the build profile. \row \li entryPoint \li \c{string} \li 1.3 \li \c{undefined} \li Name of the entry point of an executable or dynamic library. If this property is undefined, the toolchain's default is used. \row \li runtimeLibrary \li \c{string} \li 1.3.3 \li \c{"dynamic"} for MSVC, \c{undefined} for others \li Type of the used runtime library. Accepted values are \c{"static"} and \c{"dynamic"}. If this property is set to \c{undefined}, then the default runtime library of the toolchain is used. \note For MSVC the default value is \c{"dynamic"}. \note At the moment this property is only functional for MSVC. \endtable \section1 Properties Specific to Apple Platforms \table \header \li Property \li Type \li Since \li Default \li Description \row \li frameworkPaths \li \c{pathList} \li 1.0 \li \c{undefined} \li List of framework search paths. Relative paths are considered to be relative to the .qbs product file they are used in. \row \li systemFrameworkPaths \li \c{pathList} \li 1.0 \li \c{undefined} \li List of framework search paths. Relative paths are considered to be relative to the .qbs product file they are used in. Header files in frameworks in those paths will not cause warnings. \row \li frameworks \li \c{stringList} \li 1.0 \li \c{undefined} \li List of frameworks to be linked. If the framework is part of your project, consider using a Depends item instead. \row \li weakFrameworks \li \c{stringList} \li 1.0 \li \c{undefined} \li List of frameworks to be weakly linked. If the framework is part of your project, consider using a Depends item instead. \row \li installNamePrefix \li \c{string} \li 1.0 \li \c{undefined} \li The prefix for the internal install name (LC_ID_DYLIB) of a dynamic library on Darwin (OS X and iOS). Typically this should be set to \c{"@rpath"} on modern platforms that support it, which includes OS X 10.5 and above, and all versions of iOS. \row \li automaticReferenceCounting \li \c{bool} \li 1.4 \li \c{undefined} \li Whether to enable Automatic Reference Counting (ARC) for Objective-C and Objective-C++ source code. If \c{undefined}, uses the compiler default (probably \c{false}). \row \li requireAppExtensionSafeApi \li \c{bool} \li 1.4 \li \c{undefined} \li Whether to enforce the use of only app-extension-safe APIs on OS X and iOS. This is necessary for building Application Extensions in OS X Yosemite and iOS 8 and above. If \c{undefined}, uses the compiler and linker defaults (probably \c{false}). \row \li minimumIosVersion \li \c{string} \li 1.0 \li undefined, but may be set by generated profiles \li A version number in the format [major].[minor] indicating the earliest version of iOS that the product should run on. Passes -miphoneos-version-min= to the compiler. If undefined, compiler defaults will be used. \row \li minimumOsxVersion \li \c{string} \li 1.0.1 \li undefined, but may be set by generated profiles \li A version number in the format [major].[minor] indicating the earliest version of OS X that the product should run on. Passes -mmacosx-version-min= to the compiler. If undefined, compiler defaults will be used. \endtable \section1 Properties Specific to Unix Platforms \table \header \li Property \li Type \li Since \li Default \li Description \row \li archiverName \li \c{string} \li 1.0 \li \c{"ar"} \li Name of the archiver binary. This is set in the build profile. \row \li archiverPath \li \c{string} \li 1.0 \li determined by qbs-setup-toolchains \li Full path of the archiver binary. This is set in the build profile. \row \li exportedSymbolsCheckMode \li \c{string} \li 1.4.1 \li "ignore-undefined" \li Controls how \QBS determines whether an updated dynamic library causes relinking of dependents. The default value is \c "ignore-undefined", which means that undefined symbols being added or removed do not cause any relinking. If that should happen, for example because dependent products are linked with an option such as \c "--no-undefined", then this property can be set to \c "strict". \row \li nmName \li \c{string} \li 1.2 \li \c{"nm"} \li Name of the nm binary. This is set in the build profile. \row \li nmPath \li \c{string} \li 1.2 \li determined by qbs-setup-toolchains \li Full path of the nm binary. This is set in the build profile. \row \li objcopyName \li \c{string} \li 1.4 \li \c{"objcopy"} \li Name of the objcopy binary. This is set in the build profile. \row \li objcopyPath \li \c{string} \li 1.4 \li determined by qbs-setup-toolchains \li Full path of the objcopy binary. This is set in the build profile. \row \li stripName \li \c{string} \li 1.4 \li \c{"strip"} \li Name of the strip binary. This is set in the build profile. \row \li stripPath \li \c{string} \li 1.4 \li determined by qbs-setup-toolchains \li Full path of the strip binary. This is set in the build profile. \row \li dsymutilPath \li \c{string} \li 1.4 \li determined by qbs-setup-toolchains \li Full path of the dsymutil binary. This is set in the build profile. \row \li dsymutilFlags \li \c{stringList} \li 1.4.1 \li undefined \li Additional flags for the dsymutil tool. \row \li positionIndependentCode \li \c{bool} \li 1.0 \li \c{undefined} \li Generate position independent code. If this property is \c{undefined}, then position independent code is generated for libraries, but not for applications. \row \li rpaths \li \c{stringList} \li 1.0 \li \c{undefined} \li List of rpaths that are passed to the linker. \row \li useRPaths \li \c{bool} \li 1.3 \li \c{true} \li Set this property to \c{false} to prevent the linker from writing rpaths to the binary. \row \li visibility \li \c{string} \li 1.0 \li \c{"default"} \li Visibility level for exported symbols. Possible values include: \c{"default"}, \c{"hidden"}, \c{"hiddenInlines"}, and \c{"minimal"}, which combines \c{"hidden"} and \c{"hiddenInlines"}. \endtable \section1 Properties Specific to Windows \table \header \li Property \li Type \li Since \li Default \li Description \row \li windowsApiCharacterSet \li \c{string} \li 1.0.1 \li \c{"unicode"} \li Specifies the character set used in the Win32 API. "unicode" will define the preprocessor symbols UNICODE and _UNICODE, "mbcs" will define _MBCS, and setting the value to undefined will use the default character set. \row \li minimumWindowsVersion \li \c{string} \li 1.0 \li undefined, but may be set by generated profiles \li A version number in the format [major].[minor] indicating the earliest version of Windows that the product should run on. Defines WINVER, _WIN32_WINNT, and _WIN32_WINDOWS, and applies a version number to the linker flags /SUBSYSTEM and /OSVERSION for MSVC or -Wl,--major-subsystem-version, -Wl,--minor-subsystem-version, -Wl,--major-os-version and -Wl,--minor-os-version for MinGW. If undefined, compiler defaults will be used. \endtable */ qbs-src-1.4.5/doc/reference/modules/ib-module.qdoc000066400000000000000000000146121266132464200220050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage index.html \page ib-module.html \ingroup list-of-modules \title Module ib \since 1.1 \brief Provides support for Apple Interface Builder and related tools and file types. The \c ib module contains properties and rules for building Interface Builder documents, storyboards, asset catalogs, and icon sets. This module is only available on OS X and iOS. \section1 General Properties \table \header \li Property \li Type \li Since \li Default \li Description \row \li warnings \li bool \li 1.1 \li \c{true} \li Whether to print warnings when compiling. Does not apply to icon sets. \row \li errors \li bool \li 1.1 \li \c{true} \li Whether to print warnings when compiling. Does not apply to icon sets. \row \li notices \li bool \li 1.1 \li \c{true} \li Whether to print warnings when compiling. Does not apply to icon sets. \row \li flags \li stringList \li 1.1 \li undefined \li Additional flags to pass to the underlying tool (ibtool, actool, iconutil). \endtable \section1 Properties Specific to NIBs and Storyboards \table \header \li Property \li Type \li Since \li Default \li Description \row \li ibtoolName \li string \li 1.3 \li \c{"ibtool"} \li Name of the ibtool binary used to compile NIBs and storyboards. This should not normally need to be changed. \row \li ibtoolPath \li string \li 1.3 \li \c{ibtoolName} \li Directory where the ibtool binary is located. This should not normally need to be changed. \row \li flatten \li bool \li 1.1 \li \c{true} \li Compiles XIBs and storyboards into flattened (non-wrapper) files. Set to \c{false} to preserve editability of the resulting nib and storyboard bundles in Interface Builder. This property should not normally need to be changed. \row \li module \li string \li 1.3 \li \c{undefined} \li Sets the name of the module that the nib or storyboard is a part of. Requires Xcode 6 or newer. \row \li autoActivateCustomFonts \li bool \li 1.3 \li \c{true} \li Instructs the ibtool compiler to add custom fonts to the application's Info.plist when compiling XIBs and storyboards, which will cause the fonts to activate upon application launch. Requires Xcode 6 or newer. \endtable \section1 Properties Specific to Asset Catalogs \table \header \li Property \li Type \li Since \li Default \li Description \row \li actoolName \li string \li 1.3 \li \c{"actool"} \li Name of the actool binary used to compile asset catalogs. This should not normally need to be changed. \row \li actoolPath \li string \li 1.3 \li \c{actoolName} \li Directory where the actool binary is located. This should not normally need to be changed. \row \li appIconName \li string \li 1.3 \li \c{undefined} \li Name of the resource in the asset catalog that will be used as the application's icon. Used to generate the partial Info.plist which will be merged into the resulting app. If this property is \c{undefined}, no application icon will be specified. \row \li launchImageName \li string \li 1.3 \li \c{undefined} \li Name of the resource in the asset catalog that will be used as the application's launch image. Used to generate the partial Info.plist which will be merged into the resulting app. If this property is \c{undefined}, no launch image will be specified. Only applies to iOS applications. \row \li compressPngs \li bool \li 1.3 \li \c{true} \li Whether to compress PNG image files when building asset catalogs. \endtable \section1 Properties Specific to Icon Sets \table \header \li Property \li Type \li Since \li Default \li Description \row \li iconutilName \li string \li 1.3 \li \c{"iconutil"} \li Name of the iconutil binary used to compile icon sets. This should not normally need to be changed. \row \li iconutilPath \li string \li 1.3 \li \c{iconutilName} \li Directory where the iconutil binary is located. This should not normally need to be changed. \endtable */ qbs-src-1.4.5/doc/reference/modules/java-module.qdoc000066400000000000000000000144561266132464200223420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage index.html \page java-module.html \ingroup list-of-modules \title Module java \since 1.4 \brief Provides Java support. The \c java module contains the properties and rules for building Java projects. \section1 Java Properties \table \header \li Property \li Type \li Since \li Default \li Description \row \li additionalClassPaths \li stringList \li 1.4 \li undefined \li Locations beside this product's class output path to consider when compiling. \row \li additionalCompilerFlags \li stringList \li 1.4 \li undefined \li Use this to supply compiler flags not covered by any of the properties in this module. \row \li additionalJarFlags \li stringList \li 1.4 \li undefined \li Use this to supply archiver flags not covered by any of the properties in this module. \row \li bootClassPaths \li stringList \li 1.4 \li undefined \li Use this if you need to specify non-standard bootstrap class files. \row \li compilerFilePath \li string \li 1.4 \li \c compilerName, prefixed by \c jdkPath if it is defined \li The command to invoke when compiling Java sources. \row \li compilerName \li string \li 1.4 \li \c{"javac"} \li The file name of the Java compiler. \row \li enableWarnings \li bool \li 1.4 \li \c true \li Controls whether warnings are emitted when compiling Java sources. \row \li interpreterFilePath \li string \li 1.4 \li \c interpreterName, prefixed by \c jdkPath if it is defined \li The command to invoke when executing Java code. \row \li interpreterName \li string \li 1.4 \li \c{"java"} \li The file name of the Java interpreter. \row \li jarFilePath \li string \li 1.4 \li \c jarName, prefixed by \c jdkPath if it is defined \li The command to run when creating or extracting \c jar files. \row \li jarName \li string \li 1.4 \li \c{"jar"} \li The file name of the \c jar tool. \row \li jdkIncludePaths \li pathList \li 1.4.1 \li determined automatically \li List of include paths for native header files. Applications using JNI to interface with native code should add these paths to \c{cpp.includePaths}. \row \li jdkPath \li path \li 1.4 \li determined automatically \li The base path of the Java Development Kit (JDK). This is equivalent to the \c JAVA_HOME environment variable, and by default will be determined automatically from one of the following: \list \li \c JAVA_HOME environment variable (all platforms) \li Registry (Windows) \li \c java_home tool (OS X) \li Known JDK paths (other Unix platforms) \endlist \row \li languageVersion \li string \li 1.4 \li undefined \li The Java language version to interpret source code as. If undefined, the compiler will use its default. \row \li runtimeVersion \li string \li 1.4 \li undefined \li The version of the Java runtime to generate compatible bytecode for. If undefined, the compiler will use its default. \row \li manifest \li object \li 1.4.2 \li undefined \li The properties to add to the manifest file when building a JAR. The contents of this property will be aggregated with the values from \c{manifestFile}. If \c{manifest} and \c{manifestFile} contain the same key, the former will take precedence. If undefined, will not be taken into account. \row \li manifestFile \li path \li 1.4.2 \li undefined \li The manifest file to embed when building a JAR. The contents of this file will be aggregated with the values in \c{manifest}. If \c{manifestFile} and \c{manifest} contain the same key, the latter will take precedence. If undefined, will not be taken into account. \row \li manifestClassPath \li stringList \li 1.4.2 \li undefined \li The entries to add to the manifest's Class-Path when building a JAR. \row \li warningsAsErrors \li bool \li 1.4 \li \c false \li If this property is enabled, the compiler will abort where it would normally emit a warning. \endtable */ qbs-src-1.4.5/doc/reference/modules/nodejs-module.qdoc000066400000000000000000000043651266132464200227010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage index.html \page nodejs-module.html \ingroup list-of-modules \title Module nodejs \since 1.3 \brief Provides Node.js support. The \c nodejs module contains support for running \l{http://nodejs.org}{Node.js} applications from \QBS. \section1 General Properties \table \header \li Property \li Type \li Since \li Default \li Description \row \li applicationFile \li path \li 1.3 \li \c{undefined} \li The input JavaScript file whose corresponding output will be executed when running the Node.js application. If this property is \c{undefined}, the product will not be runnable. \endtable */ qbs-src-1.4.5/doc/reference/modules/nsis-module.qdoc000066400000000000000000000132751266132464200223730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage index.html \page nsis-module.html \ingroup list-of-modules \title Module nsis \since 1.2 \brief Provides Nullsoft Scriptable Install System support. The \c nsis module contains properties and rules for building EXE installers for Windows using the Nullsoft Scriptable Install System. This module is available on all platforms. \note A typical NSIS script includes an OutFile command to set the filename of the generated installer executable. However, \QBS overrides any OutFile commands found in the script, and therefore, you must use the targetName property to set the filename. \section1 General Properties \table \header \li Property \li Type \li Since \li Default \li Description \row \li defines \li stringList \li 1.2 \li \c{undefined} \li List of preprocessor macros that get passed to the compiler. To set macro values, use the following syntax: \c{cpp.defines: ["USE_COLORS=1", 'COLOR_STR="blanched almond"']} \row \li disableConfig \li bool \li 1.2 \li \c{false} \li Whether to disable inclusion of nsisconf.nsh. Generally you do not need to set this property. \row \li enableQbsDefines \li bool \li 1.2 \li \c{true} \li Whether to define preprocessor macros corresponding to values from the project and product objects. When building a 64-bit package, the preprocessor variable \c{Win64} will also be defined. \row \li warningLevel \li string \li 1.2 \li \c{"normal"} \li Severity of warnings to emit. The higher the level, the more warnings will be shown. The levels \c{none}, \c{errors}, \c{warnings}, \c{info} and \c{all} correspond to NSIS verbosity levels 0 through 4, inclusive. \c{normal} corresponds to the default level. \row \li compilerFlags \li stringList \li 1.2 \li undefined \li Additional flags for the NSIS compiler. \row \li compressor \li string \li 1.2 \li \c{"default"} \li Compression algorithm used to compress files and data in the installer. Setting this property overrides any SetCompressor command in the NSI file being compiled. Possible values include: \c{"default"}, \c{"zlib"}, \c{"zlib-solid"}, \c{"bzip2"}, \c{"bzip2-solid"}, \c{"lzma"}, \c{"lzma-solid"} \row \li version \li string \li 1.2 \li \c{undefined} \li The NSIS version. Consists of four numbers separated by dots, for instance "2.46.0.0". \row \li versionMajor \li int \li 1.2 \li \c{versionParts[0]} \li The NSIS major version. \row \li versionMinor \li int \li 1.2 \li \c{versionParts[1]} \li The NSIS minor version. \row \li versionParts \li list \li 1.2 \li \c{empty} \li The NSIS version as a list. For instance, NSIS version 2.46.0.0 would correspond to a value of \c[2, 46, 0, 0]. \row \li versionPatch \li int \li 1.2 \li \c{versionParts[2]} \li The NSIS patch level. \row \li versionBuild \li int \li 1.2 \li \c{versionParts[3]} \li The fourth NSIS version number component. \row \li toolchainInstallPath \li path \li 1.2 \li determined automatically \li NSIS installation directory. Determined by searching known registry keys and known installation paths until a match is found. This should not normally need to be changed. \row \li compilerName \li string \li 1.2 \li \c{"makensis"} \li Name of the compiler binary. This should not normally need to be changed. \row \li compilerPath \li string \li 1.2 \li \c{compilerName} \li Directory where the compiler binary is located. This should not normally need to be changed. \endtable */ qbs-src-1.4.5/doc/reference/modules/qbs-module.qdoc000066400000000000000000000253741266132464200222070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage list-of-modules.html \page qbs-module.html \ingroup list-of-modules \title Module qbs \since 1.0 \brief Comprises general properties. The \c qbs module is implicitly loaded in every product. It contains properties of the current build environment, independent of the used programming languages and toolchains. \section1 General Properties \table \header \li Property \li Type \li Since \li Default \li Description \row \li buildVariant \li \c{string} \li 1.0 \li \c{"debug"} \li Contains the name of the build variant for the current build. \row \li debugInformation \li \c bool \li 1.0 \li \c{true} for debug builds, \c{false} otherwise \li Specifies whether to generate debug information. \row \li enableDebugCode \li \c bool \li 1.0 \li \c{true} for debug builds, \c{false} otherwise \li Specifies whether to compile debug code in the product. This is typically enabled for debug builds and disabled for release builds. \row \li optimization \li \c{string} \li 1.0 \li \c{"none"} for debug builds, \c{"fast"} for release builds \li Specifies the general type of optimization that should be performed by all toolchains. Allowed values: \c{"none"}, \c{"fast"}, \c{"small"} \row \li targetOS \li \c{stringList} \li 1.0 \li \c{undefined} \li Specifies the OS you want to build the project for. This is typically set in a profile. Possible values include one or more of the following: \c{"aix"}, \c{"android"}, \c{"blackberry"}, \c{"bsd"}, \c{"bsd4"}, \c{"bsdi"}, \c{"cygwin"}, \c{"darwin"}, \c{"dgux"}, \c{"dynix"}, \c{"freebsd"}, \c{"hpux"}, \c{"hurd"}, \c{"integrity"}, \c{"ios"}, \c{"ios-simulator"}, \c{"irix"}, \c{"linux"}, \c{"lynx"}, \c{"osx"}, \c{"msdos"}, \c{"nacl"}, \c{"netbsd"}, \c{"openbsd"}, \c{"os2"}, \c{"os2emx"}, \c{"osf"}, \c{"qnx"}, \c{"qnx6"}, \c{"reliant"}, \c{"sco"}, \c{"solaris"}, \c{"symbian"}, \c{"ultrix"}, \c{"unix"}, \c{"unixware"}, \c{"vxworks"}, \c{"windows"}, \c{"windowsce"}, \c{"windowsphone"}, \c{"winrt"} \row \li architecture \li \c{string} \li 1.0 \li \c{undefined} \li Specifies the target platform's processor architecture. \c{undefined} indicates that the target platform is architecture-independent (for example the CLR or JVM). This is typically set in a profile. Commonly used values are: \c{"x86"}, \c{"x86_64"} and \c{"arm"}. \row \li toolchain \li \c{stringList} \li 1.0 \li \c{undefined} \li Specifies the attributes of the toolchain that is going to be used for this build. Typical values include: \c{"gcc"}, \c{"llvm"}, \c{"clang"}, \c{"mingw"}, \c{"msvc"} \row \li sysroot \li \c{string} \li 1.0 \li \c{undefined} \li Specifies the sysroot of the target platform. This property is typically set in a profile for cross-compiling. \row \li pathListSeparator \li \c{string} \li 1.0 \li \c{";"} on Windows, \c{":"} on Unix \li Holds the platform-specific separator for path list that is used in environment variables or other contexts. \row \li nullDevice \li \c{string} \li 1.4.2 \li \c{"NUL"} on Windows, \c{"/dev/null"} on Unix \li Holds the platform-specific file path corresponding to the null device. \endtable \section1 Environment Properties This section lists constant, read-only properties set by \QBS internally. These properties should not be overridden. \table \header \li Property \li Type \li Since \li Default \li Description \row \li hostOS \li \c{stringList} (read only) \li 1.0 \li \c{undefined} \li This property is set by \QBS internally and specifies the OS \QBS is running on. The possible values for this property are the values of \c targetOS, though some may not be supported. \row \li hostOSVersion \li \c{string} (read only) \li 1.2 \li \c{undefined} \li The host operating system version. Currently only defined for Windows and Apple platforms. Consists of two or three numbers separated by dots, for instance "10.9" or "6.3.9600". \row \li hostOSBuildVersion \li \c{string} (read only) \li 1.2 \li \c{undefined} \li The host operating system's build version. Currently only defined for Windows and Apple platforms. On Windows, this is the 4 or 5 digit Windows build number and is equivalent to \c versionPatch. On Apple platforms, this is a standard build number in the Apple versioning scheme, for instance "13C64". \row \li hostOSVersionMajor \li \c{int} (read only) \li 1.2 \li \c{hostOSVersionParts[0]} \li The host operating system major version. \row \li hostOSVersionMinor \li \c{int} (read only) \li 1.2 \li \c{hostOSVersionParts[1]} \li The host operating system minor version. \row \li hostOSVersionParts \li \c{list} (read only) \li 1.2 \li \c{empty} \li The host operating system version as a list. For instance, Windows 8.1 (version 6.3.9600) would correspond to a value of \c[6, 3, 9600]. \row \li hostOSVersionPatch \li \c{int} (read only) \li 1.2 \li \c{hostOSVersionParts[2]} \li The host operating system patch level. \row \li version \li \c{string} (read only) \li 1.4.1 \li \li Version number of \QBS as a string, i.e. "1.4.1". \row \li versionMajor \li \c{int} (read only) \li 1.4.1 \li \li Major version number of \QBS. \row \li versionMinor \li \c{int} (read only) \li 1.4.1 \li \li Minor version number of \QBS. \row \li versionPatch \li \c{int} (read only) \li 1.4.1 \li \li Patch version number of \QBS. \endtable \section1 Installation Properties This section lists properties specific to the \QBS installation mechanism. See \l{Installing Files} for more information. \table \header \li Property \li Type \li Since \li Default \li Description \row \li install \li \c{bool} \li 1.0 \li \c{false} \li Specifies whether to install a certain set of files. This is typically set in a \c{Group} item to mark a number of files as installable. \note Artifacts for which this property is enabled automatically receive the file tag "installable". This is useful for writing packaging-related rules. \row \li installSourceBase \li \c{string} \li 1.4 \li see below \li Specifies the base directory of the local files that are going to be installed. The source base directory is omitted from the target directory path specified in \c{installDir}. The default value of this property is the directory of the current file to be installed, relative to the product's source directory. \row \li installDir \li \c{string} \li 1.0 \li \c{undefined} \li Specifies the installation directory for the files of a product or a \c{Group}. The value of this property is a path that is relative to \c installPrefix. \row \li installPrefix \li \c{string} \li 1.1 \li \c{empty} \li Specifies the global installation prefix. It is implicitly prepended to all values of \c installDir. The \c installPrefix itself is relative to the \c installRoot in the context of installation. \row \li installRoot \li \c{string} \li 1.4 \li \c{/install-root} \li Specifies the global installation root. It is implicitly prepended to all values of \c installPrefix in the context of installation. \note This property is fundamentally different from \c installDir and \c installPrefix in that it must not be visible to the code being built. In fact, the install root is often just a temporary location used to package the binaries, which should therefore not assume they will be in that location at run-time. \endtable */ qbs-src-1.4.5/doc/reference/modules/qt-modules.qdoc000066400000000000000000000271231266132464200222230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage index.html \page qt-modules.html \ingroup list-of-modules \title Qt Modules \brief Provide Qt support. The \c{Qt.*} modules contain properties and rules for Qt. \section1 Creating Dependencies to Qt Modules The Qt modules are special in that they are submodules within the \c Qt "namespace", which has ramifications on the syntax when expressing dependencies. Assume your product depends on the \c core and \c network modules. Then you could write: \code Depends { name: "Qt.core" } Depends { name: "Qt.network" } \endcode Or, alternatively: \code Depends { name: "Qt"; submodules: ["core", "network" } } \endcode \section1 List of Submodules \table \header \li Submodule Name \li Qt Module Name \li Notes \row \li axcontainer \li QAxContainer \li This module is only available on Windows. \row \li axserver \li QAxServer \li This module is only available on Windows. \row \li concurrent \li Qt Concurrent \li \row \li core \li Qt Core \li All other \c Qt modules have a dependency to this one, so you do not need to list it in your dependencies if you depend on at least one other \c Qt module. For more information on the properties you can specify, see \l{core Properties}. \row \li dbus \li Qt D-Bus \li \row \li declarative \li Qt Quick 1 \li Provides the \c{Qt Quick 1} module. For more information, see \l{declarative Properties}. \row \li designer \li Qt Designer \li \row \li enginio \li Qt Enginio \li \row \li gui \li Qt GUI \li For more information, see \l {gui Properties}. \row \li help \li Qt Help \li You do not need this module for building \c qdoc documentation, because that functionality is part of the \c core module. This module is for using Qt classes such as \c QHelpEngine. \row \li multimedia \li Qt Multimedia \li \row \li multimediawidgets \li Qt Multimedia Widgets \li \row \li network \li Qt Network \li \row \li opengl \li Qt OpenGL \li \row \li phonon \li Phonon (Qt 4 only) \li \row \li printsupport \li Qt Print Support \li \row \li quick \li Qt Quick (2) \li Provides the \c{Qt Quick} module (Qt Quick 2). For more information, see \l {quick Properties}. \row \li qml \li Qt QML \li \row \li script \li Qt Script \li \row \li sql \li Qt SQL \li \row \li svg \li Qt SVG \li \row \li testlib \li Qt Test \li \row \li webkit \li Qt WebKit \li \row \li webkitwidgets \li Qt WebKit Widgets \li \row \li widgets \li Qt Widgets \li \row \li xml \li Qt XML \li You do not need this module for the \c QXmlStreamReader and \c QXmlStreamWriter classes, because those classes are a part of the \c core module. This module provides the deprecated DOM and SAX classes. \row \li xmlpatterns \li Qt XML Patterns \li \li \endtable \section1 core Properties As opposed to most other \c Qt modules, \c core defines a number of properties that can be interesting to users. Some of them only need to be defined if the respective installation of Qt was built in some unusual way, for instance by setting non-default \c configure flags. \table \header \li Property \li Type \li Default \li Description \row \li availableBuildVariants \li \c{stringList} \li set by \c{qbs-setup-qt} \li The build variants that this Qt installation offers. \row \li binPath \li \c{path} \li \c{undefined} \li The path in which Qt tools such as \c qmake, \c moc and so on are located. \row \li config \li \c{stringList} \li \c{empty} \li Corresponds to the default value of qmake's \c CONFIG variable. \row \li docPath \li \c{path} \li \c{undefined} \li The path in which the Qt documentation is located. \row \li frameworkBuild \li \c{bool} \li \c{undefined} \li Specifies whether Qt was built as a framework. This is only relevant for Darwin systems. \row \li incPath \li \c{path} \li \c{undefined} \li The base path of the Qt headers. \row \li libInfix \li \c{string} \li \c{empty} \li The library infix can be set at Qt build time to change the name of Qt's libraries. For instance, if the infix is "Test", then on Unix systems, the \c{Qt Core} library will be in a file called \c{libQt5CoreTest.so} instead of the default \c{libQt5Core.so}. \row \li libPath \li \c{path} \li \c{undefined} \li The path in which the Qt libraries are located. \row \li lreleaseName \li \c{string} \li \c{"lrelease"} \li The base name of the \c lrelease tool. Set this if your system uses a name such as "lrelease-qt4". \row \li mkspecPath \li \c{path} \li \c{undefined} \li The path in which the Qt mkspecs are located. \row \li mocName \li \c{string} \li \c{"moc"} \li The base name of the \c moc tool. Set this if your system uses a name such as "moc-qt4". \row \li namespace \li \c{string} \li \c{undefined} \li The Qt namespace that can be set at build time via the \c configure script. By default, Qt is not built in a namespace. \row \li pluginPath \li \c{path} \li \c{undefined} \li The path in which the Qt plugins are located. \row \li qdocEnvironment \li \c{stringlist} \li \c{undefined} \li The environment for calls to \c qdoc. Typically, you will need to set some variables here when running \c qdoc to build your project documentation. \row \li qdocName \li \c{string} \li \c{"qdoc3"} for Qt 4, \c{"qdoc"} otherwise \li The base name of the \c qdoc tool. \row \li qdocQhpFileName \li \c{string} \li \c{undefined} \li Controls which name the \c qhp file gets when generating documentation with \c qdoc. \row \li qtBuildVariant \li \c{string} \li See below. \li Specifies the type of Qt libraries to build against: "debug" or "release". The default value is the build variant of the code linking against Qt. If Qt does not offer that build variant, the build variant offered by Qt is chosen instead. \note On some systems, it is not possible to link code built in debug mode against libraries built in release mode and vice versa. \row \li qtConfig \li \c{stringList} \li \c{empty} \li Corresponds to the default value of qmake's \c QT_CONFIG variable. \row \li staticBuild \li \c{bool} \li \c{undefined} \li Specifies whether Qt was built statically. \row \li version \li \c{string} \li \c{undefined} \li The Qt version. Consists of three numbers separated by dots, for instance "5.1.1". \row \li versionMajor \li \c{int} \li \c{versionParts[0]} \li The Qt major version. \row \li versionMinor \li \c{int} \li \c{versionParts[1]} \li The Qt minor version. \row \li versionParts \li \c{list} \li \c{empty} \li The Qt version as a list. For instance, Qt version 5.1.1 would correspond to a value of \c[5, 1, 1]. \row \li versionPatch \li \c{int} \li \c{versionParts[2]} \li The Qt patch level. \endtable \section1 declarative Properties \table \header \li Property \li Type \li Default \li Description \row \li qmlDebugging \li \c{bool} \li \c{false} \li Specifies whether QML debugging support should be compiled into your binaries. \row \li qmlImportsPath \li \c{string} \li set by \c{qbs-setup-qt} \li The absolute path to the directory where Qt's QML imports are installed. \row \li qmlPath \li \c{string} \li set by \c{qbs-setup-qt} \li The absolute path to the directory where Qt's QML files are installed. This property is undefined for Qt4. \endtable \section1 gui Properties \table \header \li Property \li Type \li Default \li Description \row \li uicName \li \c{string} \li \c{"uic"} \li The base name of the \c uic tool. Set this if your system uses a name such as "uic-qt4". \endtable \section1 quick Properties \table \header \li Property \li Type \li Default \li Description \row \li qmlDebugging \li \c{bool} \li \c{false} \li Specifies whether QML debugging support should be compiled into your binaries. \row \li qmlImportsPath \li \c{string} \li set by \c{qbs-setup-qt} \li The absolute path to the directory where Qt's QML imports are installed. \row \li qmlPath \li \c{string} \li set by \c{qbs-setup-qt} \li The absolute path to the directory where Qt's QML files are installed. This property is undefined for Qt4. \endtable */ qbs-src-1.4.5/doc/reference/modules/typescript-module.qdoc000066400000000000000000000137061266132464200236240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage index.html \page typescript-module.html \ingroup list-of-modules \title Module typescript \since 1.3 \brief Provides TypeScript support. The \c typescript module contains properties and rules for building \l{http://www.typescriptlang.org}{TypeScript} applications and may be used in combination with the \l {Module nodejs} {nodejs} module to run TypeScript applications directly from \QBS. \section1 General Properties \table \header \li Property \li Type \li Since \li Default \li Description \row \li warningLevel \li \c{string} \li 1.3 \li \c{"normal"} \li Severity of warnings to emit. The higher the level, the more warnings will be shown. \c{pedantic} causes the TypeScript to emit warnings on expressions and declarations with an implied 'any' type. \row \li targetVersion \li \c{string} \li 1.3 \li \c{undefined} \li ECMAScript target version for generated JavaScript code. \c{undefined} uses the TypeScript \l{https://github.com/Microsoft/TypeScript/wiki/Compiler-Options}{compiler default}. \row \li moduleLoader \li \c{string} \li 1.3 \li \c{undefined} \li If TypeScript modules are being used, the JavaScript module loading mechanism to use in the generated JavaScript code. \c{undefined} indicates modules are not being used. See \l{https://github.com/Microsoft/TypeScript/wiki/Compiler-Options}{Compiler Options} for a list of possible values. \row \li stripComments \li \c{bool} \li 1.3 \li \c{!qbs.debugInformation} \li Whether to remove comments from the generated JavaScript files. \row \li generateDeclarations \li \c{bool} \li 1.3 \li \c{false} \li Whether to generate corresponding .d.ts files during compilation; these are TypeScript's equivalent of header files. \row \li generateSourceMaps \li \c{bool} \li 1.3 \li \c{qbs.debugInformation} \li Whether to generate corresponding .map files during compilation. \row \li compilerFlags \li \c{stringList} \li 1.3 \li \c{undefined} \li Additional flags for the TypeScript compiler. \row \li singleFile \li \c{bool} \li 1.3 \li \c{false} \li Whether to compile all TypeScript source files to a single JavaScript output file. The default is to compile each TypeScript file to a corresponding JavaScript file. This property is incompatible with \c{moduleLoader}. \row \li version \li \c{string} \li 1.3 \li \c{undefined} \li The TypeScript version. Consists of four numbers separated by dots, for instance "1.0.0.0". \row \li versionMajor \li \c{int} \li 1.3 \li \c{versionParts[0]} \li The TypeScript major version. \row \li versionMinor \li \c{int} \li 1.3 \li \c{versionParts[1]} \li The TypeScript minor version. \row \li versionParts \li \c{list} \li 1.3 \li \c{empty} \li The TypeScript version as a list. For instance, TypeScript version 1.0 would correspond to a value of \c[1, 0, 0, 0]. \row \li versionPatch \li \c{int} \li 1.3 \li \c{versionParts[2]} \li The TypeScript patch level. \row \li versionBuild \li \c{int} \li 1.3 \li \c{versionParts[3]} \li The fourth TypeScript version number component. \row \li toolchainInstallPath \li \c{path} \li 1.3 \li \c{undefined} \li TypeScript installation directory. This should not normally need to be changed provided that \c{tsc} is already available by searching the PATH environment variable. \row \li compilerName \li \c{string} \li 1.3 \li \c{"tsc"} \li Name of the compiler binary. This should not normally need to be changed. \row \li compilerPath \li \c{string} \li 1.3 \li \c{compilerName} \li Directory where the compiler binary is located. This should not normally need to be changed. \endtable */ qbs-src-1.4.5/doc/reference/modules/wix-module.qdoc000066400000000000000000000172751266132464200222320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage index.html \page wix-module.html \ingroup list-of-modules \title Module wix \since 1.2 \brief Provides Windows Installer XML Toolset support. The \c wix module contains properties and rules for building MSI and EXE setup packages with the \l{http://wixtoolset.org}{Windows Installer XML Toolset}. This module is available on all platforms. \section1 General Properties \table \header \li Property \li Type \li Since \li Default \li Description \row \li debugInformation \li \c{bool} \li 1.2 \li \c{qbs.debugInformation} \li Generate debug information. See \c{qbs.debugInformation}. \row \li defines \li \c{stringList} \li 1.2 \li \c{undefined} \li List of preprocessor macros that get passed to the compiler. To set macro values use the following syntax: \c{wix.defines: ["USE_COLORS=1", 'COLOR_STR="blanched almond"']} \row \li enableQbsDefines \li \c{bool} \li 1.2 \li \c{true} \li Whether to define preprocessor macros corresponding to values from the project and product objects. When building a 64-bit package, the preprocessor variable \c{Win64} will also be defined. \row \li visualStudioCompatibility \li \c{bool} \li 1.2 \li \c{true} \li Passes most of the same preprocessor macros to the compiler as Visual Studio does. This allows easier authoring WiX files that are compatible with both \QBS and MSBuild. \row \li includePaths \li \c{pathList} \li 1.2 \li \c{undefined} \li List of include paths. Relative paths are considered to be relative to the .qbs product file they are used in. \row \li treatWarningsAsErrors \li \c{bool} \li 1.2 \li \c{false} \li Warnings will be handled as errors and cause the build to fail. \row \li warningLevel \li \c{string} \li 1.2 \li \c{"normal"} \li Severity of warnings to emit. The higher the level, the more warnings will be shown. Possible values include: \c{"none"}, \c{"normal"}, \c{"pedantic"} \row \li verboseOutput \li \c{bool} \li 1.2 \li \c{false} \li Whether to display verbose output from the compiler and linker. \row \li compilerFlags \li \c{stringList} \li 1.2 \li \c{undefined} \li Additional flags for the Candle compiler. \row \li linkerFlags \li \c{stringList} \li 1.2 \li \c{undefined} \li Additional flags for the Light linker. \row \li cultures \li \c{stringList} \li 1.2 \li \c{undefined} \li List of localizations to include in the MSI. Use \c{undefined} to include all localizations. \row \li extensions \li \c{stringList} \li 1.2 \li \c{["WixBalExtension"]} if the product type is an EXE setup application, otherwise \c{undefined}. \li List of extension assemblies to link into the output. Possible values include: \c{"WixBalExtension"}, \c{"WixComPlusExtension"}, \c{"WixDependencyExtension"}, \c{"WixDifxAppExtension"}, \c{"WixDirectXExtension"}, \c{"WixFirewallExtension"}, \c{"WixGamingExtension"}, \c{"WixIisExtension"}, \c{"WixMsmqExtension"}, \c{"WixNetFxExtension"}, \c{"WixPSExtension"}, \c{"WixSqlExtension"}, \c{"WixTagExtension"}, \c{"WixUIExtension"}, \c{"WixUtilExtension"}, \c{"WixVSExtension"}, custom assemblies \row \li version \li \c{string} \li 1.2 \li \c{undefined} \li The WiX version. Consists of four numbers separated by dots, for instance "3.7.1224.0". \row \li versionMajor \li \c{int} \li 1.2 \li \c{versionParts[0]} \li The WiX major version. \row \li versionMinor \li \c{int} \li 1.2 \li \c{versionParts[1]} \li The WiX minor version. \row \li versionParts \li \c{list} \li 1.2 \li \c{empty} \li The WiX version as a list. For instance, WiX version 3.7.1224.0 would correspond to a value of \c[3, 7, 1224, 0]. \row \li versionPatch \li \c{int} \li 1.2 \li \c{versionParts[2]} \li The WiX patch level. \row \li versionBuild \li \c{int} \li 1.2 \li \c{versionParts[3]} \li The fourth WiX version number component. \row \li toolchainInstallPath \li \c{path} \li 1.2 \li determined automatically \li WiX installation directory. Determined by searching the registry for the latest version. This should not normally need to be changed. \row \li toolchainInstallRoot \li \c{path} \li 1.2 \li determined automatically \li WiX binaries directory. Determined by searching the registry for the latest version. This should not normally need to be changed. \row \li compilerName \li \c{string} \li 1.2 \li \c{"candle.exe"} \li Name of the compiler binary. This should not normally need to be changed. \row \li compilerPath \li \c{string} \li 1.2 \li \c{compilerName} \li Directory where the compiler binary is located. This should not normally need to be changed. \row \li linkerName \li \c{string} \li 1.2 \li \c{"light.exe"} \li Name of the linker binary. This should not normally need to be changed. \row \li linkerPath \li \c{string} \li 1.2 \li \c{linkerName} \li Directory where the linker binary is located. This should not normally need to be changed. \endtable */ qbs-src-1.4.5/doc/reference/reference.qdoc000066400000000000000000000054631266132464200204220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ /*! \contentspage index.html \previouspage shell.html \page reference.html \title Reference \list \li \l{List of Language Items} \li \l{List of Built-in Services} \li \l{List of Command-line Tools} \li \l{List of Modules} \li \l{Command and JavaScriptCommand} \endlist */ /*! \contentspage reference.html \group list-of-builtin-services \title List of Built-in Services \QBS provides the following built-in JavaScript extensions to simplify operations that are expected to be needed often in project files. To gain access to the operations provided by a particular Service - for example, the File service - use the following statement at the top of your \QBS project file: \code import qbs.File \endcode If you instead need to access the service from a JavaScript file, import it using the following statement at the top of your JavaScript file: \code var File = loadExtension("qbs.File"); \endcode */ /*! \contentspage reference.html \group list-of-modules \title List of Modules These are the modules shipped with \QBS. */ /*! \contentspage reference.html \group list-of-items \title List of Language Items \QBS provides the following built-in QML items to define projects. */ qbs-src-1.4.5/doc/templates/000077500000000000000000000000001266132464200156445ustar00rootroot00000000000000qbs-src-1.4.5/doc/templates/images/000077500000000000000000000000001266132464200171115ustar00rootroot00000000000000qbs-src-1.4.5/doc/templates/images/arrow.png000066400000000000000000000020571266132464200207550ustar00rootroot00000000000000PNG  IHDR,otEXtSoftwareAdobe ImageReadyqe<$iTXtXML:com.adobe.xmp HIDATxb?PL C :x3`(UtA@1?b@l ˁb(8JJ bRJ>V) .ⳃlPz#9x'؁vp;g[rh~ur0@o!nIENDB`qbs-src-1.4.5/doc/templates/images/arrow_down.png000066400000000000000000000002611266132464200217770ustar00rootroot00000000000000PNG  IHDR ?tEXtSoftwareAdobe ImageReadyqe<SIDATxb9s9s037oaIII1Yf̀ˁ8ahӧOi Xt  MU7IENDB`qbs-src-1.4.5/doc/templates/images/bg_l.png000066400000000000000000000001441266132464200205210ustar00rootroot00000000000000PNG  IHDRx+IDAT(cxɣG M2Eoh#? hIENDB`qbs-src-1.4.5/doc/templates/images/bgrContent.png000066400000000000000000000002251266132464200217230ustar00rootroot00000000000000PNG  IHDR tEXtSoftwareAdobe ImageReadyqe<7IDATxb|" `TQU1Ǐ"L~H*0. 0(IENDB`qbs-src-1.4.5/doc/templates/images/blu_dot.png000066400000000000000000000002501266132464200212440ustar00rootroot00000000000000PNG  IHDRRWtEXtSoftwareAdobe ImageReadyqe<JIDATxbdn /}cJ4@DAP ( eL@tF|0/%W"/IENDB`qbs-src-1.4.5/doc/templates/images/box_bg.png000066400000000000000000000001311266132464200210520ustar00rootroot00000000000000PNG  IHDRrcf IDAT QJ6mHB|F~oYIENDB`qbs-src-1.4.5/doc/templates/images/breadcrumb.png000066400000000000000000000002061266132464200217230ustar00rootroot00000000000000PNG  IHDROMIDATm1 0 SyWYML>eBZ$!UX@"~q}vzf&"3{u9SYYIENDB`qbs-src-1.4.5/doc/templates/images/btn_next.png000066400000000000000000000012611266132464200214400ustar00rootroot00000000000000PNG  IHDRa pHYs  tEXtSoftwareAdobe ImageReadyqe<>IDATx|SMLA~;ݟn[bSb#?ěIʏ%1'=INzՓg#ы6$#AzI$$PRcfvlwІm6˼y}ol/|hޫNhm0t{)OQgubYQ vjmrγ@)XרJ >Q@fqzـ mE-G!>h;%) |[`wG k&>g~XcO""N]L{& |X]wZ 3>Ml&ࠪV+gacTfG5s$T&\ /9+=W9<Zr3\5 WIVk~Fylw\y jۂ(ubM2nF A;yڈ GV($nONn5Q_O\#IE e[ۡ0z>$F)]4 WNf<ɸ@(\egz:3P%')w?/L976yGG4@]}eU_\ +4YIENDB`qbs-src-1.4.5/doc/templates/images/btn_prev.png000066400000000000000000000012441266132464200214370ustar00rootroot00000000000000PNG  IHDRa pHYs  tEXtSoftwareAdobe ImageReadyqe<1IDATx|SkA~;&kikl_T7HJ*AT'Ez,^Z/9E(#M"٬;]Mm>ؙ7o!Ưgmh'lp'-HS>ECDQKPLhlNJm J@K*Yf-pG[plgе3SVbGo jSO>H" Axxҩn_ur+qϥ<Ɔ9hJWD[#DO̵&ƝEXЙӠf[<լKmv895mMOF˟>%oc–~k0}wf@䒈5'Q_Wx-T 6`kG\l}c0#u$9Xbth_un9ڣK_ >ױVMC:1-Q"Ågʡ)w~ ^R^,ɮ(+:[.klȃdߥway 0IENDB`qbs-src-1.4.5/doc/templates/images/bullet_dn.png000066400000000000000000000003461266132464200215720ustar00rootroot00000000000000PNG  IHDR5tEXtSoftwareAdobe ImageReadyqe<IDATxb?.QX?zĀ>H !k +L?HqN221'#??3gU;,bхAT(IENDB`qbs-src-1.4.5/doc/templates/images/bullet_gt.png000066400000000000000000000001741266132464200216020ustar00rootroot00000000000000PNG  IHDROCIDATcm@Ï[ry:]65+T&G3=Iv-IENDB`qbs-src-1.4.5/doc/templates/images/bullet_sq.png000066400000000000000000000001121266132464200216030ustar00rootroot00000000000000PNG  IHDRoxIDATcpY*h+2$IENDB`qbs-src-1.4.5/doc/templates/images/bullet_up.png000066400000000000000000000003221266132464200216070ustar00rootroot00000000000000PNG  IHDR4tEXtSoftwareAdobe ImageReadyqe<3PLTEՔ՗ԓڧԔӑ֡ҍӦԓڢ׼߮ךF#D5IDATx\IEц",&>]md ֆwޏPU+vIENDB`qbs-src-1.4.5/doc/templates/images/feedbackground.png000066400000000000000000000004071266132464200225630ustar00rootroot00000000000000PNG  IHDRddpTtEXtSoftwareAdobe ImageReadyqe<IDATx 0!k"oekGOk " @" @" @" @" @" @" @" @" @" @" @z#A֜IENDB`qbs-src-1.4.5/doc/templates/images/header.png000066400000000000000000000072701266132464200210550ustar00rootroot00000000000000PNG  IHDR.~q7sRGBbKGD pHYs  tIME5<8IDATxy|TǿL2@%a DYE[ @Z~dTFP@C d_!}L2Knfdgs>szf1+Πh.C՟̉Y>q8 y5N2T5S"#.pscsq6<a2CI&x"b\ESu:Fm& D,_S_פVWi(9jEveώћ̷ބ .#~zk|6|# %KWu#-Ì' Wc70&dOzUl~^5Ǩ䜏i(mRdgTɲUL|o5"k]O4{M&MRbwZv^܄ԏdž,ry0,i{5,@VŶ7cϙ1rw x?OK]$7ֵ4M칺&Ժ;^g# B*`DX6LyWKN@^êo ;.lIty(Eq ԥ`_ Ӣr j[*I+iQsLNC z);F&LbbO}vϻԟϳ$T^P$Ӷi8NjQT  O?].dA.VDK'ޑO=ԿiXwktj%*MRb1Y"{l-5yId*i4R%Eb_I+=DiC-fc_3y,y]]2IoR\ԗ!SXn6KosuH4%#KP6¥:dMe}8#_&(,v.gYckĬ:W~BHH?la9\gSLmAzٱ( Ruɫk%dWnRLj~&nǍ=_)muYeqxdVZ\Ϋ?.(]ZK"LE:s?升Aw6ۃTp)#e%=4e 5& i9<~S}+[ɪ:ogJq2*N&q ҞQ]/׷֐Vzs7RȾ.V.uSc/?Ŗ%۴L: 6`dkpA^A{S^2\ؾVu)%]z d%fŸ76 'Ooi(12h<}e6ej !Ej.ٵeS\΋X*umZ֟zVx"xùXG7saJvr{b6ۋ>CԬ?KiM/FBw$e ۱:U V&iQshT׳oTSӢ`u$"w~7/LMgVr4-:\z?N!\2ԩJ7~EvuV>.n,]XjvAQ-fArw_uF_j%RYUMZR-ȏ~mKѵZʉsE9T*h4ѵeף2+յVl/ @xKlXv;KR8c{Dr"8ZO5~|a*k,"@[3ժ*YBണ I#K b&[&7Q 15ڣ"Ѵq~{qp&WKn͉c(QP\KUTqf)oCG~ʳM_UYEAƟ"D>pss9yE\ZR^:~J9OC_U71ղ6q[rp&W $$fly B;%;́>z8.'og\T|=i6ؓr2W )CzE0 a3pYaʙ @xYzrp&WD>}UHnnt,p]Y $r&E4ۨMcf΂l%m?=,?`ɭdq;ޡkuAzp=%rvȮ``?qأwbsid;`o!&l#aOjw[x,M#V7O4ki4VzU)ࢸ0j`^v ek-orh͖$-MeudU}k'YeyzG~ϼL~mj]+-Zy5ٕ>bu ._OJZJM\'Dfu~sѩ,+!}F29bS_]BglݳkV&l2ZGQsĭR\MC2g^60L=uM7Pi9IW:,\=ə\w ڴt7F4Lx)./6JކwemcDž7-%sXw|IS go?79DzլK]l_gET4]7lO;mƵdB wawH z+ YZEVkr0 N.3s).{Ϟlv3yl)υe[N˫)Qy.c|t L;߭v%FNdoU ܽ491Kȑ~1lG(ϡIӀؓ0h'v7.!2}IW]JD<3ċ.3[b >upJy4kN0G9h}DBTfYB@=zFcKd w&0or}y{>WӬi +iQsX0b*M%{p7حPo>ev\pavAk;1\pzfG\) TmTR^߆]e\p[K vVzºԷVmӸ .pG_r_IENDB`qbs-src-1.4.5/doc/templates/images/header_bg.png000066400000000000000000000001621266132464200215160ustar00rootroot00000000000000PNG  IHDRݿtEXtSoftwareAdobe ImageReadyqe<IDATxbs6###IENDB`qbs-src-1.4.5/doc/templates/images/home.png000066400000000000000000000020641266132464200205510ustar00rootroot00000000000000PNG  IHDR>tEXtSoftwareAdobe ImageReadyqe<$iTXtXML:com.adobe.xmp :*PLTEsssssssssssssssssssssssssssssssssssssssO tRNS 0@P`pU!jWIDATc`*a޽S{´{.ɸ g1Xlwȴ03000oEY 3]\X\\͛F78IENDB`qbs-src-1.4.5/doc/templates/images/horBar.png000066400000000000000000000053671266132464200210470ustar00rootroot00000000000000PNG  IHDR⢎ pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F"IDATx% j9MIENDB`qbs-src-1.4.5/doc/templates/images/ico_note.png000066400000000000000000000012111266132464200214110ustar00rootroot00000000000000PNG  IHDRk?tEXtSoftwareAdobe ImageReadyqe<+IDATxb`F\Ox vb$ @|fͺ@5  xû7_~301p3p3Ij@P_Z&pKe G,uD=# *oȋ)308/(r j,7Z&D?{RvfcqǐGg"ҷ ?qx^u~!9k{Yel-AD14xA>G&v*$@ @ @T  ȗ8U*-h\*Aq_ hU>HMl  :lIENDB`qbs-src-1.4.5/doc/templates/images/ico_note_attention.png000066400000000000000000000010211266132464200234750ustar00rootroot00000000000000PNG  IHDRk?tEXtSoftwareAdobe ImageReadyqe<IDATxb`䴧+Jv@ f1в} A}Chn1e >a`kPP?Y,d?5Xϫ *P*goE-&1H:gQ`oAA]OuA)ط`C>VnY<>b T[d:E4{%P}௏X}gbԷ(!_>DoaA ϋ`}ً(5X1V߂(Jl``נorbF-bĝj/b}˷ l Ç oi2z]i1u0/ S%@+@xP 8CIENDB`qbs-src-1.4.5/doc/templates/images/ico_out.png000066400000000000000000000005521266132464200212620ustar00rootroot00000000000000PNG  IHDR $ pHYs  tEXtSoftwareAdobe ImageReadyqe<IDATxڔR 0lJ?Z7p (:dBOɋĀyI]{OMӔ0Vses#׃IP@(~K, XnN5Ex}@@(#D4="|D#@"!z]顬tvvd3eNv@0ě&Bׯ_a]]!"iG~/28/+95̣>6Q~nBۓ/1]xE-DM>k.=zم'j"j#q`>hy]\\G bTQ.//+~UtoP'yZ U#}<8!j0 l tPN(pt`6}U (4ڷQ%h~x$hg|sithzv}瀧áMy7sxth|ݦt.//d2I@@Y98u}}G@W@h4J7}>Yh@ ep^^]}9<0;et:|9.//+Ű sd23ʡ=_c ;@~`/H蜯^ř98oaR.@Sy38.H6r82@}3=9X@OĹkh{=gggi:.@7"0` {s 9<ǏuCCDF>kX,lta{DnCIBDCǺ7:=w5̈́^@BrI^뻻;!:ܰ|C >>>Nog?j j!EyA9矾t-5f"Brm: Wқ7ox<>{.~eyIfNrL&tqqi+h=4C >t( c ʣb5kT|thF<5Bt(|]vnu_4N c 1E/<?Z(v9Sʠ0Y {_zTP@|k?_ g7l63`g:@7z/rz3ʰ}>ÃW#sx׏?BW#s'z(}!v;;@/u.f^/rs|GgcWқ7ox<~,]U8+-&@KT7!z>=BkυtIu5wGx^%s?(;sŽs{`^|CCIENDB`qbs-src-1.4.5/doc/templates/images/page_bg.png000066400000000000000000000001241266132464200212000ustar00rootroot00000000000000PNG  IHDRh LIDATc?(<ɓ'`S5t^IENDB`qbs-src-1.4.5/doc/templates/images/qt_icon.png000066400000000000000000000112471266132464200212600ustar00rootroot00000000000000PNG  IHDR;G6^tEXtSoftwareAdobe ImageReadyqe<IIDATx[{p^u߳_$aɶe[P;'!q%3 1%a`N!Ӵ?С`H'5N 61ؘl,?%a!zdzw+}WNp1wٳ9M\>!?pZW9nM%\L2a^vygv#?c/XV 1LyG6*'BDS2K?c3{{P1'x\d /1IOMJ*r %`y2=JwsBϗzk&,QrWL0[.IQ/DpI"mDI[j7t{ eڼ2{%d Iȵ~@^diE6֐'Ԥ+7M {n͐s~c-D)WkY+7Q>Y>I-C=Y>$R\"X>7xv{"3,AKPXr9;(Fj"AhgP*B%3rT9U-䏩Pm2TQhn-Q\4E IZ[dyGLm:z) 8ZP>9Eup ʪz#W叫kZ|gCzk\ 'yUr ;`y56s)`+-fB]ץ&^SsZoo|ǟ끟L;յpB>_:G٦0"*$\}݌I1e^"\E;@a0Qn:e9}lB՗ d+j*6 Fn+F^R!LY&fy-}*>P&N+dpui,8"ׅL+lB(HlЄGTW_m.4,=n̏ت &0Tի^pw¸Y}O0lژT0C3y(3ӞgpX, f1 %%K!|W:quHø hu*I12sGѠ" ^9Ly&d|TlMiƁeuU^F5T0x xM6xWW|l1Aaz 3YqtDsԐDOR}%)4t !cFw4)XF:<_Umns8AjZ5GV6 DLŁ:̴xR]W-Xn$ʹ8 nPw f„6CVyOv^o7$8ER@ a"aEr6ap}ռOuV[ ۩'ee!9w h{ח?K~t7%Xޕ yڷf.\Uӯa߿/ƥ38UTV6?.lp0ɹ2bfv1&!ҺX}ETN l[{׮9&-u}KD|Ƭ􈹧P2FUiB?[1%;OuXQ/kJY]2v`ty,كpч,9ܽrB2dWwy͒n3-5UF}ͦE?$㽫bJcUd~>z~o*\IDK{G;Ow]S}` 3p=Mܞ)¥޳شG.7NOę~ V#,_] Vgʴ^mk妁@i0A1k;9LϪ5c'_1>:OfsT/~h<^lx3jAse;̴eL1]0ϙpW`-M?UuG3xǁN~E@pj@lh`v3Il4%m gX l j V0TxX/2O1lZ6JX,.𤸶):g֚18Bpm0$ xnT~74ι /? t{PܔT|`aktڰKx}.Dž sUYB;MxhpMLNCX/d˩nȱt{s(0[̡蒋%ux<(9d+8-Zss!Dh5;*TnSy!Ph6ק坧o?#ToV1 ey{/>)-=d\愕=t2U<-8<#}i3j ‡80 *yaj]&Vo0Оru p1Z=[RIt ï3K-!]SGpp`t ngwhP7'tbcAr.: *2rb"K[\,A?B= M"- aɊH!1?!,d d=befN>]Ic.lF61 Zb3gA#Mc_XdE7k_$17|yC,FwWmZ'/zR[ #VQ!,b -%#!2;/ZY!Nqjc6#Pb,O e5.=P_veVf*gJ&moo6dKq$>|`͇)" !, m#=!2;/2Y!6  O!G#H;2^^H+c3d;JqBfEfZ!_m*.G>Sg<(hSkRPp!, rB1 OD,U  GM& !R ,D(HmzP 2-FbnG}5Z`ch+3!DIe/;cZ !, dV,P33fA}EmE"-,$Cd{u?F|e=b 2(],G3K!j%y[_t e?QF+H5"0(). !, rO:!2;>W."X2Y!Ml|sN1d^X_pxk7hG% HmFnS. CCJ]PL6^j?#V5' +)!,a :8oC|u(U! 3s hP'X*h^;edj%dXXg(D)nePI~q='/$ ;qbs-src-1.4.5/doc/templates/images/sprites-combined.png000066400000000000000000001721061266132464200230750ustar00rootroot00000000000000PNG  IHDR H=tEXtSoftwareAdobe ImageReadyqe<IDATx \e%NoI:$aMz;0"* x_:QqGt,8w¾&,@KdtN/_sӧ;yCj;us<$F(P"`#8J: @@t :W)QH$ze=,5t :t@@: @@t~M3' 6 tѓG M :t@@: @@t :t@@: @@t :t@@R  b#5~ gl% 6Mq\nh`ߣ;t@@~%}\ b: @@~b͚52fk7|S-Z$+W)--6SYgFzkkZBldFІvjC6tz ϙcʘcU+?n-{m梅1ǝ eee[{~ӎ82c59~.-S[U0Ӽ-׮ v۸:̘yYh&dll;CA^=t=9Tm޴~϶?ur1Ӷ劲ߝɲm6z،}mZ?n~Lݲ~dw:!y,}lN~W^|I'Co1^Gכ>뮻; s@/=Q?ǻ^isC>%o/)0+k8!ڽkWzwݺ5{ny,G~F[[WWІs̄-{}9SuZw]ʪu-yaݮsq.q>3*v}k?ݮ/?X'=)^vyOu6v8-hv5_OiHw}wrDˮ`gɦŦ'lj]~N_O=ia ۷mKλleߟBv>՛g=9 ?[l]6|{#Zx}rUW#<"_"׀nkgm5iנ?LO q5w.}ϭyyDùK[c_( Z. }ٔ_CU4-JZ֢ʜ9sZFmf^˪~֧s(nC{b@OxD[%~_tdN!W&\ö:CM|,_<86CydOR8wr-KOA h nP6-Dˎ aklg\8[msJ(4ۚhh fWkE*L.:_[DweK _Ԧ8hĐkmVnٓ1=XvZBCqOjӺCkGK,W_}uɄr #G4ŤՂ bojK_2k\0[uk5@s.$8t۷8 ny{+,v@opC >؞ IMmm.軶8}u]ݮ罚3"#7cŶN͓v;k@w 8unq똶->9Pk)u ;v5֞ۦV+6k8|mM|1<}ϜPZwͪb@6>U9Щuw÷A_ek=l?t ]5@75-{tHnkl['4ɥ'uŌt7a\X;'$qCx:!rE}eҥ~ԨQy59|}ɧLs\ùyY}]Gs/ / ^xax\z,%FZ% 0c3;H=jݲ5dg4d>yz5*n. ü^gͲlՎHGݝ&K7mSlٖ搪}?1iw tu辈^R'ce$Cnvƕݶʋ5dOԻ[;kOjgmnlkSvmM5!?_e(t4h?+VܵeQޭ{"@ JkF5h0JvGgll7XjĆ\MÊ=)b/Y6lϝ&Նuȶ-SZą{{p66@Ӻ^zL6] z̴A eEokfimM޻#ֲ5: tz|eWhkk3a}֭6y,ZB4(f[v!ag!ҺKj]2Dž@]gms7CtolҚXv;}buԛ֜{6m'zQv۴Z5XuLZVmέMU6'-pAûlۗ\v\- ngu:;{26_ғzbAk˵e9s¦E=NZnY?kooiQ;::Nr'͓SN9% DeִT/5c:y\Ğ~ꨣ'5\#cǎx uYgmHtׯ~+SFm#oܸM/Ǧ5П~Lk }p`v : @@tJsYql! #ϐ#ϘnCtÎ놧.1g|1bX?7{z[^-Y[d,%wkg^tz\[|˷FɑÎ4/q˵-6n#n{w72D:?m.8vGet{ *1/鴟=N s1alS Δ劲nviy}mZ&?n~Lݲ~dwz+>rxn[,KK3#_$z|8?55V6WoPoDpst G6!et~7aP߻;}4gtq;t&&o'sק>0Y872z2zZθ7[w}k?Қuswzt{i>ӏ;msn[ƗIo56!=>ǡ=]^rW.S#=)׫*.,ݺXU59[OaڟY3ۜа1g?97hy5(x FRoN q5w.}ϭyyąt0Qc_( Z. ”_CU4<9NU?H; 3Z[m+W`KIM0v(fm^n}ǩ ,-K˧|"[wlj~Nh]-wyss(n{b@OxD[%~_tz\6ʱhMmuoNPn|~_$>L8LQ頨nP B=y.;.t(tw_ek>㚆DZ5ZnkWqN~Bj au )dϧ&lmkvߛuusnZhαb['_{}qƱ[`Yxi-&/moObtyBǹ?V+;qrG(cG5g}}͆i˭ $ܖ!n=}ɳmGwݵyot0cPZl6$h [hcKU;ˬNsZkMm>۷7]Nw|Vw=8U>剖Ϳ/p*ZlNt1=6z}up\ߗumV~]M{O 57E 5ijPH58 6ޖ!Xw;{[5&M=l`˧myfT\!?3]6uvO.Ņ|/@tZfw=~1[|m+EsÎ ϾPǏ:#]Zp[S==d?K ::|~(aeۀ2U.]e(I~rƬKƺ;n[#7]ުUtr2d뇮NGm.:l6~α[ObGwϦ[cVOwZc=eh~_͕ܝ\s<~48ߑ'2^.cܼ¹ %wmp쭦י}p㗝-F1knP[kw{>=W&vݖ5n:[3ߊ]αb{Rۜ ph6'+/]z}c䉿[mNR|۞5=uh*˯mƮϺv N's_O}VvUC¾\MC-dY*4w9᫫m]́ w|w_6@Ӻ d6]ͧsOd}O՛¶mg>oFq50zIK~-E<>bM;kXFk݅Ԋ˞&t^@ Sv6ej >cZf{Y0FfA݆ŪA.S Z($s`8YGi-gkJ6:Qm^kﱢB#kYuBhL E^2Mss^ݹ/߹۬74۸=yu\V[[n˫ZC؀c6ǖkۯܥK3q2G=COxכX-Z#vq?; .϶uLZkLGٴv krl6dЃl˺.n>Ԋ.s|aaMgtXzvfWgt%XTilY<5@M=Vw f[)z<,7.6uf|<|vz^qƺm1@q=Yӟ}dXͭM8ѿkq5;Nﰆl #GayzL+8\eGhSDF2kve;EzA5 ~1? 5XW@G@(e@,f5: Џ0;#?^mt :t@@: @@t :t@@: @@t :t@@: @@t :t@@: @@t@@@Mt@y~f=?:Gy}4).'fomo:hPWt uB:Cܝ(7iw/7^Tn8@ 7Grۜ<[_!RQV"|9'S[s>[ ԸN@! M8W W|T'Ri;2gm2}}\2H qX*G@@̀Og!#D_wTv\C$n8:-Al :dpJp~C:M^ 6/Ҳ/ /~|xcm.jΝ' DgV;+'I]Eqh!2f2{t82Fq9pn'G6~Б܏v*t8H0WE`^xn sH߰]Y_W1Bj*嵟{myC2ObO7{MaCMY?ԴjΣ` t3~k-y[cA&7}6D>@CV .}uG:=g/ݏ<={f lҝ|/CS z[cyN@(~H'@ϕd*6:u GmI0L{N-x$EúKFf$tTiWls3n:g\6!4 muۭelֶwo=c:8sYc5F,9cl |fY-P?5].ҩEbtgֳa9 Ȟ|ӏ=;Nҡۏ'S/-ҽ̐&n.׋\ :x9sم{7 gPY0Lsw~,N뻡y ߜXmj-M;Ly186Tc~gZ{X5w%wOHb.K@'@1zD<3t&r;u=%f9/3~;#59g-ܥH`$#?mϪǼَ=`GOhػ4n8tҩ_Eб?]hN/~8 :Ov=w6_^߆/u3ЮV{}jH'@iڞP$6y7lk՛2`9rq43޲A6^&hk.ݧ]"gq=os}C29rhM M4W}~{6рg~j^˳Mb7v=Y ru5rgW;7.G1(&@1 ^4g9i=6_FymM|jtk?j,^ؑd_˒/Γ/޲?⠩cc2j wn_*t0&G/Ѭ?yMozc۔' qmz4DhTŖ޷~*y緦&vZssVtvr/27,O{ҌtioZ{U_^;۔)]5\k NeKr!֎?=ͩw'$Q:[S}lmm6۶Dz.wxNǵPP;wg5`Ԡyq?2DcOcŭ= vumbi6%MtE]J'mg|#9A` ˝jf?2<=ϭO.eЀnR9RJnzS͸ޚvϞ^cڵ?7۾KY~Dpuڋ ;q?|i9cYn&Zo>0j4k ~w΋&hjyX_lm[> Uvms Bziq_2E宣?oyTL.W篯i~g=ՠ'8'XvҲI -msn^hȴ5@[j˕=}pg69Bj k]\vhyŦN7mf2QMlS'.V?f6_\ q鳞"\=쁰Jt(4æ;P~o^셛M8o,|3,` :Ngù*OTJEbPSpoź4+z }fd;-Fn~izN2?= Yh`kä_צ?~fj Aqq{6} _ f_i|-ݷ:l5|4iжOkRT5:;;b qRkmogel^`F8sެp=K9>v^t v^:M;ϿuwZn-=t4:v^Crtw?oJsieM Z|ݓL.Kj.пd<M؃*IVm#Oݤ?.s"x^yw|b#Sa[iYEA?}^jY?_5ٚ7emPNH5a0vBJ݀ߕ\?p0ONXî=9Qh9 n8&6nY¹]OؒymM~ɶ9 3g5̆0.0c޽ε n01t_l-f- d9'dYN4GOE_[uqѶtrt4[z!ZcnY<"fzNN3wOdm~5 ͧ&m^v,[me/oGjsG~S62 2`++׭7v3uDq=w9/F9uж|NvrWp=cwg= qipZeRg7ߜoNmSNF~vyx h_) psIe]& _sas?xDn~LՖe'4X+?S?B䥝?tekfY:݊{L;hĕ=n$0̝626 nKm?.C/ q;zr2z3n2[N61./:XZʛWɶ\b϶'ai={1U׎\n^kSrԞ^]p^5I[~+clp+fh3^ Bkpt4`p+'zzҽQBi 2Z(xrM@K4֜;5lmg\ۛ_Qj7?Soϑfs?&7?|ڙrѤ2~g{HklTmV|tm[5ZmHANp^w*wa+/i=r*nP;M%Uko^`mn892m@uEZZ;dTIfͪ75}EyBHc؀^S1DW/׾|YQLoj";n6=/6?M>m4Xttru^b,^cQ|N=ڏ7M2WͿse_UV{i9^2˿'wJbyk^`2{wD~Fy;I ׼xl:W'CIR[ѐ^@Fq?qY?5j] Un ~nS`fӭ-
    ۠lŖ@h}Dl+6w-MrNt{27YېjSyz9nXikJe/xey<~j͂6򐌓R_ yGxlW#hwo<55ظAfr/a5@Qά.^=[O\v-f8+33Ԍ^+[O#7Gy\_z5,GB{':@]u{/wˤ>&aӗ^min5':|䏖!V\3p2@yܯǤ8ht[C zښxw}]O^SzKYg&ˏz SSIqf{ؑu mmW׹~vprmz go9Zn]|y²{I5ww}<Ps!M{7Wq PV)3Myw~ݩ#_\fڗ#FځdVp.f^AGt7(l\w`)acE|+qvkmM/t[?GmbvBÖ_r{Ćb5fliF~bBp7>mi2Mm8˱6zb65k0ְnOZeiⶇW(4fOVpӼ~:__}..pmN>5o^Z:/0 4HE65:xt3'o%˘D}Dqf4^zSNrt}]w!n$|OiF2SD"uvp˪M`XsOPh-q䑆K':[}up252p[%a^\;ht.-pˤNonm ˭ӹSN486m.*Л'fGGzr% Mo7{ҹ ǿ,7_rg| r֠?deӂG6ǵ+Q9W@A 7 MKU5ƪ'O7d&׺> 5Sf*]:6wGwwH\- >}9/6Ͷ٬Ъ.8MNm tn$|hNTAIM=S~sL(.U{|6$kvút^^::.FWWj/R]x5p(47tq{ݳ˵I'sww^]68~4k~] $Mx3/&%}+Y?<]0v#G$Wθ]w˻?'_==@ jmȍxs֛|-hZ~r۳?;ۛ_N5o<|f%Yq!G[y/rGtB :4wNa `lArXc _}98n\3?|OO^;_j3՘~?˻ۍ~m{𠉻 ~0{ s7_xTHyBz9\qAòN_ɞtC*kQ[ҶKlx"\&@Js5$.T',O)=V˨Y~ewxGu?`j__TN|O#'L]yjzSV옟P.=;A@۲Gz:)ݭJjjSFo^ FWW>4*4"[v>ߙ1@5"y ]彷?lPݽ;5&z{y2mQW+?c/:Ki<8kAf/[n~,h6LqO##>3O>vV܏L gs+/+o=V>\ʤ/w/Zwqܽ[*_Gʝ|/k3vunkdwe{s'w+mR:zP8W/Zc/ǝ(pgwNdkM@TQ`dwss3GxLD8ȨA)Sx xы, n#9f@9w 9 BT ]^R9r1.o[sNMԃ3F8)뜺I?:wZ@=ml *7U0w`89Q`iB.sj{^d 瑁ؼHs=ڏKf 5_w/`ъrY`is2 L~fſTcg<ë9L_mc~y[F΂npvLbӃ٥>0$Z9=L K.y)M^ SNoF_tb6icuU`9_Ɲ$M;U ,Ɏ-ҴwKi<:\|f&v^=yHT˙w;!Hp$v6(Rn:joFZwG`nԩ:WmyfSd,ә<h:cP7`7F3:{ы{v5N@tP y?cnOb&KLgОՕ$7&~'?^:M-1ѶW;:<0+'Hc* ǘԘӰ<|5:4w@Qř] ˘Uev@4TMFIy 8`zL#vy3j*}N#5aqFb}꥛w A8Z#>F_ 迺v mTE.۬=3>|0fԖ70m^5VE8s]Mo(y#d6O񚊡200Dˇ>b|g#@Oz*dMHa k3! @wy~ӚY_zo5q_& v?3 P`@t7J͐ ptt99@@'s⵵}(HP@@@ {Y7mVh!8IZГ|ơwl۾kƍik?yL (,Oj^{_)vmcwoiS_5pBѢErJiiiRikkj:u|3Z@ꆊuv4-(X:گ_{}{/M$u7ȲeKNdԨQkKQ[Cr@)//Ҳ2)M&qBV,c-~}\uU#o~/'@ʷ^c/76]ɞ=%h}Og;:|'dʊYԎoK R.;>~5kLM.܋yZ|g>O==Ϭf}HI'ث;%W"FozT (RQV"%2rLlyͽR6 q;<[f@1շnMTm{s3K2+eok-{[ ~{)|i(m2@T!~VZ!߻gOO \qpB;n ~ʃ[ry~>fAT=aHyvmH2Vȇ-u2liho7~zykMB6rD!cKJAt$d7Si{QVDaWī/ax5ұcmƴ=444ȶdP_vT'zJ'|R.6lɓ'\Y9P=P%KRZ3¹swDxߔԦӝXC=asϕٳgײՠk ߰a\}L^oqt@?coۺE IݞI2|'Rσi;LN.n2O,KN]mRZIcmۥy ik )IroZ9jz5sh*nka%ChގPvS}f[lo}[o~󛲩e CU[|+ջkdr3wíjj:p/\xnVӚ`ܸqj*0`ڵ4gd̘1fZ ?0 ^e$ʀ: NOJA {-嵭ۓ9mvjiLSx+)h6k7K jKMogL!r͚5rЈ}6ӷ|mwo2q߰\liM'?)l=Xn͜,Ϙ1方ftlgV*{[ڥb$ TU'lے֝&4kطhaQ2WUUeǣ ek@423qbpړ!1hvI`Wtޚl˒1gP Zn˻iӦv_cԛu_x12($F7Fx:M;:Ru8ok,0^ɛWĀ>7d⧦52*ߐ!CdŇ-Ҷayl}T~Z]^>L5ĵ-6l('x͓t^%O:|IoWdѢE2jԷeKmwNݷ#Ze˖rݎ>:g?oЃt :pLYS0'_317A]ieƁ ǟ8)KI ]Aj^+++3RC;6$- d}g2d_\<:טp|AɷoN>XN:N_{2sfy>˷ ~Xnͬ&%^B::LL$dWk\w3i⮵a@Ob4vUeyjY Z[Pӵ|Y/ִs޽[^bMs+vwyC1}u7n NjG_۹4;ד ^;YzWX,R9:(yMr-sWj\s)< ~Gviή2RZ{5+7_&N(Gi: ڌ}ǎZ !˞={-Y~ ϩmu떛k^F aˆ.+daΉ]He{CR /гA/ϟ?k=zVk׮5~_/(B@tA'A#劏g&].C-GΞy6Y=Y ]$K]MܵV\wl0X*jYuJF@߶mY/m>p@0|`oCYti= g[kkQ˪'/춱=Oq-_dJ)I%cbkϨ=wȡC˃oT^' ǎ:KZ:vAce9sɽoO`TTEz2fjyGZM4I:nN}%?[]])ָkM釾wox?tٹsP~xX''6wUQ{@OTq TכG{wK.[l2 rSimow.?kݶ3Ysc/}bAχMd}u }Qfr^wӷ8fO et[2`{M`oi%woLv0;$U^ =^/4qJjjM3Ųu XiFr_mljrk}2tP3*(U=Zt? G>`~G{MwPa-5*zMy%ʤ<5ۖL?sssSĥ{aj]Gq/blmk3' άuib1c2Czoooo+U{k/.uG{1߀n w.&Q5TunmGFʼ22YYٲk$RP=4ymfP)WMjҽth/>~u[Zt@ &c{\sE :4cw`𰴤LV6#]0KnMr+ͯ}o.--Gd|49dYEӳIx^yEu3,'xBn4Pnk]#yҩ;: = AmI_*d/cXV-啲i<_FZwɮZnmt/5mnz˸ wMɧmScx)HnݾLJv,` 詾u*7aHGJes/15o?!*Z7õyr>@<65a8_+#bg}L:ul q!ݓV&֞>Q4r/++K&G7]ҁzd:^Ԋ'4.ʮMm%RY2\¦֭-rHa3nK2^{o/W?Y\Jmgs\/ 9tʔ>i{$ݽr`;^e^N?_RQM`?T'_G{Ls; {ӄ\6MFq/1)`zml;t7?tIߤȧyF~ӟʕsd j\{_ʔɓtΣ;ҵ@Ie8At{N !TzAxԽo."K\O]$ju{KYU-;Z}䇷*7t\zbɩ"??Gv٧߶NA=#Kmtn0i{q5H;ykގ4hڲ/\?e_/31}cçnIM=LnF콯D{eD:7oד~{jt}?WBR52RAyK;CI%K#T&:i2'J-w%ٲKOlN|rՕW&ٺu[Քk۶m]/&"w4ez%\r=\BBzwATl Q4!P{3r\ٽR狓}>yyХH\ܸsyQ;Y(w|]9   ?Ǡ3y)בD)|^흏3cȻ>M7!?M;3~C֢ ={pwbĈ|r7|7vmXd v܉^0kĉXt7bΧ@8 |;V8w0{(x.P(#r   ZрCjrEEv?a\vy 53#3tzB2[Ց(kܹSY`(RLs'QX ;V6%Fnx[nlVW;{Y+ a?Ck)NAAqmH.y.Gqf&iIUZlRe{7Ok(?%tځ!CHlAAAAG<2 2I;2Th(Lb    J   8uAAA :AAAA8L8h%y;vcNqZl(--EEET   7]NJ+㙙tƈB0Dee'LÇAA_Et9_fә"N+<H:AAA<ݎA\s⌢&M† dAA!wƠA geeeAAA777h%Ai8|>:AAAoz$D]    :AAAA$AAAANAAA :AAAAAAAANAAA$AAAAAAA :AAAA$AAAA HAAAANA/((@ss3!#bЉ   C ݻw"8݋>}Љ   Cֆ]vY"xVNJ+PQQA'   *$EQL2TZZ*"YYY$qiBvN&$)~J%"ǽwuͤ߻}~'@Bu2gL/{+mmm̮c]C^Our󑓝}%듗^%p8$AAAxعlMىa#a1E {[ z\ ɒde%slM.9$=}B[sKT^7Zb}s.gb-ؼu"U:aYQR3NEu| z~?EWr:=z:l:4|H= :AAA8A> |1jLkԃ` 1 |qnRloI_?FW߅Cu(9fjٰ5 0}#nG~V:,fp(EHxyE;}e.gl4ٯݯmNAkOooGI=NnN򼼼ؼ!RNAAs92y;jY!ضwP;[77"!Y$Ud9|p a8,8g|d5υ7qs1'HK9`Ya2`cNb'Z.ӆHf n\'QZ+ɽ9ݝm:e^09QYճE$A'  t^s z:+` uB;NE"L| BD;AfB=|dDyիǸ=gx R2a諏6h[5glb>;-Eu"9mp/힄hiC c1e 5$Mf]Q/ٽvÕ7>R ж$ ror-!헫ɺ&-ZTw6 E[8RXz.3$A'   :/sG qۏv&r>5!ÃM-(=Sg\c#͑=yTD=M$3 h!XwYHH;SFX ) -Ee勰|r\te[?܄^!vD6]K9GNл'6?\&2@V>`Їz1ulCƛ7NNAAXw> ,>5!gCWQSj vc .&!a!s\*"?AD$7Ց >kQd\EK7o*R5y;7 OP[M-gjkb2 dfZ~&D~cX˹ͦT9W߇C\|ɥ2u&.Z^}]>]E_dWY WO[; l6KŢljOI  8m\6&)&&^datOtYISu}Z;<"11s`ӁyX?bED=GQ"]]ʞF9'LGAZ&^/g(>/7> CR,36oނW^y9"5,p=-Z#b:PHm"bApsѲñ%;o܀_i/~oY)V ~ߣӇc΂_럾vrqk1Fu}>OxORҏnI:AAA]NVjG8GQϞ T;ޔ$FXr 9h5^sQԋ^%v:<=%b^_F|)."l֭۱sv.CoW_u%zWVV ilhD: xaM>́^#s:Z2~ "w˸o_v~_/<CFW4^q,'[={`Æ x/cgI}u>|[z'R1܋p߄RIJ_m7c9rypeQoAAA'nZɹi <.]Q8ᰌNx~&!Ȣ*bbn  A& Ŀ )Lcذ!JjQ3$t۶1oXz-F9}gGlV;k&[b&I ) ܋(_\  K_ ~D͊ ]?pCudX&tL7#I صz'̮UaC~X7e:<69Oa-7ހ1Ç#-'I   DpE K^T和9v/@@o˚/FPOp;EaryK*6KCA?" 1y=LcnvV@IϞ#`6[zѷo0O13ZMLt8\~)Ŏ`DR.T]DEudQ}?LgA(.)o!ōbv"]M;x򲳰qrt6/s&#[yB:r 6{I9A'  t)A[ z3a&sA&u;z0TŽ[6ѳܑ.{h<Hͧb93X/?OODdi2d 8(a͸{؈^xC|wfjܚ f"35qj b0rc< EK=dËW}۠ڇCuu8hXb&ٰezӅҞ=oljG3݅N֟ (NAAę(iiȨb9gUEs&J$|n?F%Zqx^|HfϞ8{X,\wD̏~Gu1܀/o[Χ]Рdb?2=tn ;>P{0 okZJ9s٣gvM+/쌌_xLläS(?c+!L:&=MO;j;K vdF %=K\b;{/AA  8s/AGs>HDϹޫl0Yu%A.\V#p t/ż.|Ύ녴J|P$)'B$Šd&So)Zu3WVaX3e~N!R#Y-bKWSeD,>K~wd}.y:x'?/(ťY/XyuwqRfo4?= 6n܈0>Gu7ߊe{A44M B<,|CMD dq#l|xW\NM  8sDc3QA؅p%.%WO]"-tx%,"R՗rĠ~#XVŪkp9jj:;koફ#bJ#=#E}BQDx45_~Zluܶ$y[mAQIM&Q `$Ϋ³x8ScƓuZ19%";6% {'*jD茥{eUj=! )aVx}2}xL0gOᷛ'~ ˉF#=3 ťشy\uqιѯ4 vw=4{ |(W6_   N'VSn77FD{kHP& ~HT5ﲏLoFWEٳgcΝ /(|Y8{wdYaBBy6= 0l!+WEPg%:n sC[Ž! +;Ϻ9>}%l*^dw?J[&1Ha`97.jڽ.A1eVE݌]M^vCEc*_9n]̄#pkm_ b;6mBGGF݁- ӆE#+& -\H0Ia횵8tӧO*AAA&A=K {jz{XkٹBA#?|OFnnOI#oz\s5x{pcݻXOњi 2֭ߣG!իgĀϭH7I3nH\6wH0fZ볘w[Ue)J#/{\ O)m8T^W'ı^;)CCC|+Llj'E|3w/^,^͛' =Z=o   NW$t"[/REziWD4+bEoP(pKQV'Z{ꪫqco)*R-VT #+_rΪO۶K/jסÆ"s8dl?3yHA+wb>5@omل}ek~WA9>Oܟ lʇN9qt:󭭭ݾ.:Æ fΜux0pW_   NwIqPKqgDx/Ykƣr8X;Ԋqn*=z s?C C~q2 Kf kT|É3YTz: UQ-bV[v8su('?=eQl9Ov-oFu> 9w!!W-?۹ (~d3U!ubY Za? MMM;93J>ߧOR >\.:lCAAt-]IHqthq񂮾+\a zNNee%6o* Uo}͟}?"v//I*M((,mGE<$y3~Cfu̿*Z+;NND|+/E矋{ߺn|4\Pu~ qӍ7YoOW4.xW߿} #+S_==`徰 Uʹї8Z?<#<]~ʕ8p(8HAAA0AONkU:<" ).b5A(|Vcܹb]~9f͚%*XBI`g_W]/`tHL6 `1c·GWkDScrp栨^1,i7-ZOjAt>>Ǣa+= .W;w 6$?꘬s]p+V1LauXz9կ}ڇǟ@an~J;B(X,VJѬkLws)LU.ͅ7p#;Ԍ#FMTw߱szid"?bH'@~N|٧Gp7oCYY_\|%o^~u߸x-ٱ˗8//*kiZ|1&EiZz5]NJ-ZºuPRR]{YYس!dׅm^{â ?9.cN,7-BıZzܡd'~5B[w^%)˗/DAAAbns[Ak1NǶE#j'aQ_6suըðC`DwfԎaOp _º kE'N,l ֊9s ˋ4ѣ}pbYc0n8PLNwc \` y 6>1Rl>{6פֿk_^} t8Xj9OQث/{x+AAa.Ư?7Av\ G@:s#U>OqB}"ɳ5u   HЏH&IWԐ.MI&舥QQW_#\v$W[\p3<#F0Q#+73ɚյ(*.@I"C^MfL2y8 ae2)|IG[s;.rܱSN-Z5y"q=KAV:/:][nvvz0p s̉~3f_w rJD7xs5voAbq#{sO2XbI7=b·'Wx?Uv&m   fMG+F%If :>frqrLpWgMs>vڔr*z믫D0f5#%]b 4͈Ԁ-NI7!‘V(8Vo,;;2$g:/ħh,̎%̇#ww?("` G)F#ƙ7=l1^/>KdpHe$ft&_m?)ͥDAAA6k*}ERTbvUn@gg;7Ќ}E[%s)=*Va9>dM}UWW_K.mm?\vz8R1jx66$8ԇoUc[6q,#$kXl(f?uI+F(̫懵s7(YXLy'.7ʋIII_<9R;?<*o/   N ݖvO@"kvPУҳVd RbT+‘Q{J*l)3́;@'Z Ǥdy׾b-غkkv ~`_SSz!\x^uƎ»o'c*FQU&T`?Aaa!V!5- w}+ [ahB3O#Zw.I'ڑpڵnEJzk) B~xt:;`edjA[q"Ǡu64w r T)* kׯa*ܠ ?ߞ~{ǽIϘ:,9K|_VZvu^uKEЅCZ1>Y}ƥKI-$Kᤈ/IJr?Z=_+"r>ؘ{ڛwܘ~"DnllD[[mۆJ!\s %"  ^m[0iDgUU+ZI_n5>c>>m ^ 3<"aS^۬iyx qhjQuHQXs>F@0Bnf!+'zP-v6YE0*6('߇Ce&m7~/e2ޙ[lVj3, 7q7GU  8ws&!###.r]j;TO!'#}JK_P8,":EE3| Sͱ'޳')tY큮UoNA+'KyWc]XsE֮$sNJyyil@AisoΏ= y`tV=%1=QojBQY:BĞͳ׶FBAAĉt]?As&/zŴx+)1/PO19SP=  wtŒڶ{vڎTi>uOv=F`o (xJ.:o\PE5Me̮>'֮ו[ߥ'9v"=3;#~A~w' tސ@t-Eq (.o}K=t!!nAAqwĹ3Cnn,f*Vt,={wkłyLrȹzVVb%'TFu 1l$|)t^]ф]P:/JTvPߎ}a \Nx>%AwVvZؔnvt47qfҫ )jY{ܼg-u`DsvTl]AAqbdqL/"z=3.8vQ2De\RPTP(D:oq x7KW/E}CJO6r]ҍj^(TStUK.e܇bVqteQϷm7όӆ@(xG$Ydl`aYz`IUS1~7f diѽ %JAAA'S۱xb4feQ b?j"F~= ?2 P]dddA[[L./}͊G ҘM4W/;|heS'ON+jU'_q<Τ܋;oËkVJƽw݊=a߸( p{ɷk1చb13A7ES9MljTH4d7,sFΥ~줿(AAA|iFgn ECKt#=#p\EͼdbŴß܏sS.Rѓ-nݣnbܘޮ䢶):nMoC\F}mft 8co-ɇYÖܸvlطjm2-HPToNAAit;Ěs:GIcE]c4)xOvU;[9j]p!3];ˡ}һE= ɪpr v%&&mRT$msrUѪkFtE%xܤHA7i[].]!*\vkhhP#ZqRnOvq񬯩"Qcn}'a"y2Qo9sNU7TFtw!9B^u9 GؚC>7d̮W#.EվJ&f9PUD8Ewp` UCfc V.ƝL{W%~cxwz}8щ=-nRɳ& D]1^_[M$AAA"ABn~($*`5He 7/V8W\8)c^;;MzRf'LG nчy=U9L恩S'̄Ov]wo0@~MMw~{TeRAoX'W>G z0Op_< ?=0Wߏ&fbAx=9\Jml%J BC-[0qtCaee[Pг2i=l㣷4x t65`;0kL!UM-0i >dNqm…o"VE >Ekv?ddehY AAq=3+&vTW͹HEXZzlv o-"|xiL.2d=5\o[U~īу90yUAOHǹ"@S!T؉>U9*׋TEҵ(8ovz'k(X\;цG+&ST9bBu8oZۛٹSxEіy_{_|W'xpE6E5 {ǟ+].CiStaCٿw&^Lx 6+koL0t ZYgyfNosAӫkL< яIJG7Mjl¹矏fߎ;wK[x9`ǡ:?z!G.NvOn5ތ>l(-]"ޚMfl=o}}pv.R[^=N0 $-Uk %!  zDVp\`fj8$_^'67"5;v,xJ]nT 6)n|"ؘ8 Y/Jv TROLnIsЫvR/t   NPS9f<^*%/0(Ǡ'J{bj{sM*kw6t ,8.\]K6"khCâ5`ɦFbr\4[ >)Qq='QOwjeYo#=Ƶkq`~bb5ǃ֡ p homnKOݷ/ƌ'q?-uxC#- @iHG 4 =`%zܔNAAit!<*̤-$} `t6N6'Nzr A 驙1LcY/>bX8f;\[a V{֋Vm<:/ڪ|ia&m{((GeU7S3azhh0I}coFΣZNOG4ZK/aҥ⪫w|"џG &Ṇ|KHFam_Jʹ65hz {/zBVVXhK>9k /HͮY#  8uΤ۶lG0@0LHMUԝw'Ft՗E*=KREZZZSҰ"-3E YD:$RۡE{e1ϫЍڻOWOiNoG@cG6N\ . : ?Z\WٳgzzlݰAD=R5kDUv.!]z)st?g?Ƌ/`…^< .vmmfA]ur7PUq8׮E"E+kŖbE=W   S+輥E?o.RUSI:{RA7w'eƪz26%iHYEGߊ6Z/WBq[ǰAcThHsrHJyNE73n3Om7iٌf {jk!ٌ6&7^=:g.]o W^q]c[n3,~[|9rpw{3;|dj>z}11}̙b=}縨X <Өeo7ILO!CgZ :;}٤Jz=AAA ]"UGDemᐚBrz8g vV)<"Ea(Gy)Qm]J{H@'V4E+w=A^mK40!Bo<{6^|X}ll7@ˉuj+5gÖb~rVY`_k[,E];֮c"3| iȊ SH#   :O;v{ܨWt:S:;'Нls'?FjcEu%"S'1ڟ4]${"qqq׮mDEzB-wsHg0\v~Bڅ| w?>f̘!#=K.–M1r.Z\D;n{/5ojZ+p 7b0塩ݳtk$=!e$)VO AAA.AEQnV3u,K(<WdeS,If(;V ]kK8gXLp8,Q=izk5]gfZj^>]OQ Yzt\K'HIԞ[tЇP(42?v$|GKկ|OC߇'bPy9rP-~ҊA;RP9sE뱎 EE_oތQÇP]2220hh^}0o޻8X[W{+54!33cǍەGQk 7,Y_   N1ؼv139R#(ţj_ jX>qYұZyT o%Ncmδozr5#+"'fr/O ")1pt9rΖ>A7 3nKZo3tKۦĵ7(=ύ-،=j[ZHŋ?W rQڿ^N#s~:+89;xuޮVQ n>Fݗ*\I}?QTxm^Z*;lm^ gtM` FZcD    ,gegagu(ueE3X#`Da7h&"|w8Ve]xS. (?ζ3rXXVZlqbjm~^KRɃq>>~Vja] a;}^U"1p}]~)ҭo*pwK*։Rd:byp/nJq&}Hʁ#3PDWp7^nAAq]nZEt\skaTg5@ÇƸG#Bj>q){[ac A?l ({dUkO? K&ILB2dWj n73Dev_V/]" >"3+Mђ)r>(&JH5|finVo rԯ<~ zO)HF!Vk/ =!MoЫkj[o_y.|S|wEh=$,x} -_9fߺq#(׏]'Y 5zoصۥ{"qޑn5:AAA'_йbY̼6hy7_Hi>h+'.ȼsF_b·3s^e!l)vHjU#ߟ/OT#ʹdsҭU{{k窚{ ĶVRȁSIUo7p4A"]g Vbٷe׊e[7mY "EHaQ<~9 ƫ4!ZBq٦$Eb-fBAAĩP8 g `M!0)N+p4r޵R*W^p-|&Ώ*E+wx`1cW_]7bR#8oʥHÒ aI1x,Փc֤DJ>Yvm]S {4=4AfƝ_Eh؎Tz|_ Qأ|c9%%<内+~ok>kx70؄]ve4l"iΜ90ef%6eKb- 2lذ`Uww^_gO!~cppۇ澎޹v[.'5 kmfA]  8[zI'L܎t3[+8r!51v]~XFP[sϹ6S#ȲW>u[.g;qp%Zv}ع3vsusyTXLH~qyW_   N*fjr!gaYNCkVɊQzqdӻ6 _ w)jiLHqh9Ӄx6 z"ձPϽtE+P6dRR1?Ih\{,/"v]q5ֻdBP~I X^0X ;p ,_24#cer,)KV;ϒK_v PC׃5?oG*+eeEg+V9NKU=Yx>۔ 77x_3Pt% pfg} pMR g7;9a{>;{Dt|R43|)e@*+d$?=?]jy8ݱMe>X {ę>jA?0Rs`I/MuTydVuj$MfE+',LfVsªw6ڦr2˼qwm\A>%x}#ߩݛNF{'bHNwWa/SbKVߗ 7#! ڼП??wܾCVccV|SMkJÌFНxBdppм}!{2#% :$Lg46˫p`7uv׹Ah'˭a7zs]̔[e۞r!O=dy^Reri÷eqڈyy\+v{tz׿ƫ~|#mCڵ-sO欻C4lo]=ms͕Jimm?+/@**䞻vy.-zu/c^x> ]xL_e',o{.ٱuNo8KWIoW)Jp :Ψp>=I>rlWڄv]֬B*kfRē %zqL *tmi/7*qƱM y-_k_fyMr֫ΒkFטuO'SreeozIy%OaB}w!6뙗iӤƄގٲq ؓA H7 ?R`urСpI$|3z[ˬ2k^n-sѰJ{ {B]e;:ۯsjp t)4MAw k7%ݼ͟%Xb@ x!TEx cZN̽ܢ{]]u)ݹz~ۮ屧n}|(3,Kd!{gYv~S][,\PXB>sS媫 ok߸~ھ]NNm?Kw! I|/.qJq#=gJ0G$.e"cfpy5h `1yMWz24t>)k e䖛~m^3Ѯ,ߎR; a%??]|+XL8XzQ!MGV.^9;lG??|~z~']|Gk|߾)}CC-W]zGyόv3/~ _/tZfݻ ejuJ.[*{vX$;1WUW!_%K<eÀ Ĕ2CVcNa@6*P^|vbw]Y# %2s6a?)ny:я7=^#SB*~nT98Kdzfdtpyy䅋/%[njU˟t\JP}d2ol[߼`I֮tHwsW G$-2R^Kddh@FF2rp6i۷Cg4JtlT<.S<prva⌚{>Vv c1sΊ|]`?{]ݘ#&Tz؋CzşS*{{*kN{dy.RdEgR\=&tٽy^Mom_mk$馛ohPZ:r,rGGmL|1']FL6yϵ_~zYa4+zdȼޡ d%YQmA^7ЯʼnnH'D/^T=ݱKs7cOw/Z4kScmc{ϫx\dFo.MK伄UXvNNX _ˁcovpEh.j/79seہ=k֮w饗؆q'dWkK$GrX/=0A8wvKe:-\6rys \`ّl1;aU}5W cнbN 族K/a7/h =P^[Ll~hsm8wu=^ej~pxy+ʅsݗCBwFU%r)^) ~;zlӝhsgּhyu9y΃-2(X.x[)=7:o?/ $ļv40 ntt] ЛfLhX㾮=?ီ` t—L*|F qa0|qASh.XDo;'%T >^7L9Ή.+ԥd f]m 6Ȝys*Λ7 ɿwGLr|A;8:#V_|7}ﱠ[.%0dw/>yO$cNɖ -;2kNaHuąp>) : Fu}p4ސ#yN UKU'(.|,^Mܣ_?~c{6mS-&j+^q/LۑژnUv~Sʫ!~׿; pNy_R0^WzE'ɯDv֮dҟ=wx8kѽn^€.8ˬESI[:(C CCڋ_RozqRK U csw]^3|C򖷾U~KzGK_!]r 7H,--~Cne-~+_8?ohw^N{ڤnJL g%_ONWe5 t~<mWؽ=ccT5Wz~Xk"?^m{6=}ݲuF%6wo*9&//&~s1;!_[km9 ۷o3fu5_p2Iv\7ueӳ BfC=/V7cI*#UЌ_NX|XaU-& ^:Kw`Fڮx~l㷅>-Iˬ8]+zh skbs4Gc5~+x!}gׄnńnьv^i1}m涹x˻?Xyp5wjY|TT} ¸[ 緦6+`^mx'^gDYRVQ)gH' ĕS!i q9P+1=#^RQ&wv۞9f.k{T>qD?:) _cDjN(?7^ {KK'O57ˉ'. s}s9R(RW['?q)١x)\'fΒ~Yp}nMz);7  wG+ѿ;;Co%؜|r[;]+dx(6 :GO:UUMkd/ c YH@$! }yX/=&tkhj>['-6#lb/Z_mƣa;7:z9O'1LH6$t{q˪3;J79K7\ټyArɌdkO'ϗAocrk.O?]Guk9s_RVW%r<Яp@z"a\$p^y,Eݟj+^8? uw#m>p+yCYI'ϒQt +GZ1=Huqho>KIpG{?3Um4*c50RDv ⍓H+魫s)z~XdMqrjЪ~|A ]dh8#ך >w|7$̾Όu]2xkM7${姞&餷d^go K2K.[>ξo[[p6bN;DctgS1OWHf_j&``c7Kv;Xpu֎NZ2z<dB ziw?xd#rR~՗TTV;gR6*U|d΂pe/cszIqzñc:}?c Y+lfQ#٬l޳[&{koݷ>ophRg Pa&.MJMEsdRA8VK+ ׯg׭wϟ7G1yZΛUuʅNRf_s#0۵_.ۥ%KcC}lȄaԳ3Oo4aƄTB0tvV3cVN6oBMymЋټFzs:+PX3w_Mb`xL&`>eQ="NN9wԏL?4h^*E'׋7Da\,5@+u9s6O}B>֭[JkzQ*nK& 趂Fcri[=///Pt}H?lkbʒ_}6`}rފT{j 'WiN:/|0 ͫEs[eύcWJRӪ~~7Sf\n)-h/Euus熵dRgzA^?]N^vg׭ {__̙7_Mow=أ%ַMzzz_)5NdjFee,Zt K'$XnOxn-8v=毝m7׵ur>80(=}222"鲴TWWIYyya#9WF7SlJy A?6tU.݁Gr_/_ϻኯؐUY-2ճt.hiz|##%^fq^gw3DyWo N^TN^̄_ˎeEW*9{mwuɷoI}}}˿<ЯeO_wҲerlH%y 1{; .J90w!#Ys:zL4kݫp8Fjj^f͐YgʤIuR^QnPll}A?\y|熇ܥ\5 ^Lx#?yG{+"'׀)OV °nCyLb~RiD3/lw.6yOo#mʚ?>)_פq4ѿ}}g[>%wq pa:y.`+Ӯxs^-gqrIw!_V!-|ydJr^\/`zIHfD{dhpPq1\*t' qbZv;_y;厇,-;Mحcafud3aou{VG5syn؄yy՟|я^{l"koi~o3f4oؾMxRQQ!/#%HeEԙp"--x.^:қ 0Gyp\<e,]&3rG**e zDp9īpO~@O[)Ϋ~•dύveS6[cIf=q%8LIl) wG~=5z,]W/6dA ~ѢEaʌHˁ3V\>H b9i2y~-g赯ڷW>ɿYMM/~Ѿ`~nR,_zlyzTWW˾;}}dS{~;.p&#$iV*TViV.Ǩ :`o?pFqcOJ۰Z4Jt>"hiR?e]sNJyyav Ņv?'k F/;m|lc#Y+ʼn'%*/hXuN'/I_wTNa1o ?̽ͩSdxhXMhsmP*|,ꂔyM}')^|ώdh?gE^+icY ٌHGa׺r9.;=ig3 ?)u%Wr\ve/_46ΐo1|~t|{ߓ3_(gٙv掎A{hP{'J6G# ÕW_t9@;~Z8aϻϒeﶍm TmW.ɂ׉חWMkd ?Gù2/WK ɐ E<|HP/Owlq/F^}1 &}ۺyDic+7N?{}Ąni1u'%RI4Rbw9fc'hnbɿm.7`nL\R~^/Seg|H,֨Le%n7i.e ع偸LIoIܵk'4̜#MԳ^#vl͏&CK2so1wx7$_]6RV]^Н7 0Sҧ{/Ob|&>ڬ p~9iv[52t[8 ִB2kf9=8R 2y޵^gB{JuC=~{POϨp^κlM2I,mw[ClI ?H% O&2?=YVe`mM; ii)K1 &hk]~y >uGaR=vAXOk.{+܆Is gzQǡ{咫_oҼVk7F=OF >Æs9F\)s? 0{~\ˎk@&|R [*hH{pW>H"s#Gϑg׮ϛ3o]|dH{ f̽eTּN0fTYRZ_&kUj%.y_<*mKh87( mՓ»^;{{yv|?we_I@ Wy650z}RV=};0gL8nd\9{p#C2yҔAwu sɝHmmnk>Aپ}_׾m^) RUSUZ_.[[[Wg7<+#f[WUUo}=AMsn4CNOxg>K/ejjjds$nB^Cw/Q@w5r咈%diam Ψ>m)Wm}o|3yO欴]5\Vdg7E2^Qe6` k ;ٛw>b{jS/={=X))YE׻zz{mFz錖:W9 ǯ{ٍ̱zJdyW@_z2ud7{l!Cla5=̶5[K7lD~F۶m76|sgnw,&AT0 : `Ŋrc_Юz׸T4\(=lފxn-8Fod![ԑӿS^uJse Z`E6v.T"i-nAU\[WnLk!)/r>$f:7G{BzOO:tkۆqAXRq{{{m׮]g?2eTii9 y%_ׯo|ꓟ;Ww)坲u{o klHinŋK1*7۳Ƅx ܮx҄ݦzu͎ȵ]+~WEJtX{, y<Ӓe |_KcbZ>aKkplV㱰Dcsg=n;,HYđw˙/g*8'eL>xyG- {L6ܰk%dBuE,{/s\q{dᜥ200`ù; Z9_߲bH6dNx` $DopM@{llۺ&LO*_dͺuI:Ydp3_yUxx z'xL;k8~bIPS]}D+vǙ>ܗ|`^9{4l}ϘpuV?]fj#yVkϐTk'=̿4Q@=hH&$NK2*x}2^n"m:.i>,?koGXH02U+OYi+SHSlᆬ̘>7W^azBB ¹q_il-2tjJZǂ~}ffjaHͨ=QYϵ;K/a_WH:id/-zoBy\,^߮^{yf6A|(_2Ms[NctAmuUdúns:N0;464WanT*~?mrEWʃndjN#srº^nç U`s' *AWp_PaO`6(J6[6=^uYΫeø /d)')˖-"mRkI$^Y!g٫BvoQ2;J9V+:]{%~zćnma3QkEs#$@"Gٯ~z˭h߯T|p IKl݊Uiٷs+t/ta0JcO_ ـǞz楦&yի_eoPu>c+ c9#M37h\?xѡ!\/ZK %·;r9\>лù^!+9[oտXRe&oByVtkjLЬSڠ8hv,¹Y'𙒮!dv8w]LcN"Bm# .4B~Y&ԮZ[y˲Ӽ})7t'~{:};L10sjla{u 'tRmg~GM ό Jee=ϥCk;  ۓFÃr=ړK,[L؟tyJuR[W'Ywe` Jc} ItK}^y9, c5QV· 9omXZ%~}yn޿τaٻo [ U5%Mss/2ck혞L4˨ k05o:|d$g3gΖ}{z0`:nݦyP10g8fkCDZo(;Ļ?VSUnE;( zߦו'=k0A?<"7ne˖mVme=嗀j̒.b5_jg_GЃ{eOrkQ|I^&SQY.M3vR]ZR7yB}vʪʂ!Zԉlңpt-h Q¹k'm6[w`%мٞHUHOO47H &O2݆3<[**!I$KK:]͙3džDKEy컔'{n'W? j)3%`t91>hN{~a F9?'b IOhs>)3gͲUJ/%L+ĄD>fs٬|C9VV*x4,s}\CQP*Axߺc}Lë&2io?$u2~)JMY,ZLRTWK Z弢e5KK}X^'E=s,]XY{qB9aut;#wcRЫ-m݇n؎zƿ޲e}ζ;m\y\q咊D:]  4 ]s>=t{ c۝}M4s̝?#޽{d Niec9􄎞Cm9mRo>#+_1|Źus&5;pUooMm0i9v~zP7k {w@!I\N!=_%*;߿_ln2j~Ԛ+d3qwuU=PSU]%q=ґ'bԼh2엉~={l@PtRw>pMvyzx<{:Ä9vd b1(KYvu^s=`cIf{IC,{C,Iw s,YP=\Y`[<|}YYhQdDƄz{2`>s|ܹNHC㵹]G!yHӬ cnτ|NøCCD@.?61=&T.{RʟJTM5/bstk BT[{=(-me~ٴY7ʴ)v̙3ezyغ} 4 <.X/lv[TLL2A.5e4;|a :D[를V½^UOG-6>V/ݰsDw}͚5v{566ڵiVVuy;nN睲\ꦘP暀>`{صm{Ѽϻ^ns^z̛7W:c,?K*Xbt:@@?k.R4kRiphhX: MM޵{l޼IܹseѼRYYa궴HgW6U6DO<3u. A7k ?keTzh烗 {a7ԏ0O(ڹ]iiԙsMi){$nrv$#CC248hA;AE}Sz{Àúw]zf&^oKȆȸ g&A{2rٜ9wﮕɫ\nZ;?]ԥIOhc9[հUEMCmrHzzeOn;lusaU~mꥡ*>k/OpKcM4GEu\ Gԏ`hBsNXOVyF{/̰]FrpYVMdqLW|)''R|!totp HXQglwmSX?XV, ~sPZ <vNM(=')y~￱䱠2,S@y#ysdF92mdt"k.^;ނph B>Ɔ2\j58KXE?/opx|~^tAeXV}~PmΥg+fkYGRf^dLfT AGZuݶL{ Aр~,=]M6?4Κ5˄)%TK- 5@C1R>m.NS t*=rlA̝xz]xd#-.ua8kѹУ{KqH(]>M4 GE^Ux}\Cyv>xByRn9pyNێxi"t.ͦ풶]lCʹ{16 y@`V*EVUfU 0~쑄~9tn[^^k8MF+k8`{qċ^bR= ~;%CEyay4$߿sɋ.|O>fpz@Y҃W_L)׹/t‘?Gz8؍΃PÊ-$M4oѓ(u{YJ%BᜀzunߧaK@kï#K>n |/8TpҋqG'B9 Xo ^:X~̏6/ ~$ב>X4y{!S 9u, S}9G äa:l`m:`/A@/Vc Ώu#&Y׽xyB9z vBn?" + propertyTags[i].getElementsByTagName('pageTitle')[0].firstChild.nodeValue + linkEnd; $('#ul001').append(full_li_element); $('#ul001 .defaultLink').css('display','none'); } } if(propertyTags[i].getElementsByTagName('pageType')[0].firstChild.nodeValue == 'Article'){ articleCount++; for (var j=0; j< propertyTags[i].getElementsByTagName('pageWords').length; j++){ full_li_element = linkStart + propertyTags[i].getElementsByTagName('pageUrl')[j].firstChild.nodeValue; full_li_element =full_li_element + "'>" + propertyTags[i].getElementsByTagName('pageTitle')[0].firstChild.nodeValue + linkEnd ; $('#ul002').append(full_li_element); $('#ul002 .defaultLink').css('display','none'); } } if(propertyTags[i].getElementsByTagName('pageType')[0].firstChild.nodeValue == 'Example'){ exampleCount++; for (var j=0; j< propertyTags[i].getElementsByTagName('pageWords').length; j++){ full_li_element = linkStart + propertyTags[i].getElementsByTagName('pageUrl')[j].firstChild.nodeValue; full_li_element =full_li_element + "'>" + propertyTags[i].getElementsByTagName('pageTitle')[0].firstChild.nodeValue + linkEnd ; $('#ul003').append(full_li_element); $('#ul003 .defaultLink').css('display','none'); } } if(i==propertyTags.length){$('#pageType').removeClass('loading');} } if(lookupCount > 0){$('#ul001 .menuAlert').remove();$('#ul001').prepend('
  • Found ' + lookupCount + ' hits
  • ');$('#ul001 li').css('display','block');$('.sidebar .search form input').removeClass('loading');} if(articleCount > 0){$('#ul002 .menuAlert').remove();$('#ul002').prepend('
  • Found ' + articleCount + ' hits
  • ');$('#ul002 li').css('display','block');} if(exampleCount > 0){$('#ul003 .menuAlert').remove();$('#ul003').prepend('
  • Found ' + articleCount + ' hits
  • ');$('#ul003 li').css('display','block');} if(lookupCount == 0){$('#ul001 .menuAlert').remove();$('#ul001').prepend('
  • Found no result
  • ');$('#ul001 li').css('display','block');$('.sidebar .search form input').removeClass('loading');} if(articleCount == 0){$('#ul002 .menuAlert').remove();$('#ul002').prepend('
  • Found no result
  • ');$('#ul002 li').css('display','block');} if(exampleCount == 0){$('#ul003 .menuAlert').remove();$('#ul003').prepend('
  • Found no result
  • ');$('#ul003 li').css('display','block');} // reset count variables; lookupCount=0; articleCount = 0; exampleCount = 0; } //build regular expression object to find empty string or any number of blank var blankRE=/^\s*$/; function CheckEmptyAndLoadList() { var pageUrl = window.location.href; var pageVal = $('title').html(); $('#feedUrl').remove(); $('#pageVal').remove(); $('.menuAlert').remove(); $('#feedform').append(''); $('#feedform').append(''); $('.liveResult').remove(); $('.defaultLink').css('display','block'); var value = document.getElementById('pageType').value; if((blankRE.test(value)) || (value.length < 3)) { //empty inputbox // load default li elements into the ul if empty // loadAllList(); // replaced $('.defaultLink').css('display','block'); // $('.liveResult').css('display','none'); }else{ $('.defaultLink').css('display','none'); } } /* $(window).resize(function(){ if($(window).width()<400) $('body').addClass('offline'); else $('body').removeClass('offline'); }); */ // Loads on doc ready $(document).ready(function () { //alert(pageUrl); //$('#pageUrl').attr('foo',pageUrl); var pageTitle = $('title').html(); var currentString = $('#pageType').val() ; if(currentString.length < 1){ $('.defaultLink').css('display','block'); CheckEmptyAndLoadList(); } $('#pageType').keyup(function () { var searchString = $('#pageType').val() ; if ((searchString == null) || (searchString.length < 3)) { $('#pageType').removeClass('loading'); $('.liveResult').remove(); $('.searching').remove(); CheckEmptyAndLoadList(); $('.report').remove(); // debug$('.content').prepend('
  • too short or blank
  • '); // debug return; } if (this.timer) clearTimeout(this.timer); this.timer = setTimeout(function () { $('#pageType').addClass('loading'); $('.searching').remove(); $('.list ul').prepend(''); $.ajax({ contentType: "application/x-www-form-urlencoded", url: 'http://' + location.host + '/nokiasearch/GetDataServlet', data: 'searchString='+searchString, dataType:'xml', type: 'post', success: function (response, textStatus) { $('.liveResult').remove(); $('.searching').remove(); $('#pageType').removeClass('loading'); $('.list ul').prepend(''); processDigiaData(response); } }); }, 500); }); }); qbs-src-1.4.5/doc/templates/scripts/narrow.js000066400000000000000000000045301266132464200212030ustar00rootroot00000000000000var narrowInit = function() { /* TODO: Could probably be more efficient, not hardcoding each element to be created */ // 1: Create search form var narrowSearch = $('
    '); var searchform = $("#qtdocsearch"); narrowSearch.append(searchform); $("#qtdocheader .content .qtref").after(narrowSearch); // 2: Create dropdowns var narrowmenu = $('
      '); // Lookup var lookuptext = $("#lookup h2").attr("title"); $("#lookup ul").removeAttr("id"); $("#lookup ul li").removeAttr("class"); $("#lookup ul li").removeAttr("style"); var lookupul = $("#lookup ul"); var lookuplist = $('
    • '); var lookuplink = $('
      '); lookuplink.append(lookuptext); lookuplist.append(lookuplink); lookuplist.append(lookupul); narrowmenu.append(lookuplist); // Topics var topicstext = $("#topics h2").attr("title"); $("#topics ul").removeAttr("id"); $("#topics ul li").removeAttr("class"); $("#topics ul li").removeAttr("style"); var topicsul = $("#topics ul"); var topicslist = $('
    • '); var topicslink = $(''); topicslink.append(topicstext); topicslist.append(topicslink); topicslist.append(topicsul); narrowmenu.append(topicslist); // Examples var examplestext = $("#examples h2").attr("title"); $("#examples ul").removeAttr("id"); $("#examples ul li").removeAttr("class"); $("#examples ul li").removeAttr("style"); var examplesul = $("#examples ul"); var exampleslist = $('
    • '); var exampleslink = $(''); exampleslink.append(examplestext); exampleslist.append(exampleslink); exampleslist.append(examplesul); narrowmenu.append(exampleslist); $("#shortCut").after(narrowmenu); $('ul#narrowmenu').superfish({ delay: 100, autoArrows: false, disableHI: true }); } $(document).ready(function(){ /* if ($('body').hasClass('narrow')) { narrowInit(); } */ if($(window).width()<600) { $('body').addClass('narrow'); if ($("#narrowsearch").length == 0) { narrowInit(); } } else { $('body').removeClass('narrow'); } }); $(window).bind('resize', function () { if($(window).width()<600) { $('body').addClass('narrow'); if ($("#narrowsearch").length == 0) { narrowInit(); } } else { $('body').removeClass('narrow'); } });qbs-src-1.4.5/doc/templates/scripts/superfish.js000066400000000000000000000072021266132464200217020ustar00rootroot00000000000000 /* * Superfish v1.4.8 - jQuery menu widget * Copyright (c) 2008 Joel Birch * * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html * * CHANGELOG: http://users.tpg.com.au/j_birch/plugins/superfish/changelog.txt */ ;(function($){ $.fn.superfish = function(op){ var sf = $.fn.superfish, c = sf.c, $arrow = $([' »'].join('')), over = function(){ var $$ = $(this), menu = getMenu($$); clearTimeout(menu.sfTimer); $$.showSuperfishUl().siblings().hideSuperfishUl(); }, out = function(){ var $$ = $(this), menu = getMenu($$), o = sf.op; clearTimeout(menu.sfTimer); menu.sfTimer=setTimeout(function(){ o.retainPath=($.inArray($$[0],o.$path)>-1); $$.hideSuperfishUl(); if (o.$path.length && $$.parents(['li.',o.hoverClass].join('')).length<1){over.call(o.$path);} },o.delay); }, getMenu = function($menu){ var menu = $menu.parents(['ul.',c.menuClass,':first'].join(''))[0]; sf.op = sf.o[menu.serial]; return menu; }, addArrow = function($a){ $a.addClass(c.anchorClass).append($arrow.clone()); }; return this.each(function() { var s = this.serial = sf.o.length; var o = $.extend({},sf.defaults,op); o.$path = $('li.'+o.pathClass,this).slice(0,o.pathLevels).each(function(){ $(this).addClass([o.hoverClass,c.bcClass].join(' ')) .filter('li:has(ul)').removeClass(o.pathClass); }); sf.o[s] = sf.op = o; $('li:has(ul)',this)[($.fn.hoverIntent && !o.disableHI) ? 'hoverIntent' : 'hover'](over,out).each(function() { if (o.autoArrows) addArrow( $('>a:first-child',this) ); }) .not('.'+c.bcClass) .hideSuperfishUl(); var $a = $('a',this); $a.each(function(i){ var $li = $a.eq(i).parents('li'); $a.eq(i).focus(function(){over.call($li);}).blur(function(){out.call($li);}); }); o.onInit.call(this); }).each(function() { var menuClasses = [c.menuClass]; if (sf.op.dropShadows && !($.browser.msie && $.browser.version < 7)) menuClasses.push(c.shadowClass); $(this).addClass(menuClasses.join(' ')); }); }; var sf = $.fn.superfish; sf.o = []; sf.op = {}; sf.IE7fix = function(){ var o = sf.op; if ($.browser.msie && $.browser.version > 6 && o.dropShadows && o.animation.opacity!=undefined) this.toggleClass(sf.c.shadowClass+'-off'); }; sf.c = { bcClass : 'sf-breadcrumb', menuClass : 'sf-js-enabled', anchorClass : 'sf-with-ul', arrowClass : 'sf-sub-indicator', shadowClass : 'sf-shadow' }; sf.defaults = { hoverClass : 'sfHover', pathClass : 'overideThisToUse', pathLevels : 1, delay : 800, animation : {opacity:'show'}, speed : 'normal', autoArrows : true, dropShadows : true, disableHI : false, // true disables hoverIntent detection onInit : function(){}, // callback functions onBeforeShow: function(){}, onShow : function(){}, onHide : function(){} }; $.fn.extend({ hideSuperfishUl : function(){ var o = sf.op, not = (o.retainPath===true) ? o.$path : ''; o.retainPath = false; var $ul = $(['li.',o.hoverClass].join(''),this).add(this).not(not).removeClass(o.hoverClass) .find('>ul').hide().css('visibility','hidden'); o.onHide.call($ul); return this; }, showSuperfishUl : function(){ var o = sf.op, sh = sf.c.shadowClass+'-off', $ul = this.addClass(o.hoverClass) .find('>ul:hidden').css('visibility','visible'); sf.IE7fix.call($ul); o.onBeforeShow.call($ul); $ul.animate(o.animation,o.speed,function(){ sf.IE7fix.call($ul); o.onShow.call($ul); }); return this; } }); })(jQuery); qbs-src-1.4.5/doc/templates/style/000077500000000000000000000000001266132464200170045ustar00rootroot00000000000000qbs-src-1.4.5/doc/templates/style/narrow.css000066400000000000000000000113231266132464200210260ustar00rootroot00000000000000 /* start narrow mode */ body.narrow { background-image: none; } .narrow a { color: #44a51c; } .narrow .header, .narrow .header .content, .narrow .footer, .narrow .wrapper { margin: 0 7px; min-width: 300px; } .narrow .footer { margin: 0px; } .creator .header, .creator .header .content, .creator .footer, .creator .wrapper { margin: 0px; min-width: 300px; } .narrow .header { width: 100%; margin: 0; height: auto; background: #fff url(../images/header_bg.png) repeat-x 0 100%; padding: 10px 0 5px 0; overflow: visible; } .narrow .header .content { } .narrow .header #nav-logo { display: none; } .narrow .header .qtref { width: auto; height: auto; color: #363534; position: static; float: left; margin-left: 25px; font: bold 18px/1 Arial; } .narrow .header .qtref a { color: #00732F; } .narrow .header .qtref span { background-image: none; text-indent: 0; } .narrow .header #nav-topright { display: none; } .narrow .header #shortCut { clear: both; font-weight: normal; position: static; float: left; margin: 15px 0 0 25px; overflow: hidden; padding: 0; height: auto; } .narrow .header #shortCut ul { float: none; margin: 0; width: auto; font-size: 11px; } .narrow .header #shortCut ul li { background-image: none; } .narrow .header #shortCut ul .shortCut-topleft-active, .narrow .header #shortCut ul .shortCut-topleft-inactive { background-image: none; height: auto; padding: 0; width: auto; } .narrow .header #shortCut ul li a { color: #00732F; } .narrow .wrapper .hd { background: url(../images/bg_ul_blank.png) no-repeat 0 0; } .narrow .wrapper .bd { background: url(../images/bg_l_blank.png) repeat-y 0 0; } .narrow .wrapper .ft { background: url(../images/bg_ll_blank.png) no-repeat 0 0; } .narrow .sidebar { display: none; } .narrow .wrap { margin: 0 5px 0 5px; } .creator .wrap { margin: 0px; background:#FFFFFF; } .narrow .wrap .toolbar { border-bottom: none; } .narrow .wrap .content { padding-top: 15px; } .creator .wrap .content { padding-top: 10px; } .creator .wrap .content .guide { padding-top: 15px; } .narrow .wrap .feedback { display: none; } .narrow .wrap .breadcrumb ul li { font-weight: normal; } .narrow .wrap .breadcrumb ul li a { color: #44a51c; } .narrow .wrap .breadcrumb ul li.last a { color: #363534; } #narrowsearch { display: none; } .narrow #narrowsearch { display: block; float: right; margin-right: 25px; _position: relative; } .narrow #narrowsearch fieldset { _position: absolute; _margin-top: -1px; } .narrow #narrowsearch { background: url("http://doc.qt.nokia.com/prototype/html/images/sprites-combined.png") no-repeat scroll -6px -348px transparent; height: 21px; padding: 2px 0 0 5px; width: 167px; } .narrow #narrowsearch input { border: none; font: 13px/1.2 Verdana; height: 19px; outline: none; padding: 0; width: 158px; *border: 1px solid #fff; *height: 17px; _height: 18px; /* to be fixed */ display: none; /* to be fixed */ } .narrow .indexbox .indexIcon { display: none; } .narrow .indexboxcont .section { width: 64%; padding-left: 0; } .narrow .indexboxcont .sectionlist { width: 32.5%; } #narrowmenu { display: none; float: right; margin: 15px 40px 0 0; font-size: 11px; } .narrow #narrowmenu { display: block; } #narrowmenu a { line-height: 1.1; background: url(../images/arrow_down.png) no-repeat 100% 50%; white-space: nowrap; padding: 0 16px 0 5px; } #narrowmenu li { margin-left: 20px; } #narrowmenu li li { margin: 0 0 5px 0; } #narrowmenu li li a { padding: 0; background-image: none; } #narrowmenu li, #narrowmenu li ul { background-color: #fff; margin-top:-1px; } #narrowmenu li ul { width: auto; padding: 5px; } .sf-menu li:hover ul, .sf-menu li.sfHover ul { top: 1.2em; } /* end narrow mode */ qbs-src-1.4.5/doc/templates/style/offline.css000066400000000000000000000214011266132464200211360ustar00rootroot00000000000000body{ font: normal 400 14px/1.2 Arial; margin-top:85px; font-family: Arial, Helvetica; color:#313131; text-align:justify; margin-left:5px; margin-right:5px; } img{ -moz-box-shadow: 3px 3px 3px #ccc; -webkit-box-shadow: 3px 3px 3px #ccc; box-shadow: 3px 3px 3px #ccc; border:#8E8D8D 2px solid; margin-left:0px; max-width: 800px; height: auto } b{ font-weight:600; } .content{} .descr{ margin-top:35px; /*max-width: 75%;*/ margin-left:5px; text-align:justify; min-height:700px; vertical-align:top; } .name{ max-width: 75%; font-weight:100; } tt{ text-align:left;} /* ----------- links ----------- */ a:link{ color: #2C418D; text-decoration: none; text-align:left; } a:hover{ color: #869CD1; text-decoration:underline; text-align:left; } a:visited{ color: #869CD1; text-decoration: none; text-align:left; } a:visited:hover{ text-decoration:underline; text-align:left; } a[href*="http://"], a[href*="ftp://"],a[href*="https://"] { text-decoration: none; background-image:url(../images/ico_out.png); background-repeat:no-repeat; background-position:left; padding-left:20px; text-align:left; } /*a[href*="http://qt.nokia.com/doc/"], a[href*="http://doc.qt.nokia.com/"] { background: none; padding-left: 0px; text-align:left; }*/ .flags{ text-decoration:none; text-height:24px; } /* ------------------------------- NOTE styles ------------------------------- */ .notetitle, .tiptitle, .fastpathtitle{ font-weight:bold; } .attentiontitle,.cautiontitle,.dangertitle,.importanttitle,.remembertitle,.restrictiontitle{ font-weight:bold; } .note,.tip,.fastpath{ background: #F2F2F2 url(../images/ico_note.png); background-repeat: no-repeat; background-position: top left; padding:5px; padding-left:40px; padding-bottom:10px; border:#999 1px dotted; color:#666666; margin:5px; } .attention,.caution,.danger,.important,.remember,.restriction{ background: #F2F2F2 url(../images/ico_note_attention.png); background-repeat:no-repeat; background-position:top left; padding:5px; padding-left:40px; padding-bottom:10px; border:#999 1px dotted; color:#666666; margin:5px; } /* ------------------------------- Top navigation ------------------------------- */ .header{ height:1px; padding:0px; margin:0px; } .qtref{ display: block; position: relative; top: -76px; height:15px; z-index: 1; font-size:11px; padding-right:10px; float:right; } .naviNextPrevious{ display: block; position: relative; text-align: right; top: -53px; float:right; height:20px; z-index:1; padding-right:10px; padding-top:2px; vertical-align:top; margin:0px; } .naviNextPrevious > a:first-child{ background-image:url(../images/btn_prev.png); background-repeat:no-repeat; background-position:left; padding-left:20px; height:20px; padding-left:20px; } .naviNextPrevious > a:last-child{ background-image:url(../images/btn_next.png); background-repeat:no-repeat; background-position:right; padding-right:20px; height:20px; margin-left:30px; } .breadcrumb{ display: block; position: relative; top:-20px; /*border-top:2px solid #ffffff;*/ border-bottom: 1px solid #cecece; background-color:#F2F2F2; z-index:1; height:20px; padding:0px; margin:0px; padding-left:10px; padding-top:2px; margin-left:-5px; margin-right:-5px; } .breadcrumb ul{ margin:0px; padding:0px; } .breadcrumb ul li{ background-color:#F2F2F2; list-style-type:none; padding:0; margin:0; height:20px; } .breadcrumb li{ float:left; } .breadcrumb .first { background:url(../images/home.png); background-position:left; background-repeat:no-repeat; padding-left:20px; } .breadcrumb li a{ color:#2C418D; display:block; text-decoration:none; background:url(../images/arrow.png); background-repeat:no-repeat; background-position:right; padding-right:25px; padding-left:10px; } .breadcrumb li a:hover{ color:#909090; display:block; text-decoration:none; background:url(../images/arrow.png); background-repeat:no-repeat; background-position:right; padding-right:20px; padding-left:10px; } /* table of content no display */ /* ----------- headers ----------- */ @media screen{ .title{ color:#313131; font-size: 18px; font-weight: normal; left: 0; padding-bottom: 20px; padding-left: 10px; padding-top: 20px; position: absolute; right: 0; top: 0; background-color:#E6E6E6; border-bottom: 1px #CCC solid; border-top: 2px #CCC solid; font-weight:bold; margin-left:0px; margin-right:0px; } } h1 { margin: 0; } h2, p.h2 { font: 500 16px/1.2 Arial; font-weight:100; background-color:#F2F3F4; padding:4px; margin-bottom:30px; margin-top:30px; border-top:#E0E0DE 1px solid; border-bottom: #E0E0DE 1px solid; max-width: 99%; } h3{ font: 500 14px/1.2 Arial; font-weight:100; text-decoration:underline; margin-bottom:30px; margin-top:30px; } h3.fn,span.fn{ border-width: 1px; border-style: solid; border-color: #E6E6E6; -moz-border-radius: 7px 7px 7px 7px; -webkit-border-radius: 7px 7px 7px 7px; border-radius: 7px 7px 7px 7px; background-color: #F6F6F6; word-spacing: 3px; padding: 5px 5px; text-decoration:none; font-weight:bold; max-width:75%; font-size:14px; margin:0px; margin-top:30px; } .name{ color:#1A1A1A; } .type{ color:#808080; } @media print { .title { color:#0066CB; font-family:Arial, Helvetica; font-size: 32px; font-weight: normal; left: 0; position: absolute; right: 0; top: 0; } } /* ----------------- table styles ----------------- */ .table img { border:none; margin-left:0px; -moz-box-shadow:0px 0px 0px #fff; -webkit-box-shadow: 0px 0px 0px #fff; box-shadow: 0px 0px 0px #fff; } /* table with border alternative colours*/ table,pre{ -moz-border-radius: 7px 7px 7px 7px; -webkit-border-radius: 7px 7px 7px 7px; border-radius: 7px 7px 7px 7px; background-color: #F6F6F6; border: 1px solid #E6E6E6; border-collapse: separate; font-size: 12px; line-height: 1.2; margin-bottom: 25px; margin-left: 15px; font-size: 12px; line-height: 1.2; margin-bottom: 25px; margin-left: 15px; } table th{ text-align:left; padding-left:20px; } table td { padding: 3px 15px 3px 20px; border-bottom:#CCC dotted 1px; } table p { margin:0px;} table tr.even { background-color: white; color: #66666E; } table tr.odd { background-color: #F6F6F6; color: #66666E; } table thead { text-align:left; padding-left:20px; background-color:#e1e0e0; border-left:none; border-right:none; } table thead th { padding-top:5px; padding-left:10px; padding-bottom:5px; border-bottom: 2px solid #D1D1D1; padding-right:10px; } /* table bodless & white*/ .borderless { border-radius: 0px 0px 0px 0px; background-color: #fff; border: 1px solid #fff; } .borderless tr { background-color: #FFF; color: #66666E; } .borderless td { border:none; border-bottom:#fff dotted 1px; } /* ----------- List ----------- */ ul{ padding-bottom:2px; } li ul { padding-top: 10px; } li { margin-bottom: 10px; padding-left: 8px; list-style:outside; list-style-type:square; text-align:left; } ol{ margin:10px; padding:0; } ol > li{ margin-left: 30px; padding-left:8px; list-style:decimal; } .centerAlign{ text-align: left; } .cpp{ display: block; margin: 10; overflow: hidden; overflow-x: hidden; overflow-y: hidden; padding: 20px 0 20px 0; } .footer{ margin-top: 50px; padding-left:5px; margin-bottom: 10px; font-size:10px; border-top: 1px solid #999; padding-top:11px; } .footerNavi{ width:auto; text-align:right; margin-top:50px; z-index:1; } .memItemLeft{ padding-right: 3px; } .memItemRight{ padding: 3px 15px 3px 0; } .qml{ display: block; margin: 10; overflow: hidden; overflow-x: hidden; overflow-y: hidden; padding: 20px 0 20px 0; } .qmldefault{ padding-left: 5px; float: right; color: red; } .qmlreadonly{ padding-left: 5px; float: right; color: #254117; } .rightAlign{ padding: 3px 5px 3px 10px; text-align: right; } /* ----------- Content table ----------- */ @media print{ .toc { float: right; padding-bottom: 10px; padding-top: 50px; width: 100%; background-image:url(../images/bgrContent.png); background-position:top; background-repeat:no-repeat; } } @media screen{ .toc{ clear:both; float:right; vertical-align:top; -moz-border-radius: 7px 7px 7px 7px; -webkit-border-radius: 7px 7px 7px 7px; border-radius: 7px 7px 7px 7px; background:#FFF url(../images/bgrContent.png); background-position:top; background-repeat:repeat-x; border: 1px solid #E6E6E6; padding-left:5px; padding-bottom:10px; height: auto; width: 200px; text-align:left; z-index:2; margin-left:20px; margin-right:20px; margin-top:0px; padding-top:0px; } } .toc h3{ text-decoration:none; } .toc h3{font: 500 14px/1.2 Arial; font-weight:100; padding:0px; margin:0px; padding-top:5px; padding-left:5px; } .toc ul{ width:160px; padding-left:10px; padding-right:5px; padding-bottom:10px; padding-top:10px; } .toc ul li{ margin-left:20px; list-style-image:url(../images/blu_dot.png); list-style:outside; } .toc ul li a:link{ color: #2C418D; text-decoration: none; } .toc ul li a:hover{ color: #869CD1; text-decoration:underline; } .toc ul li a:visited{ color: #869CD1; font-weight: bold; } .level1{ border:none;} .clearfix{ clear:both;} qbs-src-1.4.5/doc/templates/style/style.css000066400000000000000000000710231266132464200206610ustar00rootroot00000000000000@media screen { /* basic elements */ html { color: #000000; background: #FFFFFF; } body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, button, textarea, p, blockquote, th, td { margin: 0; padding: 0; } table { border-collapse: collapse; border-spacing: 0; } fieldset, img { border: 0; max-width:100%; } address, caption, cite, code, dfn, em, strong, th, var, optgroup { font-style: inherit; font-weight: inherit; } del, ins { text-decoration: none; } li { list-style: none; } ol li { list-style: decimal; } caption, th { text-align: left; } h1, h2, h3, h4, h5, h6 { font-size: 100%; } q:before, q:after { content: ''; } abbr, acronym { border: 0; font-variant: normal; } sup, sub { vertical-align: baseline; } tt, .qmlreadonly span, .qmldefault span { word-spacing:5px; } legend { color: #000000; } input, button, textarea, select, optgroup, option { font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; } input, button, textarea, select { font-size: 100%; } strong { font-weight: bold; } em { font-style: italic; } /* adding Qt theme */ html { /* background-color: #e5e5e5;*/ } body { background: #e6e7e8 url(../images/page_bg.png) repeat-x 0 0; font: normal 13px/1.2 Verdana; color: #363534; } a { color: #00732f; text-decoration: none; } hr { background-color: #E6E6E6; border: 1px solid #E6E6E6; height: 1px; width: 100%; text-align: left; margin: 15px 0px 15px 0px; } pre { border: 1px solid #DDDDDD; -moz-border-radius: 7px 7px 7px 7px; -webkit-border-radius: 7px 7px 7px 7px; border-radius: 7px 7px 7px 7px; margin: 0 20px 10px 10px; padding: 20px 15px 20px 20px; overflow-x: auto; } table, pre { -moz-border-radius: 7px 7px 7px 7px; -webkit-border-radius: 7px 7px 7px 7px; border-radius: 7px 7px 7px 7px; background-color: #F6F6F6; border: 1px solid #E6E6E6; border-collapse: separate; font-size: 11px; margin-bottom: 25px; } pre.highlightedCode { display: block; overflow:hidden; } thead { margin-top: 5px; font:600 12px/1.2 Arial; } th { padding: 5px 15px 5px 15px; background-color: #E1E1E1; border-left: 1px solid #E6E6E6; } td { padding: 3px 15px 3px 15px; } tr.odd td:hover, tr.even td:hover {} td.rightAlign { padding: 3px 5px 3px 10px; } table tr.odd { border-left: 1px solid #E6E6E6; background-color: #F6F6F6; color: #66666E; } table tr.even { border-left: 1px solid #E6E6E6; background-color: #ffffff; color: #66666E; } table tr.odd td:hover, table tr.even td:hover { /* background-color: #E6E6E6;*/ /* disabled until further notice */ } span.comment { color: #8B0000; font-style: italic; } span.string, span.char { color: #254117; } /* end basic elements */ /* font style elements */ .heading { font: normal bold 16px/1.2 Arial; padding-bottom: 15px; } .subtitle { font-size: 13px; } .small-subtitle { font-size: 13px; } /* end font style elements */ /* global settings*/ .header, .footer, .wrapper { min-width: 600px; max-width: 1500px; margin: 0 30px; } .header, .footer { display: block; clear: both; overflow: hidden; } .header:after, .footer:after, .breadcrumb:after, .wrap .content:after, .group:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } /* end global settings*/ /* header elements */ .header { height: 115px; position: relative; } .header .icon { position: absolute; top: 13px; left: 0; } .header .qtref { position: absolute; top: 28px; left: 88px; width: 302px; height: 22px; } .header .qtref span { display: block; width: 302px; height: 22px; text-indent: -999em; background: url(../images/sprites-combined.png) no-repeat -78px -235px; } .content a:visited { color: #4c0033; text-decoration: none; } .content a:visited:hover { color: #4c0033; text-decoration: underline; } #nav-topright { height: 70px; } #nav-topright ul { list-style-type: none; float: right; width: 370px; margin-top: 11px; } #nav-topright li { display: inline-block; margin-right: 20px; float: left; } #nav-topright li.nav-topright-last { margin-right: 0; } #nav-topright li a { background: transparent url(../images/sprites-combined.png) no-repeat; height: 18px; display: block; overflow: hidden; text-indent: -9999px; } #nav-topright li.nav-topright-home a { width: 65px; background-position: -2px -91px; } #nav-topright li.nav-topright-home a:hover { background-position: -2px -117px; } #nav-topright li.nav-topright-dev a { width: 30px; background-position: -76px -91px; } #nav-topright li.nav-topright-dev a:hover { background-position: -76px -117px; } #nav-topright li.nav-topright-labs a { width: 40px; background-position: -114px -91px; } #nav-topright li.nav-topright-labs a:hover { background-position: -114px -117px; } #nav-topright li.nav-topright-doc a { width: 32px; background-position: -162px -91px; } #nav-topright li.nav-topright-doc a:hover, #nav-topright li.nav-topright-doc-active a { background-position: -162px -117px; } #nav-topright li.nav-topright-blog a { width: 40px; background-position: -203px -91px; } #nav-topright li.nav-topright-blog a:hover, #nav-topright li.nav-topright-blog-active a { background-position: -203px -117px; } #nav-topright li.nav-topright-shop a { width: 40px; background-position: -252px -91px; } #nav-topright li.nav-topright-shop a:hover, #nav-topright li.nav-topright-shop-active a { background-position: -252px -117px; } #nav-logo { background: transparent url(../images/sprites-combined.png ) no-repeat 0 -225px; left: -3px; position: absolute; width: 75px; height: 75px; top: 13px; } #nav-logo a { width: 75px; height: 75px; display: block; text-indent: -9999px; overflow: hidden; } .shortCut-topleft-inactive { padding-left: 3px; padding-right: 3px; background: transparent url( ../images/sprites-combined.png) no-repeat 0px -58px; height: 20px; } .shortCut-topleft-inactive span { font-variant: normal; } .shortCut-topleft-inactive span a:hover, .shortCut-topleft-active a:hover { text-decoration:none; } #shortCut { padding-top: 10px; font-weight: bolder; color: #b0adab; } #shortCut ul { list-style-type: none; float: left; width: 347px; margin-left: 100px; } #shortCut li { display: inline-block; margin-right: 25px; float: left; white-space: nowrap; } #shortCut li a { color: #b0adab; } #shortCut li a:hover { color: #44a51c; } /* end header elements */ /* content and sidebar elements */ .wrapper { background: url(../images/bg_r.png) repeat-y 100% 0; } .wrapper .hd { padding-left: 216px; height: 15px; background: url(../images/page.png) no-repeat 0 0; overflow: hidden; } .wrapper .hd span { height: 15px; display: block; overflow: hidden; background: url(../images/page.png) no-repeat 100% -30px; } .wrapper .bd { background: url(../images/bg_l.png) repeat-y 0 0; position: relative; } .wrapper .ft { padding-left: 216px; height: 15px; background: url(../images/page.png) no-repeat 0 -75px; overflow: hidden; } .wrapper .ft span { height: 15px; display: block; background: url(../images/page.png) no-repeat 100% -60px; overflow: hidden; } .navTop{ float:right; display:block; padding-right:15px; } /* end content and sidebar elements */ /* sidebar elements */ .sidebar { float: left; margin-left: 5px; width: 200px; font-size: 11px; } .sidebar .searchlabel { padding: 0 0 2px 17px; font: normal bold 11px/1.2 Verdana; } .sidebar .search { padding: 0 15px 0 16px; } .sidebar .search form { background: url(../images/sprites-combined.png) no-repeat -6px -348px; height:21px; padding:2px 0 0 5px; width:167px; } .sidebar .search form input#pageType { width: 158px; height: 19px; padding: 0; border: 0px; outline: none; font: 13px/1.2 Verdana; } .sidebar .box { padding: 17px 15px 5px 16px; } .sidebar .box .first { background-image: none; } .sidebar .box h2 { font: bold 16px/1.2 Arial; padding: 0; } .sidebar .box h2 span { overflow: hidden; display: inline-block; } .sidebar .box#lookup h2 { background-image: none; } .sidebar #lookup.box h2 span { } .sidebar .box#topics h2 { background-image: none; } .sidebar #topics.box h2 span { } .sidebar .box#examples h2 { background-image: none; } .sidebar #examples.box h2 span { } .sidebar .box .list { display: block; max-height:200px; min-height:120px; overflow-y:auto; overflow-x:none; } .list li a:hover { text-decoration: underline; } .sidebar .box ul { padding-bottom:5px; padding-left:10px; padding-top:5px; } .sidebar .box ul li { padding-left: 12px; background: url(../images/bullet_gt.png) no-repeat 0 5px; margin-bottom: 5px; } .sidebar .bottombar { background: url(../images/box_bg.png) repeat-x 0 bottom; } .sidebar .box ul li.noMatch { background: none; color:#FF2A00; font-style:italic; } .sidebar .box ul li.hit { background: none; color:#AAD2F0; font-style:italic; } .sidebar .search form input.loading { background:url("../images/spinner.gif") no-repeat scroll right center transparent; } .floatingResult{ z-index:1; position:relative; padding-top:0px; background-color:white; border:solid 1px black; height:250px; width:600px; overflow-x:hidden; overflow-y:auto; } .floatingResult:hover{ display:block; } .floatingResult:hover{ } /* end sidebar elements */ /* content elements */ .wrap { margin: 0 5px 0 208px; overflow: visible; } .wrap .toolbar { background-color: #fafafa; border-bottom: 1px solid #d1d1d1; height: 20px; position: relative; } .wrap .toolbar .toolblock { position: absolute; } .wrap .toolbar .breadcrumb { font-size: 11px; line-height: 1.2; padding: 0 0 10px 21px; height: 10px; } .wrap .toolbar .toolbuttons { padding: 0 0 10px 21px; right: 5px; vertical-align: middle; overflow: hidden; } .wrap .toolbar .toolbuttons .active { color: #00732F; } .wrap .toolbar .toolbuttons ul { float: right; } .wrap .toolbar .toolbuttons li { float: left; text-indent: -10px; margin-top: -5px; margin-right: 15px; font-weight: bold; color: #B0ADAB; } .toolbuttons #print { border-left: 1px solid #c5c4c4; margin-top: 0; padding-left: 7px; text-indent: 0; } .toolbuttons #print a { width: 16px; height: 16px; } .toolbuttons #print a span { width: 16px; height: 16px; text-indent: -999em; display: block; overflow: hidden; background: url(../images/sprites-combined.png) no-repeat -137px -311px; } .toolbuttons #smallA { font-size: 10pt; } .toolbuttons #medA { font-size: 12pt; } .toolbuttons #bigA { font-size: 14pt; margin-right: 7px; } #smallA:hover, #medA:hover, #bigA:hover { color: #00732F; } .wrap .content { padding: 30px; word-wrap:break-word; } .wrap .breadcrumb ul { } .wrap .breadcrumb ul li { float: left; background: url(../images/breadcrumb.png) no-repeat 0 3px; padding-left: 15px; margin-left: 15px; font-weight: bold; } .wrap .breadcrumb ul li.last { font-weight: normal; } .wrap .breadcrumb ul li a { color: #363534; } .wrap .breadcrumb ul li.first { background-image: none; padding-left: 0; margin-left: 0; } .wrap .content ol li { background:none; font:normal 10pt/1.2 Verdana; margin-bottom:10px; margin-left:12px; /*list-style-type:disc;*/ } .wrap .content ol li { background:none; margin-bottom: 10px; padding-left:0px; margin-left:52px; } .wrap .content li { background: url(../images/bullet_sq.png) no-repeat 0 5px; font: normal 400 10pt/1.2 Verdana; margin-bottom: 10px; padding-left:12px; } .content li:hover {} .wrap .content h1 { font: bold 18px/1.2 Arial; } .wrap .content h2 { border-bottom:1px solid #DDDDDD; font:600 16px/1.2 Arial; margin-top:15px; width:100%; } .wrap .content h3 { font: bold 14px/1.2 Arial; font:600 16px/1.2 Arial; margin-top:15px; width:100%; } .wrap .content p { line-height: 20px; padding: 5px; } .wrap .content table p { line-height: 20px; /* padding: 0px;*/ } .wrap .content ul { padding-left: 25px; padding-top: 10px; } .wrap .content ul img { vertical-align:middle; } a:hover { color: #4c0033; text-decoration: underline; } .feedback { float: none; position: absolute; right: 15px; bottom: 10px; font: normal 8px/1 Verdana; color: #B0ADAB; } .feedback:hover { float: right; font: normal 8px/1 Verdana; color: #00732F; text-decoration: underline; } .alphaChar{ width:95%; background-color:#F6F6F6; border:1px solid #E6E6E6; -moz-border-radius: 7px 7px 7px 7px; border-radius: 7px 7px 7px 7px; -webkit-border-radius: 7px 7px 7px 7px; font-size:12pt; padding-left:10px; margin-top:10px; margin-bottom:10px; } .flowList{ /*vertical-align:top;*/ /*margin:20px auto;*/ column-count:3; -webkit-column-count:3; -moz-column-count:3; /* column-width:100%; -webkit-column-width:200px; -col-column-width:200px; */ column-gap:41px; -webkit-column-gap:41px; -moz-column-gap:41px; column-rule: 1px dashed #ccc; -webkit-column-rule: 1px dashed #ccc; -moz-column-rule: 1px dashed #ccc; } .flowList dl{ } .flowList dd{ /*display:inline-block;*/ margin-left:10px; min-width:250px; line-height: 1.2; min-width:100%; } .flowList dd a{ } .wrap .content .flowList p{ padding:0px; } .content .alignedsummary { margin: 15px; } .qmltype { text-align: center; font-size: 160%; } .qmlreadonly { padding-left: 5px; float: right; color: #254117; } .qmldefault { padding-left: 5px; float: right; color: red; } .qmldoc { } *.qmlitem p { } #feedbackBox { display: none; -moz-border-radius: 7px 7px 7px 7px; -webkit-border-radius: 7px 7px 7px 7px; border-radius: 7px 7px 7px 7px; border: 1px solid #DDDDDD; position: fixed; top: 100px; left: 33%; height: 230px; width: 400px; padding: 5px; background-color: #e6e7e8; z-index: 4; } #feedcloseX { display: inline; padding: 5px 5px 0 0; margin-bottom: 3px; color: #363534; font-weight: bold; float: right; text-decoration: none; } #feedbox { display: inline; width: 370px; height: 120px; margin: 0px 25px 10px 15px; } #noteHead { font-weight:bold; padding:10px 10px 10px 20px; } #feedsubmit { display: inline; float: right; margin: 4px 32px 0 0; } .note { font-size:7pt; padding-bottom:3px; padding-left:20px; } #blurpage { display: none; position: fixed; float: none; top: 0px; left: 0px; right: 0px; bottom: 0px; background: transparent url(../images/feedbackground.png) 0 0; z-index: 3; } .toc { float: right; -moz-border-radius: 7px 7px 7px 7px; -webkit-border-radius: 7px 7px 7px 7px; border-radius: 7px 7px 7px 7px; background-color: #F6F6F6; border: 1px solid #DDDDDD; margin: 0 20px 10px 10px; padding: 20px 15px 20px 20px; height: auto; width: 200px; } .toc h3, .generic a { font: bold 12px/1.2 Arial; } .generic{ } .generic td{ /* padding:5px;*/ } .generic .alphaChar{ margin-top:5px; } .generic .odd .alphaChar{ background-color: #F6F6F6; } .generic .even .alphaChar{ background-color: #FFFFFF; } .alignedsummary{} .propsummary{} .memItemLeft{} .memItemRight{ padding:3px 15px 3px 0; } .bottomAlign{} .highlightedCode { margin:10px; } .LegaleseLeft{} .valuelist{} .annotated td{ padding: 3px 5px 3px 5px; } .obsolete{} .compat{} .flags{} .qmlsummary{} .qmlitem{} .qmlproto{} .qmlname{} .qmlreadonly{} .qmldefault{} .qmldoc{} .qt-style{} .redFont{} code{} .wrap .content .toc ul { padding-left: 0px; } .wrap .content .toc h3{ border-bottom:0px; margin-top:0px; } .wrap .content .toc h3 a:hover{ color:#00732F; text-decoration:none; } .wrap .content .toc .level2 { margin-left: 15px; } .wrap .content .toc .level3 { margin-left: 30px; } .content .toc li { font: normal 10px/1.2 Verdana; background: url(../images/bullet_dn.png) no-repeat 0 5px; } .relpage { -moz-border-radius: 7px 7px 7px 7px; -webkit-border-radius: 7px 7px 7px 7px; border-radius: 7px 7px 7px 7px; border: 1px solid #DDDDDD; padding: 25px 25px; clear: both; } .relpage ul { float: none; padding: 15px; } .content .relpage li { font: normal 11px/1.2 Verdana; } h3.fn, span.fn { -moz-border-radius:7px 7px 7px 7px; -webkit-border-radius:7px 7px 7px 7px; border-radius:7px 7px 7px 7px; background-color: #F6F6F6; border-width: 1px; border-style: solid; border-color: #E6E6E6; font-weight: bold; word-spacing:3px; padding:3px 5px; } .functionIndex { font-size:12pt; word-spacing:10px; margin-bottom:10px; background-color: #F6F6F6; border-width: 1px; border-style: solid; border-color: #E6E6E6; -moz-border-radius: 7px 7px 7px 7px; -webkit-border-radius: 7px 7px 7px 7px; border-radius: 7px 7px 7px 7px; width:100%; } .centerAlign { text-align:center; } .rightAlign { text-align:right; } .leftAlign { text-align:left; } .topAlign{ vertical-align:top } .functionIndex a{ display:inline-block; } /* end content elements */ /* footer elements */ .footer { min-height: 100px; color: #797775; font: normal 9px/1 Verdana; text-align: center; padding-top: 40px; background-color: #E6E7E8; margin: 0; } /* end footer elements */ /* start index box */ .indexbox { width: 100%; display:inline-block; } .indexboxcont { display: block; } .indexboxbar { background: transparent url(../images/horBar.png ) repeat-x left bottom; margin-bottom: 25px; } .indexboxcont .section { display: inline-block; width: 49%; *width:42%; _width:42%; padding:0 2% 0 1%; vertical-align:top; } .indexboxcont .indexIcon { width: 11%; *width:18%; _width:18%; overflow:hidden; } .indexboxcont .section { float: left; } .indexboxcont .section p { padding-top: 20px; padding-bottom: 20px; } .indexboxcont .sectionlist { display: inline-block; vertical-align:top; width: 32.5%; padding: 0; } .indexboxcont .sectionlist ul { margin-bottom: 20px; } .indexboxcont .sectionlist ul li { line-height: 12px; } .content .indexboxcont li { font: normal bold 13px/1 Verdana; } .indexbox a:hover, .indexbox a:visited:hover { color: #4c0033; text-decoration: underline; } .indexbox a:visited { color: #00732f; text-decoration: none; } .indexbox .indexIcon { width: 11%; } .indexbox .indexIcon span { display: block; } .indexbox.guide .indexIcon span { width: 96px; height: 137px; background: url(../images/sprites-combined.png) no-repeat -5px -376px; padding: 0; } .indexbox.tools .indexIcon span { width: 115px; height: 137px; background: url(../images/sprites-combined.png) no-repeat -111px -376px; padding: 0; } .indexboxcont:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } /* start of creator spec*/ .creator { margin-left:0px; margin-right:0px; padding-left:0px; padding-right:0px; } .creator .wrap .content ol li { list-style-type:decimal; } .creator .header .icon, .creator .feedback, .creator .t_button, .creator .feedback, .creator #feedbackBox, .creator #feedback, .creator #blurpage, /*.creator .indexbox .indexIcon span,*/ .creator .wrapper .hd, /* .creator .indexbox .indexIcon,*/ .creator .header #nav-logo, .creator #offlinemenu, .creator #offlinesearch, .creator .header #nav-topright, .creator .header #shortCut , .creator .wrapper .hd, .creator .wrapper .ft, .creator .sidebar, .creator .wrap .feedback { display:none; } body.creator { background: none; font: normal 13px/1.2 Verdana; color: #363534; background-color: #FAFAFA; } .wrap .content ol li { } .creator .header, .footer, .wrapper { max-width: 1500px; margin: 0px; } .creator .wrapper { position:relative; top:5px; } .creator .wrapper .bd { background:#FFFFFF; } .creator .header, .footer { display: block; clear: both; overflow: hidden; } .creator .wrap .content p { line-height: 20px; padding: 5px; } .creator .header .qtref span { background:none; } .creator .footer { border-top:1px solid #E5E5E5; height: 50px; margin:0px; padding:10px; } .creator .footer p { text-align:justify; max-width:900px; } .creator .wrap { padding:0 5px 0 5px; margin: 0px; } .creator .wrap .toolbar { border-bottom:1px solid #E5E5E5; /*width:100%;*/ margin-left:-5px; margin-right:-5px; } .creator .wrap .breadcrumb ul li a { /* color: #363534;*/ color: #00732F; } .creator .wrap .content { padding: 0px; word-wrap:break-word; } .creator .wrap .content ol li { background:none; font: inherit; padding-left: 0px; } .creator .wrap .content .descr ol li { margin-left: 45px; } .creator .content .alignedsummary { margin: 5px; width:100%; } .creator .generic{ max-width:75%; } .creator .generic td{ /* padding:0;*/ } .creator .indexboxbar { border-bottom:1px solid #E5E5E5; margin-bottom: 25px; background: none; } .creator .header { width: 100%; margin: 0; height: auto; background-color: #ffffff; padding: 10px 0 5px 0; overflow: visible; border-bottom: solid #E5E5E5 1px; z-index:1; /* position:fixed;*/ } .creator .header .content { } .creator .header .qtref { color: #00732F; position: static; float: left; margin-left: 5px; font: bold 18px/1 Arial; } .creator .header .qtref:visited { color: #00732F; } .creator .header .qtref:hover { color: #00732F; text-decoration:none; } .creator .header .qtref span { background-image: none; text-indent: 0; text-decoration:none; } .creator .wrap .toolbar { display:block; padding-top:0px; } .creator .wrap .breadcrumb ul li { font-weight: normal; } .creator .wrap .breadcrumb ul li a { /*color: #44a51c;*/ } .creator .wrap .breadcrumb ul li.last a { /*color: #363534;*/ } .creator #narrowmenu ul { border-bottom:solid 1px #E5E5E5; border-left:solid 1px #E5E5E5; border-right:solid 1px #E5E5E5; } .creator #narrowmenu li ul { margin-top:-15px; } .creator .toc { margin:10px 20px 10px 10px; } .creator #narrowsearch, .creator #narrowmenu{ display:none; } /* end of creator spec*/ } /* end of screen media */ /* start of print media */ @media print { input, textarea, .header, .footer, .toolbar, .feedback, .wrapper .hd, .wrapper .bd .sidebar, .wrapper .ft, #feedbackBox, #blurpage, .toc, .breadcrumb, .toolbar, .floatingResult { display: none; background: none; } .content { background: none; display: block; width: 100%; margin: 0; float: none; } } /* end of print media */ qbs-src-1.4.5/doc/templates/style/style_ie6.css000066400000000000000000000012301266132464200214150ustar00rootroot00000000000000.indexbox, .indexboxcont, .group { zoom: 1; height: 1%; } .sidebar { margin-left: 3px; width: 199px; overflow: hidden; } .sidebar .search form { position: relative; } .sidebar .search form fieldset { position: absolute; margin-top: -1px; } .sidebar .search form input#searchstring { border: 1px solid #fff; height: 18px; } .wrap { zoom: 1; } .content, .toolbar { zoom: 1; margin-left: -3px; position: relative; } .indexbox { clear: both; } .indexboxcont .section { zoom: 1; float: left; } .indexboxcont .sectionlist { zoom: 1; float: left; } .wrap .toolbar .toolbuttons li { text-indent: 0; margin-right: 8px; }qbs-src-1.4.5/doc/templates/style/style_ie7.css000066400000000000000000000004021266132464200214160ustar00rootroot00000000000000.indexbox, .indexboxcont, .group { min-height: 1px; } .sidebar .search form input#searchstring { border: 1px solid #fff; height: 17px; } .indexboxcont .section { zoom: 1; float: left; } .indexboxcont .sectionlist { zoom: 1; float: left; } qbs-src-1.4.5/doc/templates/style/style_ie8.css000066400000000000000000000000001266132464200214110ustar00rootroot00000000000000qbs-src-1.4.5/doc/templates/style/superfish.css000066400000000000000000000016521266132464200215320ustar00rootroot00000000000000.sf-menu, .sf-menu * { margin: 0; padding: 0; list-style: none; } .sf-menu { line-height: 1.0; } .sf-menu ul { position: absolute; top: -999em; width: 10em; /* left offset of submenus need to match (see below) */ } .sf-menu ul li { width: 100%; } .sf-menu li:hover { visibility: inherit; /* fixes IE7 'sticky bug' */ } .sf-menu li { float: left; position: relative; } .sf-menu a { display: block; position: relative; } .sf-menu li:hover ul, .sf-menu li.sfHover ul { left: 0; top: 2.5em; /* match top ul list item height */ z-index: 99; } ul.sf-menu li:hover li ul, ul.sf-menu li.sfHover li ul { top: -999em; } ul.sf-menu li li:hover ul, ul.sf-menu li li.sfHover ul { left: 10em; /* match ul width */ top: 0; } ul.sf-menu li li:hover li ul, ul.sf-menu li li.sfHover li ul { top: -999em; } ul.sf-menu li li li:hover ul, ul.sf-menu li li li.sfHover ul { left: 10em; /* match ul width */ top: 0; } qbs-src-1.4.5/doc/templates/style/superfish_skin.css000066400000000000000000000044111266132464200225520ustar00rootroot00000000000000 /*** DEMO SKIN ***/ .sf-menu { float: left; margin-bottom: 1em; } .sf-menu a { border-left: 1px solid #fff; border-top: 1px solid #CFDEFF; padding: .75em 1em; text-decoration:none; } .sf-menu a, .sf-menu a:visited { /* visited pseudo selector so IE6 applies text colour*/ color: #13a; } .sf-menu li { background: #BDD2FF; } .sf-menu li li { background: #AABDE6; } .sf-menu li li li { background: #9AAEDB; } .sf-menu li:hover, .sf-menu li.sfHover, .sf-menu a:focus, .sf-menu a:hover, .sf-menu a:active { background: #CFDEFF; outline: 0; } /*** arrows **/ .sf-menu a.sf-with-ul { padding-right: 2.25em; min-width: 1px; /* trigger IE7 hasLayout so spans position accurately */ } .sf-sub-indicator { position: absolute; display: block; right: .75em; top: 1.05em; /* IE6 only */ width: 10px; height: 10px; text-indent: -999em; overflow: hidden; background: url('../images/arrows-ffffff.png') no-repeat -10px -100px; /* 8-bit indexed alpha png. IE6 gets solid image only */ } a > .sf-sub-indicator { /* give all except IE6 the correct values */ top: .8em; background-position: 0 -100px; /* use translucent arrow for modern browsers*/ } /* apply hovers to modern browsers */ a:focus > .sf-sub-indicator, a:hover > .sf-sub-indicator, a:active > .sf-sub-indicator, li:hover > a > .sf-sub-indicator, li.sfHover > a > .sf-sub-indicator { background-position: -10px -100px; /* arrow hovers for modern browsers*/ } /* point right for anchors in subs */ .sf-menu ul .sf-sub-indicator { background-position: -10px 0; } .sf-menu ul a > .sf-sub-indicator { background-position: 0 0; } /* apply hovers to modern browsers */ .sf-menu ul a:focus > .sf-sub-indicator, .sf-menu ul a:hover > .sf-sub-indicator, .sf-menu ul a:active > .sf-sub-indicator, .sf-menu ul li:hover > a > .sf-sub-indicator, .sf-menu ul li.sfHover > a > .sf-sub-indicator { background-position: -10px 0; /* arrow hovers for modern browsers*/ } /*** shadows for all but IE6 ***/ .sf-shadow ul { background: url('../images/shadow.png') no-repeat bottom right; padding: 0 8px 9px 0; -moz-border-radius-bottomleft: 17px; -moz-border-radius-topright: 17px; -webkit-border-top-right-radius: 17px; -webkit-border-bottom-left-radius: 17px; } .sf-shadow ul.sf-shadow-off { background: transparent; } qbs-src-1.4.5/examples/000077500000000000000000000000001266132464200147175ustar00rootroot00000000000000qbs-src-1.4.5/examples/app-and-lib/000077500000000000000000000000001266132464200170035ustar00rootroot00000000000000qbs-src-1.4.5/examples/app-and-lib/app/000077500000000000000000000000001266132464200175635ustar00rootroot00000000000000qbs-src-1.4.5/examples/app-and-lib/app/app.qbs000066400000000000000000000041351266132464200210550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ import qbs 1.0 Product { type: "application" consoleApplication: true name : "app-and-lib-app" files : [ "main.cpp" ] Depends { name: "cpp" } Depends { name: "app-and-lib-lib" } } qbs-src-1.4.5/examples/app-and-lib/app/main.cpp000066400000000000000000000030531266132464200212140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include int main() { return bla(); } qbs-src-1.4.5/examples/app-and-lib/app_and_lib.qbs000066400000000000000000000037611266132464200217510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ import qbs 1.0 Project { references: [ "app/app.qbs", "lib/lib.qbs" ] } qbs-src-1.4.5/examples/app-and-lib/lib/000077500000000000000000000000001266132464200175515ustar00rootroot00000000000000qbs-src-1.4.5/examples/app-and-lib/lib/lib.cpp000066400000000000000000000032061266132464200210240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #ifndef CRUCIAL_DEFINE # error CRUCIAL_DEFINE not defined #endif int bla() { puts("Hello World!"); return 2; } qbs-src-1.4.5/examples/app-and-lib/lib/lib.h000066400000000000000000000000711266132464200204660ustar00rootroot00000000000000#ifndef LIB_H #define LIB_H int bla(); #endif // LIB_H qbs-src-1.4.5/examples/app-and-lib/lib/lib.qbs000066400000000000000000000043011266132464200210240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ import qbs 1.0 Product { type: "staticlibrary" name: "app-and-lib-lib" files: [ "lib.cpp", "lib.h", ] cpp.defines: ['CRUCIAL_DEFINE'] Depends { name: 'cpp' } Export { Depends { name: "cpp" } cpp.includePaths: [product.sourceDirectory] } } qbs-src-1.4.5/examples/cocoa-application/000077500000000000000000000000001266132464200203045ustar00rootroot00000000000000qbs-src-1.4.5/examples/cocoa-application/CocoaApplication.qbs000066400000000000000000000052651266132464200242330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ import qbs 1.0 CppApplication { Depends { condition: product.condition; name: "ib" } condition: qbs.targetOS.contains("osx") name: "Cocoa Application" cpp.precompiledHeader: "CocoaApplication/CocoaApplication-Prefix.pch" bundle.infoPlistFile: "CocoaApplication/CocoaApplication-Info.plist" cpp.frameworks: ["Cocoa"] Group { prefix: "CocoaApplication/" files: [ "AppDelegate.h", "AppDelegate.m", "CocoaApplication-Prefix.pch", "main.m" ] } Group { name: "Supporting Files" prefix: "CocoaApplication/en.lproj/" files: [ "Credits.rtf", "InfoPlist.strings", "MainMenu.xib" ] } } qbs-src-1.4.5/examples/cocoa-application/CocoaApplication.xcodeproj/000077500000000000000000000000001266132464200255105ustar00rootroot00000000000000qbs-src-1.4.5/examples/cocoa-application/CocoaApplication.xcodeproj/project.pbxproj000066400000000000000000000345071266132464200305750ustar00rootroot00000000000000// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 14ABF7A71717761200140DA2 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 14ABF7A61717761200140DA2 /* Cocoa.framework */; }; 14ABF7B11717761200140DA2 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 14ABF7AF1717761200140DA2 /* InfoPlist.strings */; }; 14ABF7B31717761200140DA2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 14ABF7B21717761200140DA2 /* main.m */; }; 14ABF7B71717761200140DA2 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 14ABF7B51717761200140DA2 /* Credits.rtf */; }; 14ABF7BA1717761200140DA2 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 14ABF7B91717761200140DA2 /* AppDelegate.m */; }; 14ABF7BD1717761300140DA2 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 14ABF7BB1717761300140DA2 /* MainMenu.xib */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 14ABF7A31717761200140DA2 /* Cocoa Application.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Cocoa Application.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 14ABF7A61717761200140DA2 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 14ABF7A91717761200140DA2 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 14ABF7AA1717761200140DA2 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 14ABF7AB1717761200140DA2 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 14ABF7AE1717761200140DA2 /* CocoaApplication-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "CocoaApplication-Info.plist"; sourceTree = ""; }; 14ABF7B01717761200140DA2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 14ABF7B21717761200140DA2 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 14ABF7B41717761200140DA2 /* CocoaApplication-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CocoaApplication-Prefix.pch"; sourceTree = ""; }; 14ABF7B61717761200140DA2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; 14ABF7B81717761200140DA2 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 14ABF7B91717761200140DA2 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 14ABF7BC1717761300140DA2 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 14ABF7A01717761200140DA2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 14ABF7A71717761200140DA2 /* Cocoa.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 14ABF79A1717761200140DA2 = { isa = PBXGroup; children = ( 14ABF7AC1717761200140DA2 /* CocoaApplication */, 14ABF7A51717761200140DA2 /* Frameworks */, 14ABF7A41717761200140DA2 /* Products */, ); sourceTree = ""; }; 14ABF7A41717761200140DA2 /* Products */ = { isa = PBXGroup; children = ( 14ABF7A31717761200140DA2 /* Cocoa Application.app */, ); name = Products; sourceTree = ""; }; 14ABF7A51717761200140DA2 /* Frameworks */ = { isa = PBXGroup; children = ( 14ABF7A61717761200140DA2 /* Cocoa.framework */, 14ABF7A81717761200140DA2 /* Other Frameworks */, ); name = Frameworks; sourceTree = ""; }; 14ABF7A81717761200140DA2 /* Other Frameworks */ = { isa = PBXGroup; children = ( 14ABF7A91717761200140DA2 /* AppKit.framework */, 14ABF7AA1717761200140DA2 /* CoreData.framework */, 14ABF7AB1717761200140DA2 /* Foundation.framework */, ); name = "Other Frameworks"; sourceTree = ""; }; 14ABF7AC1717761200140DA2 /* CocoaApplication */ = { isa = PBXGroup; children = ( 14ABF7B81717761200140DA2 /* AppDelegate.h */, 14ABF7B91717761200140DA2 /* AppDelegate.m */, 14ABF7BB1717761300140DA2 /* MainMenu.xib */, 14ABF7AD1717761200140DA2 /* Supporting Files */, ); path = CocoaApplication; sourceTree = ""; }; 14ABF7AD1717761200140DA2 /* Supporting Files */ = { isa = PBXGroup; children = ( 14ABF7AE1717761200140DA2 /* CocoaApplication-Info.plist */, 14ABF7AF1717761200140DA2 /* InfoPlist.strings */, 14ABF7B21717761200140DA2 /* main.m */, 14ABF7B41717761200140DA2 /* CocoaApplication-Prefix.pch */, 14ABF7B51717761200140DA2 /* Credits.rtf */, ); name = "Supporting Files"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 14ABF7A21717761200140DA2 /* Cocoa Application */ = { isa = PBXNativeTarget; buildConfigurationList = 14ABF7C01717761300140DA2 /* Build configuration list for PBXNativeTarget "Cocoa Application" */; buildPhases = ( 14ABF79F1717761200140DA2 /* Sources */, 14ABF7A01717761200140DA2 /* Frameworks */, 14ABF7A11717761200140DA2 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = "Cocoa Application"; productName = CocoaApplication; productReference = 14ABF7A31717761200140DA2 /* Cocoa Application.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 14ABF79B1717761200140DA2 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0460; ORGANIZATIONNAME = "Petroules Corporation"; }; buildConfigurationList = 14ABF79E1717761200140DA2 /* Build configuration list for PBXProject "CocoaApplication" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 14ABF79A1717761200140DA2; productRefGroup = 14ABF7A41717761200140DA2 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 14ABF7A21717761200140DA2 /* Cocoa Application */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 14ABF7A11717761200140DA2 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 14ABF7B11717761200140DA2 /* InfoPlist.strings in Resources */, 14ABF7B71717761200140DA2 /* Credits.rtf in Resources */, 14ABF7BD1717761300140DA2 /* MainMenu.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 14ABF79F1717761200140DA2 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 14ABF7B31717761200140DA2 /* main.m in Sources */, 14ABF7BA1717761200140DA2 /* AppDelegate.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 14ABF7AF1717761200140DA2 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( 14ABF7B01717761200140DA2 /* en */, ); name = InfoPlist.strings; sourceTree = ""; }; 14ABF7B51717761200140DA2 /* Credits.rtf */ = { isa = PBXVariantGroup; children = ( 14ABF7B61717761200140DA2 /* en */, ); name = Credits.rtf; sourceTree = ""; }; 14ABF7BB1717761300140DA2 /* MainMenu.xib */ = { isa = PBXVariantGroup; children = ( 14ABF7BC1717761300140DA2 /* en */, ); name = MainMenu.xib; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 14ABF7BE1717761300140DA2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.8; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; }; name = Debug; }; 14ABF7BF1717761300140DA2 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.8; SDKROOT = macosx; }; name = Release; }; 14ABF7C11717761300140DA2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "CocoaApplication/CocoaApplication-Prefix.pch"; INFOPLIST_FILE = "CocoaApplication/CocoaApplication-Info.plist"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; name = Debug; }; 14ABF7C21717761300140DA2 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { COMBINE_HIDPI_IMAGES = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "CocoaApplication/CocoaApplication-Prefix.pch"; INFOPLIST_FILE = "CocoaApplication/CocoaApplication-Info.plist"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 14ABF79E1717761200140DA2 /* Build configuration list for PBXProject "CocoaApplication" */ = { isa = XCConfigurationList; buildConfigurations = ( 14ABF7BE1717761300140DA2 /* Debug */, 14ABF7BF1717761300140DA2 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 14ABF7C01717761300140DA2 /* Build configuration list for PBXNativeTarget "Cocoa Application" */ = { isa = XCConfigurationList; buildConfigurations = ( 14ABF7C11717761300140DA2 /* Debug */, 14ABF7C21717761300140DA2 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 14ABF79B1717761200140DA2 /* Project object */; } qbs-src-1.4.5/examples/cocoa-application/CocoaApplication/000077500000000000000000000000001266132464200235145ustar00rootroot00000000000000qbs-src-1.4.5/examples/cocoa-application/CocoaApplication/AppDelegate.h000066400000000000000000000032161266132464200260420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import @interface AppDelegate : NSObject @property (nonatomic, assign) IBOutlet NSWindow *window; @end qbs-src-1.4.5/examples/cocoa-application/CocoaApplication/AppDelegate.m000066400000000000000000000034131266132464200260460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import "AppDelegate.h" @implementation AppDelegate @synthesize window = _window; - (void)dealloc { [super dealloc]; } - (void)applicationDidFinishLaunching:(NSNotification *) __unused aNotification { // Insert code here to initialize your application } @end qbs-src-1.4.5/examples/cocoa-application/CocoaApplication/CocoaApplication-Info.plist000066400000000000000000000022541266132464200306750ustar00rootroot00000000000000 CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIconFile CFBundleIdentifier com.petroules.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSMinimumSystemVersion ${MACOSX_DEPLOYMENT_TARGET} NSHumanReadableCopyright Copyright © 2014 Petroules Corporation. All rights reserved. NSMainNibFile MainMenu NSPrincipalClass NSApplication qbs-src-1.4.5/examples/cocoa-application/CocoaApplication/CocoaApplication-Prefix.pch000066400000000000000000000030561266132464200306570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifdef __OBJC__ #import #endif qbs-src-1.4.5/examples/cocoa-application/CocoaApplication/en.lproj/000077500000000000000000000000001266132464200252435ustar00rootroot00000000000000qbs-src-1.4.5/examples/cocoa-application/CocoaApplication/en.lproj/Credits.rtf000066400000000000000000000007031266132464200273550ustar00rootroot00000000000000{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} {\colortbl;\red255\green255\blue255;} \paperw9840\paperh8400 \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural \f0\b\fs24 \cf0 Engineering: \b0 \ Some people\ \ \b Human Interface Design: \b0 \ Some other people\ \ \b Testing: \b0 \ Hopefully not nobody\ \ \b Documentation: \b0 \ Whoever\ \ \b With special thanks to: \b0 \ Mom\ } qbs-src-1.4.5/examples/cocoa-application/CocoaApplication/en.lproj/InfoPlist.strings000066400000000000000000000000541266132464200305640ustar00rootroot00000000000000/* Localized versions of Info.plist keys */ qbs-src-1.4.5/examples/cocoa-application/CocoaApplication/en.lproj/MainMenu.xib000066400000000000000000011340171266132464200274670ustar00rootroot00000000000000 1080 11D50 2457 1138.32 568.00 com.apple.InterfaceBuilder.CocoaPlugin 2457 NSWindowTemplate NSView NSMenu NSMenuItem NSCustomObject com.apple.InterfaceBuilder.CocoaPlugin PluginDependencyRecalculationVersion NSApplication FirstResponder NSApplication AMainMenu CocoaApplication 1048576 2147483647 NSImage NSMenuCheckmark NSImage NSMenuMixedState submenuAction: CocoaApplication About CocoaApplication 2147483647 YES YES 1048576 2147483647 Preferences… , 1048576 2147483647 YES YES 1048576 2147483647 Services 1048576 2147483647 submenuAction: Services _NSServicesMenu YES YES 1048576 2147483647 Hide CocoaApplication h 1048576 2147483647 Hide Others h 1572864 2147483647 Show All 1048576 2147483647 YES YES 1048576 2147483647 Quit CocoaApplication q 1048576 2147483647 _NSAppleMenu File 1048576 2147483647 submenuAction: File New n 1048576 2147483647 Open… o 1048576 2147483647 Open Recent 1048576 2147483647 submenuAction: Open Recent Clear Menu 1048576 2147483647 _NSRecentDocumentsMenu YES YES 1048576 2147483647 Close w 1048576 2147483647 Save… s 1048576 2147483647 Revert to Saved 2147483647 YES YES 1048576 2147483647 Page Setup... P 1179648 2147483647 Print… p 1048576 2147483647 Edit 1048576 2147483647 submenuAction: Edit Undo z 1048576 2147483647 Redo Z 1179648 2147483647 YES YES 1048576 2147483647 Cut x 1048576 2147483647 Copy c 1048576 2147483647 Paste v 1048576 2147483647 Paste and Match Style V 1572864 2147483647 Delete 1048576 2147483647 Select All a 1048576 2147483647 YES YES 1048576 2147483647 Find 1048576 2147483647 submenuAction: Find Find… f 1048576 2147483647 1 Find and Replace… f 1572864 2147483647 12 Find Next g 1048576 2147483647 2 Find Previous G 1179648 2147483647 3 Use Selection for Find e 1048576 2147483647 7 Jump to Selection j 1048576 2147483647 Spelling and Grammar 1048576 2147483647 submenuAction: Spelling and Grammar Show Spelling and Grammar : 1048576 2147483647 Check Document Now ; 1048576 2147483647 YES YES 2147483647 Check Spelling While Typing 1048576 2147483647 Check Grammar With Spelling 1048576 2147483647 Correct Spelling Automatically 2147483647 Substitutions 1048576 2147483647 submenuAction: Substitutions Show Substitutions 2147483647 YES YES 2147483647 Smart Copy/Paste f 1048576 2147483647 1 Smart Quotes g 1048576 2147483647 2 Smart Dashes 2147483647 Smart Links G 1179648 2147483647 3 Text Replacement 2147483647 Transformations 2147483647 submenuAction: Transformations Make Upper Case 2147483647 Make Lower Case 2147483647 Capitalize 2147483647 Speech 1048576 2147483647 submenuAction: Speech Start Speaking 1048576 2147483647 Stop Speaking 1048576 2147483647 Format 2147483647 submenuAction: Format Font 2147483647 submenuAction: Font Show Fonts t 1048576 2147483647 Bold b 1048576 2147483647 2 Italic i 1048576 2147483647 1 Underline u 1048576 2147483647 YES YES 2147483647 Bigger + 1048576 2147483647 3 Smaller - 1048576 2147483647 4 YES YES 2147483647 Kern 2147483647 submenuAction: Kern Use Default 2147483647 Use None 2147483647 Tighten 2147483647 Loosen 2147483647 Ligatures 2147483647 submenuAction: Ligatures Use Default 2147483647 Use None 2147483647 Use All 2147483647 Baseline 2147483647 submenuAction: Baseline Use Default 2147483647 Superscript 2147483647 Subscript 2147483647 Raise 2147483647 Lower 2147483647 YES YES 2147483647 Show Colors C 1048576 2147483647 YES YES 2147483647 Copy Style c 1572864 2147483647 Paste Style v 1572864 2147483647 _NSFontMenu Text 2147483647 submenuAction: Text Align Left { 1048576 2147483647 Center | 1048576 2147483647 Justify 2147483647 Align Right } 1048576 2147483647 YES YES 2147483647 Writing Direction 2147483647 submenuAction: Writing Direction YES Paragraph 2147483647 CURlZmF1bHQ 2147483647 CUxlZnQgdG8gUmlnaHQ 2147483647 CVJpZ2h0IHRvIExlZnQ 2147483647 YES YES 2147483647 YES Selection 2147483647 CURlZmF1bHQ 2147483647 CUxlZnQgdG8gUmlnaHQ 2147483647 CVJpZ2h0IHRvIExlZnQ 2147483647 YES YES 2147483647 Show Ruler 2147483647 Copy Ruler c 1310720 2147483647 Paste Ruler v 1310720 2147483647 View 1048576 2147483647 submenuAction: View Show Toolbar t 1572864 2147483647 Customize Toolbar… 1048576 2147483647 Window 1048576 2147483647 submenuAction: Window Minimize m 1048576 2147483647 Zoom 1048576 2147483647 YES YES 1048576 2147483647 Bring All to Front 1048576 2147483647 _NSWindowsMenu Help 2147483647 submenuAction: Help CocoaApplication Help ? 1048576 2147483647 _NSHelpMenu _NSMainMenu 15 2 {{335, 390}, {480, 360}} 1954021376 CocoaApplication NSWindow 256 {480, 360} {{0, 0}, {2560, 1418}} {10000000000000, 10000000000000} YES AppDelegate NSFontManager terminate: 449 orderFrontStandardAboutPanel: 142 delegate 495 performMiniaturize: 37 arrangeInFront: 39 print: 86 runPageLayout: 87 clearRecentDocuments: 127 performClose: 193 toggleContinuousSpellChecking: 222 undo: 223 copy: 224 checkSpelling: 225 paste: 226 stopSpeaking: 227 cut: 228 showGuessPanel: 230 redo: 231 selectAll: 232 startSpeaking: 233 delete: 235 performZoom: 240 performFindPanelAction: 241 centerSelectionInVisibleArea: 245 toggleGrammarChecking: 347 toggleSmartInsertDelete: 355 toggleAutomaticQuoteSubstitution: 356 toggleAutomaticLinkDetection: 357 saveDocument: 362 revertDocumentToSaved: 364 runToolbarCustomizationPalette: 365 toggleToolbarShown: 366 hide: 367 hideOtherApplications: 368 unhideAllApplications: 370 newDocument: 373 openDocument: 374 raiseBaseline: 426 lowerBaseline: 427 copyFont: 428 subscript: 429 superscript: 430 tightenKerning: 431 underline: 432 orderFrontColorPanel: 433 useAllLigatures: 434 loosenKerning: 435 pasteFont: 436 unscript: 437 useStandardKerning: 438 useStandardLigatures: 439 turnOffLigatures: 440 turnOffKerning: 441 toggleAutomaticSpellingCorrection: 456 orderFrontSubstitutionsPanel: 458 toggleAutomaticDashSubstitution: 461 toggleAutomaticTextReplacement: 463 uppercaseWord: 464 capitalizeWord: 467 lowercaseWord: 468 pasteAsPlainText: 486 performFindPanelAction: 487 performFindPanelAction: 488 performFindPanelAction: 489 showHelp: 493 alignCenter: 518 pasteRuler: 519 toggleRuler: 520 alignRight: 521 copyRuler: 522 alignJustified: 523 alignLeft: 524 makeBaseWritingDirectionNatural: 525 makeBaseWritingDirectionLeftToRight: 526 makeBaseWritingDirectionRightToLeft: 527 makeTextWritingDirectionNatural: 528 makeTextWritingDirectionLeftToRight: 529 makeTextWritingDirectionRightToLeft: 530 performFindPanelAction: 535 addFontTrait: 421 addFontTrait: 422 modifyFont: 423 orderFrontFontPanel: 424 modifyFont: 425 window 532 0 -2 File's Owner -1 First Responder -3 Application 29 19 56 217 83 81 75 78 72 82 124 77 73 79 112 74 125 126 205 202 198 207 214 199 203 197 206 215 218 216 200 219 201 204 220 213 210 221 208 209 57 58 134 150 136 144 129 143 236 131 149 145 130 24 92 5 239 23 295 296 297 298 211 212 195 196 346 348 349 350 351 354 371 372 375 376 377 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 450 451 452 453 454 457 459 460 462 465 466 485 490 491 492 494 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 534 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin {{380, 496}, {480, 360}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin 535 ABCardController NSObject id id id id id id id addCardViewField: id copy: id cut: id doDelete: id find: id paste: id saveChanges: id ABCardView NSButton NSManagedObjectContext NSSearchField NSTextField NSWindow mCardView ABCardView mEditButton NSButton mManagedObjectContext NSManagedObjectContext mSearchField NSSearchField mStatusTextField NSTextField mWindow NSWindow IBProjectSource ./Classes/ABCardController.h ABCardView NSView id id commitAndSave: id statusImageClicked: id NSObjectController NSImageView NSView ABNameFrameView NSView NSImage ABImageView mBindingsController NSObjectController mBuddyStatusImage NSImageView mHeaderView NSView mNameView ABNameFrameView mNextKeyView NSView mUserImage NSImage mUserImageView ABImageView IBProjectSource ./Classes/ABCardView.h ABImageView NSImageView id id id id copy: id cut: id delete: id paste: id IBProjectSource ./Classes/ABImageView.h DVTBorderedView DVTLayoutView_ML contentView NSView contentView contentView NSView IBProjectSource ./Classes/DVTBorderedView.h DVTDelayedMenuButton NSButton IBProjectSource ./Classes/DVTDelayedMenuButton.h DVTGradientImageButton NSButton IBProjectSource ./Classes/DVTGradientImageButton.h DVTImageAndTextCell NSTextFieldCell IBProjectSource ./Classes/DVTImageAndTextCell.h DVTImageAndTextColumn NSTableColumn IBProjectSource ./Classes/DVTImageAndTextColumn.h DVTLayoutView_ML NSView IBProjectSource ./Classes/DVTLayoutView_ML.h DVTOutlineView NSOutlineView IBProjectSource ./Classes/DVTOutlineView.h DVTSplitView NSSplitView IBProjectSource ./Classes/DVTSplitView.h DVTStackView_ML DVTLayoutView_ML IBProjectSource ./Classes/DVTStackView_ML.h DVTTableView NSTableView IBProjectSource ./Classes/DVTTableView.h DVTViewController NSViewController IBProjectSource ./Classes/DVTViewController.h HFController NSObject selectAll: id selectAll: selectAll: id IBProjectSource ./Classes/HFController.h HFRepresenterTextView NSView selectAll: id selectAll: selectAll: id IBProjectSource ./Classes/HFRepresenterTextView.h IBEditor NSObject id id id id id changeFont: id performCopy: id performCut: id selectAll: id sizeSelectionToFit: id IBProjectSource ./Classes/IBEditor.h IDECapsuleListView DVTStackView_ML dataSource id dataSource dataSource id IBProjectSource ./Classes/IDECapsuleListView.h IDEDMArrayController NSArrayController IBProjectSource ./Classes/IDEDMArrayController.h IDEDMEditor IDEEditor DVTBorderedView NSView IDEDMEditorSourceListController DVTSplitView bottomToolbarBorderView DVTBorderedView sourceListSplitViewPane NSView sourceListViewController IDEDMEditorSourceListController splitView DVTSplitView IBProjectSource ./Classes/IDEDMEditor.h IDEDMEditorController IDEViewController IBProjectSource ./Classes/IDEDMEditorController.h IDEDMEditorSourceListController IDEDMEditorController DVTBorderedView IDEDMEditor DVTImageAndTextColumn DVTOutlineView NSTreeController borderedView DVTBorderedView parentEditor IDEDMEditor primaryColumn DVTImageAndTextColumn sourceListOutlineView DVTOutlineView sourceListTreeController NSTreeController IBProjectSource ./Classes/IDEDMEditorSourceListController.h IDEDMHighlightImageAndTextCell DVTImageAndTextCell IBProjectSource ./Classes/IDEDMHighlightImageAndTextCell.h IDEDataModelBrowserEditor IDEDMEditorController IDEDataModelPropertiesTableController IDECapsuleListView NSArrayController IDEDataModelPropertiesTableController IDEDataModelEntityContentsEditor IDEDataModelPropertiesTableController attributesTableViewController IDEDataModelPropertiesTableController capsuleView IDECapsuleListView entityArrayController NSArrayController fetchedPropertiesTableViewController IDEDataModelPropertiesTableController parentEditor IDEDataModelEntityContentsEditor relationshipsTableViewController IDEDataModelPropertiesTableController IBProjectSource ./Classes/IDEDataModelBrowserEditor.h IDEDataModelConfigurationEditor IDEDMEditorController IDECapsuleListView IDEDataModelEditor IDEDataModelConfigurationTableController capsuleListView IDECapsuleListView parentEditor IDEDataModelEditor tableController IDEDataModelConfigurationTableController IBProjectSource ./Classes/IDEDataModelConfigurationEditor.h IDEDataModelConfigurationTableController IDEDMEditorController NSArrayController NSArrayController IDEDataModelConfigurationEditor XDTableView configurationsArrayController NSArrayController entitiesArrayController NSArrayController parentEditor IDEDataModelConfigurationEditor tableView XDTableView IBProjectSource ./Classes/IDEDataModelConfigurationTableController.h IDEDataModelDiagramEditor IDEDMEditorController XDDiagramView IDEDataModelEntityContentsEditor diagramView XDDiagramView parentEditor IDEDataModelEntityContentsEditor IBProjectSource ./Classes/IDEDataModelDiagramEditor.h IDEDataModelEditor IDEDMEditor DVTDelayedMenuButton DVTDelayedMenuButton NSSegmentedControl IDEDataModelConfigurationEditor IDEDataModelEntityContentsEditor IDEDataModelFetchRequestEditor NSSegmentedControl NSTabView addEntityButton DVTDelayedMenuButton addPropertyButton DVTDelayedMenuButton browserDiagramSegmentControl NSSegmentedControl configurationViewController IDEDataModelConfigurationEditor entityContentsViewController IDEDataModelEntityContentsEditor fetchRequestViewController IDEDataModelFetchRequestEditor hierarchySegmentControl NSSegmentedControl tabView NSTabView IBProjectSource ./Classes/IDEDataModelEditor.h IDEDataModelEntityContentsEditor IDEDMEditorController IDEDataModelBrowserEditor IDEDataModelDiagramEditor IDEDataModelEditor NSTabView browserViewController IDEDataModelBrowserEditor diagramViewController IDEDataModelDiagramEditor parentEditor IDEDataModelEditor tabView NSTabView IBProjectSource ./Classes/IDEDataModelEntityContentsEditor.h IDEDataModelFetchRequestEditor IDEDMEditorController NSArrayController IDEDataModelEditor IDECapsuleListView entityController NSArrayController parentEditor IDEDataModelEditor tableView IDECapsuleListView IBProjectSource ./Classes/IDEDataModelFetchRequestEditor.h IDEDataModelPropertiesTableController IDEDMEditorController IDEDMArrayController NSTableColumn NSArrayController IDEDataModelBrowserEditor IDEDMHighlightImageAndTextCell XDTableView arrayController IDEDMArrayController entitiesColumn NSTableColumn entityArrayController NSArrayController parentEditor IDEDataModelBrowserEditor propertyNameAndImageCell IDEDMHighlightImageAndTextCell tableView XDTableView IBProjectSource ./Classes/IDEDataModelPropertiesTableController.h IDEDocDownloadsTableViewController NSObject NSButtonCell DVTTableView IDEDocViewingPrefPaneController _downloadButtonCell NSButtonCell _tableView DVTTableView prefPaneController IDEDocViewingPrefPaneController IBProjectSource ./Classes/IDEDocDownloadsTableViewController.h IDEDocSetOutlineView NSOutlineView IBProjectSource ./Classes/IDEDocSetOutlineView.h IDEDocSetOutlineViewController NSObject id id id id id getDocSetAction: id showProblemInfoForUpdate: id subscribeToPublisherAction: id unsubscribeFromPublisher: id updateDocSetAction: id docSetOutlineView IDEDocSetOutlineView docSetOutlineView docSetOutlineView IDEDocSetOutlineView IBProjectSource ./Classes/IDEDocSetOutlineViewController.h IDEDocViewingPrefPaneController IDEViewController id id id id id id id id id id id addSubscription: id checkForAndInstallUpdatesNow: id deleteDocSet: id downloadAction: id minimumFontSizeComboBoxAction: id minimumFontSizeEnabledAction: id showHelp: id showSubscriptionSheet: id subscriptionCancelAction: id toggleAutoCheckForAndInstallUpdates: id toggleDocSetInfo: id DVTGradientImageButton DVTGradientImageButton DVTGradientImageButton NSSplitView NSView NSView DVTBorderedView DVTBorderedView NSButton NSTextView IDEDocSetOutlineViewController IDEDocDownloadsTableViewController NSComboBox NSTextField NSButton NSTextField NSWindow NSButton _addButton DVTGradientImageButton _deleteButton DVTGradientImageButton _showInfoAreaButton DVTGradientImageButton _splitView NSSplitView _splitViewDocSetInfoSubview NSView _splitViewDocSetsListSubview NSView borderedViewAroundSplitView DVTBorderedView borderedViewBelowTable DVTBorderedView checkAndInstallNowButton NSButton docSetInfoTextView NSTextView docSetOutlineViewController IDEDocSetOutlineViewController downloadsTableViewController IDEDocDownloadsTableViewController minimumFontSizeControl NSComboBox noUpdatesAvailableMessage NSTextField showInfoButton NSButton subscriptionTextField NSTextField subscriptionWindow NSWindow validateAddSubscriptionButton NSButton IBProjectSource ./Classes/IDEDocViewingPrefPaneController.h IDEEditor IDEViewController IBProjectSource ./Classes/IDEEditor.h IDEViewController DVTViewController IBProjectSource ./Classes/IDEViewController.h IKImageView id id id id copy: id crop: id cut: id paste: id IBProjectSource ./Classes/IKImageView.h NSDocument id id id id id id printDocument: id revertDocumentToSaved: id runPageLayout: id saveDocument: id saveDocumentAs: id saveDocumentTo: id IBProjectSource ./Classes/NSDocument.h NSResponder _insertFindPattern: id _insertFindPattern: _insertFindPattern: id IBProjectSource ./Classes/NSResponder.h QLPreviewBubble NSObject id id hide: id show: id parentWindow NSWindow parentWindow parentWindow NSWindow IBProjectSource ./Classes/QLPreviewBubble.h QTMovieView id id id id id showAll: id showCustomButton: id toggleLoops: id zoomIn: id zoomOut: id IBProjectSource ./Classes/QTMovieView.h WebView id id id id reloadFromOrigin: id resetPageZoom: id zoomPageIn: id zoomPageOut: id IBProjectSource ./Classes/WebView.h XDDiagramView NSView id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id id _graphLayouterMenuItemAction: id _zoomPopUpButtonAction: id alignBottomEdges: id alignCentersHorizontallyInContainer: id alignCentersVerticallyInContainer: id alignHorizontalCenters: id alignLeftEdges: id alignRightEdges: id alignTopEdges: id alignVerticalCenters: id bringToFront: id collapseAllCompartments: id copy: id cut: id delete: id deleteBackward: id deleteForward: id deselectAll: id diagramZoomIn: id diagramZoomOut: id expandAllCompartments: id flipHorizontally: id flipVertically: id layoutGraphicsConcentrically: id layoutGraphicsHierarchically: id lock: id makeSameHeight: id makeSameWidth: id moveDown: id moveDownAndModifySelection: id moveLeft: id moveLeftAndModifySelection: id moveRight: id moveRightAndModifySelection: id moveUp: id moveUpAndModifySelection: id paste: id rollDownAllCompartments: id rollUpAllCompartments: id selectAll: id sendToBack: id sizeToFit: id toggleGridShown: id toggleHiddenGraphicsShown: id togglePageBreaksShown: id toggleRuler: id toggleSnapsToGrid: id unlock: id _diagramController IDEDataModelDiagramEditor _diagramController _diagramController IDEDataModelDiagramEditor IBProjectSource ./Classes/XDDiagramView.h XDTableView NSTableView showAllTableColumns: id showAllTableColumns: showAllTableColumns: id IBProjectSource ./Classes/XDTableView.h AppDelegate NSObject id id applicationShouldTerminate: id applicationWillFinishLaunching: id IBProjectSource ./Classes/AppDelegate.h 0 IBCocoaFramework YES 3 {11, 11} {10, 3} YES qbs-src-1.4.5/examples/cocoa-application/CocoaApplication/main.m000066400000000000000000000031621266132464200246200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import int main(int argc, char *argv[]) { return NSApplicationMain(argc, (const char **)argv); } qbs-src-1.4.5/examples/cocoa-touch-application/000077500000000000000000000000001266132464200214245ustar00rootroot00000000000000qbs-src-1.4.5/examples/cocoa-touch-application/CocoaTouchApplication.qbs000066400000000000000000000061631266132464200263540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ import qbs 1.0 CppApplication { Depends { condition: product.condition; name: "ib" } condition: qbs.targetOS.contains("ios") name: "Cocoa Touch Application" cpp.precompiledHeader: "CocoaTouchApplication/CocoaTouchApplication-Prefix.pch" bundle.infoPlistFile: "CocoaTouchApplication/CocoaTouchApplication-Info.plist" cpp.frameworks: [ "UIKit", "Foundation", "CoreGraphics" ] Group { prefix: "CocoaTouchApplication/" files: [ "AppDelegate.h", "AppDelegate.m", "CocoaTouchApplication-Prefix.pch", "Default-568h@2x.png", "Default.png", "Default@2x.png", "DetailViewController.h", "DetailViewController.m", "MasterViewController.h", "MasterViewController.m", "main.m" ] } Group { name: "Supporting Files" prefix: "CocoaTouchApplication/en.lproj/" files: [ "DetailViewController_iPad.xib", "DetailViewController_iPhone.xib", "InfoPlist.strings", "MasterViewController_iPad.xib", "MasterViewController_iPhone.xib" ] } } qbs-src-1.4.5/examples/cocoa-touch-application/CocoaTouchApplication.xcodeproj/000077500000000000000000000000001266132464200276335ustar00rootroot00000000000000qbs-src-1.4.5/examples/cocoa-touch-application/CocoaTouchApplication.xcodeproj/project.pbxproj000066400000000000000000000460041266132464200327130ustar00rootroot00000000000000// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 14E3FEAA175FB2E800C857C6 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 14E3FEA9175FB2E800C857C6 /* UIKit.framework */; }; 14E3FEAC175FB2E800C857C6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 14E3FEAB175FB2E800C857C6 /* Foundation.framework */; }; 14E3FEAE175FB2E800C857C6 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 14E3FEAD175FB2E800C857C6 /* CoreGraphics.framework */; }; 14E3FEB4175FB2E800C857C6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FEB2175FB2E800C857C6 /* InfoPlist.strings */; }; 14E3FEB6175FB2E800C857C6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 14E3FEB5175FB2E800C857C6 /* main.m */; }; 14E3FEBA175FB2E800C857C6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 14E3FEB9175FB2E800C857C6 /* AppDelegate.m */; }; 14E3FEBC175FB2E800C857C6 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FEBB175FB2E800C857C6 /* Default.png */; }; 14E3FEBE175FB2E800C857C6 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FEBD175FB2E800C857C6 /* Default@2x.png */; }; 14E3FEC0175FB2E800C857C6 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FEBF175FB2E800C857C6 /* Default-568h@2x.png */; }; 14E3FEC3175FB2E800C857C6 /* MasterViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 14E3FEC2175FB2E800C857C6 /* MasterViewController.m */; }; 14E3FEC6175FB2E900C857C6 /* DetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 14E3FEC5175FB2E900C857C6 /* DetailViewController.m */; }; 14E3FEC9175FB2E900C857C6 /* MasterViewController_iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FEC7175FB2E900C857C6 /* MasterViewController_iPhone.xib */; }; 14E3FECC175FB2E900C857C6 /* MasterViewController_iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FECA175FB2E900C857C6 /* MasterViewController_iPad.xib */; }; 14E3FECF175FB2E900C857C6 /* DetailViewController_iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FECD175FB2E900C857C6 /* DetailViewController_iPhone.xib */; }; 14E3FED2175FB2E900C857C6 /* DetailViewController_iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 14E3FED0175FB2E900C857C6 /* DetailViewController_iPad.xib */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 14E3FEA6175FB2E800C857C6 /* Cocoa Touch Application.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Cocoa Touch Application.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 14E3FEA9175FB2E800C857C6 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 14E3FEAB175FB2E800C857C6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 14E3FEAD175FB2E800C857C6 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 14E3FEB1175FB2E800C857C6 /* CocoaTouchApplication-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "CocoaTouchApplication-Info.plist"; sourceTree = ""; }; 14E3FEB3175FB2E800C857C6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 14E3FEB5175FB2E800C857C6 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 14E3FEB7175FB2E800C857C6 /* CocoaTouchApplication-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CocoaTouchApplication-Prefix.pch"; sourceTree = ""; }; 14E3FEB8175FB2E800C857C6 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 14E3FEB9175FB2E800C857C6 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 14E3FEBB175FB2E800C857C6 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 14E3FEBD175FB2E800C857C6 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 14E3FEBF175FB2E800C857C6 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 14E3FEC1175FB2E800C857C6 /* MasterViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MasterViewController.h; sourceTree = ""; }; 14E3FEC2175FB2E800C857C6 /* MasterViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MasterViewController.m; sourceTree = ""; }; 14E3FEC4175FB2E800C857C6 /* DetailViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DetailViewController.h; sourceTree = ""; }; 14E3FEC5175FB2E900C857C6 /* DetailViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DetailViewController.m; sourceTree = ""; }; 14E3FEC8175FB2E900C857C6 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MasterViewController_iPhone.xib; sourceTree = ""; }; 14E3FECB175FB2E900C857C6 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MasterViewController_iPad.xib; sourceTree = ""; }; 14E3FECE175FB2E900C857C6 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/DetailViewController_iPhone.xib; sourceTree = ""; }; 14E3FED1175FB2E900C857C6 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/DetailViewController_iPad.xib; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 14E3FEA3175FB2E800C857C6 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 14E3FEAA175FB2E800C857C6 /* UIKit.framework in Frameworks */, 14E3FEAC175FB2E800C857C6 /* Foundation.framework in Frameworks */, 14E3FEAE175FB2E800C857C6 /* CoreGraphics.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 14E3FE9D175FB2E800C857C6 = { isa = PBXGroup; children = ( 14E3FEAF175FB2E800C857C6 /* CocoaTouchApplication */, 14E3FEA8175FB2E800C857C6 /* Frameworks */, 14E3FEA7175FB2E800C857C6 /* Products */, ); sourceTree = ""; }; 14E3FEA7175FB2E800C857C6 /* Products */ = { isa = PBXGroup; children = ( 14E3FEA6175FB2E800C857C6 /* Cocoa Touch Application.app */, ); name = Products; sourceTree = ""; }; 14E3FEA8175FB2E800C857C6 /* Frameworks */ = { isa = PBXGroup; children = ( 14E3FEA9175FB2E800C857C6 /* UIKit.framework */, 14E3FEAB175FB2E800C857C6 /* Foundation.framework */, 14E3FEAD175FB2E800C857C6 /* CoreGraphics.framework */, ); name = Frameworks; sourceTree = ""; }; 14E3FEAF175FB2E800C857C6 /* CocoaTouchApplication */ = { isa = PBXGroup; children = ( 14E3FEB8175FB2E800C857C6 /* AppDelegate.h */, 14E3FEB9175FB2E800C857C6 /* AppDelegate.m */, 14E3FEC1175FB2E800C857C6 /* MasterViewController.h */, 14E3FEC2175FB2E800C857C6 /* MasterViewController.m */, 14E3FEC4175FB2E800C857C6 /* DetailViewController.h */, 14E3FEC5175FB2E900C857C6 /* DetailViewController.m */, 14E3FEC7175FB2E900C857C6 /* MasterViewController_iPhone.xib */, 14E3FECA175FB2E900C857C6 /* MasterViewController_iPad.xib */, 14E3FECD175FB2E900C857C6 /* DetailViewController_iPhone.xib */, 14E3FED0175FB2E900C857C6 /* DetailViewController_iPad.xib */, 14E3FEB0175FB2E800C857C6 /* Supporting Files */, ); path = CocoaTouchApplication; sourceTree = ""; }; 14E3FEB0175FB2E800C857C6 /* Supporting Files */ = { isa = PBXGroup; children = ( 14E3FEB1175FB2E800C857C6 /* CocoaTouchApplication-Info.plist */, 14E3FEB2175FB2E800C857C6 /* InfoPlist.strings */, 14E3FEB5175FB2E800C857C6 /* main.m */, 14E3FEB7175FB2E800C857C6 /* CocoaTouchApplication-Prefix.pch */, 14E3FEBB175FB2E800C857C6 /* Default.png */, 14E3FEBD175FB2E800C857C6 /* Default@2x.png */, 14E3FEBF175FB2E800C857C6 /* Default-568h@2x.png */, ); name = "Supporting Files"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 14E3FEA5175FB2E800C857C6 /* Cocoa Touch Application */ = { isa = PBXNativeTarget; buildConfigurationList = 14E3FED5175FB2E900C857C6 /* Build configuration list for PBXNativeTarget "Cocoa Touch Application" */; buildPhases = ( 14E3FEA2175FB2E800C857C6 /* Sources */, 14E3FEA3175FB2E800C857C6 /* Frameworks */, 14E3FEA4175FB2E800C857C6 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = "Cocoa Touch Application"; productName = CocoaTouchApplication; productReference = 14E3FEA6175FB2E800C857C6 /* Cocoa Touch Application.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 14E3FE9E175FB2E800C857C6 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0460; ORGANIZATIONNAME = "Petroules Corporation"; }; buildConfigurationList = 14E3FEA1175FB2E800C857C6 /* Build configuration list for PBXProject "CocoaTouchApplication" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 14E3FE9D175FB2E800C857C6; productRefGroup = 14E3FEA7175FB2E800C857C6 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 14E3FEA5175FB2E800C857C6 /* Cocoa Touch Application */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 14E3FEA4175FB2E800C857C6 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 14E3FEB4175FB2E800C857C6 /* InfoPlist.strings in Resources */, 14E3FEBC175FB2E800C857C6 /* Default.png in Resources */, 14E3FEBE175FB2E800C857C6 /* Default@2x.png in Resources */, 14E3FEC0175FB2E800C857C6 /* Default-568h@2x.png in Resources */, 14E3FEC9175FB2E900C857C6 /* MasterViewController_iPhone.xib in Resources */, 14E3FECC175FB2E900C857C6 /* MasterViewController_iPad.xib in Resources */, 14E3FECF175FB2E900C857C6 /* DetailViewController_iPhone.xib in Resources */, 14E3FED2175FB2E900C857C6 /* DetailViewController_iPad.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 14E3FEA2175FB2E800C857C6 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 14E3FEB6175FB2E800C857C6 /* main.m in Sources */, 14E3FEBA175FB2E800C857C6 /* AppDelegate.m in Sources */, 14E3FEC3175FB2E800C857C6 /* MasterViewController.m in Sources */, 14E3FEC6175FB2E900C857C6 /* DetailViewController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 14E3FEB2175FB2E800C857C6 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( 14E3FEB3175FB2E800C857C6 /* en */, ); name = InfoPlist.strings; sourceTree = ""; }; 14E3FEC7175FB2E900C857C6 /* MasterViewController_iPhone.xib */ = { isa = PBXVariantGroup; children = ( 14E3FEC8175FB2E900C857C6 /* en */, ); name = MasterViewController_iPhone.xib; sourceTree = ""; }; 14E3FECA175FB2E900C857C6 /* MasterViewController_iPad.xib */ = { isa = PBXVariantGroup; children = ( 14E3FECB175FB2E900C857C6 /* en */, ); name = MasterViewController_iPad.xib; sourceTree = ""; }; 14E3FECD175FB2E900C857C6 /* DetailViewController_iPhone.xib */ = { isa = PBXVariantGroup; children = ( 14E3FECE175FB2E900C857C6 /* en */, ); name = DetailViewController_iPhone.xib; sourceTree = ""; }; 14E3FED0175FB2E900C857C6 /* DetailViewController_iPad.xib */ = { isa = PBXVariantGroup; children = ( 14E3FED1175FB2E900C857C6 /* en */, ); name = DetailViewController_iPad.xib; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 14E3FED3175FB2E900C857C6 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 6.1; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 14E3FED4175FB2E900C857C6 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 6.1; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; 14E3FED6175FB2E900C857C6 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "CocoaTouchApplication/CocoaTouchApplication-Prefix.pch"; INFOPLIST_FILE = "CocoaTouchApplication/CocoaTouchApplication-Info.plist"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; name = Debug; }; 14E3FED7175FB2E900C857C6 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "CocoaTouchApplication/CocoaTouchApplication-Prefix.pch"; INFOPLIST_FILE = "CocoaTouchApplication/CocoaTouchApplication-Info.plist"; PRODUCT_NAME = "$(TARGET_NAME)"; WRAPPER_EXTENSION = app; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 14E3FEA1175FB2E800C857C6 /* Build configuration list for PBXProject "CocoaTouchApplication" */ = { isa = XCConfigurationList; buildConfigurations = ( 14E3FED3175FB2E900C857C6 /* Debug */, 14E3FED4175FB2E900C857C6 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 14E3FED5175FB2E900C857C6 /* Build configuration list for PBXNativeTarget "Cocoa Touch Application" */ = { isa = XCConfigurationList; buildConfigurations = ( 14E3FED6175FB2E900C857C6 /* Debug */, 14E3FED7175FB2E900C857C6 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 14E3FE9E175FB2E800C857C6 /* Project object */; } qbs-src-1.4.5/examples/cocoa-touch-application/CocoaTouchApplication/000077500000000000000000000000001266132464200256375ustar00rootroot00000000000000qbs-src-1.4.5/examples/cocoa-touch-application/CocoaTouchApplication/AppDelegate.h000066400000000000000000000036371266132464200301740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import @interface AppDelegate : UIResponder { UIWindow *_window; UINavigationController *_navigationController; UISplitViewController *_splitViewController; } @property (nonatomic, retain) UIWindow *window; @property (nonatomic, retain) UINavigationController *navigationController; @property (nonatomic, retain) UISplitViewController *splitViewController; @end qbs-src-1.4.5/examples/cocoa-touch-application/CocoaTouchApplication/AppDelegate.m000066400000000000000000000125401266132464200301720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import "AppDelegate.h" #import "MasterViewController.h" #import "DetailViewController.h" @implementation AppDelegate @synthesize window = _window; @synthesize navigationController = _navigationController; @synthesize splitViewController = _splitViewController; - (void)dealloc { [_window release]; [_navigationController release]; [_splitViewController release]; [super dealloc]; } - (BOOL)application:(UIApplication *) __unused application didFinishLaunchingWithOptions:(NSDictionary *) __unused launchOptions { self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; // Override point for customization after application launch. if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { MasterViewController *masterViewController = [[[MasterViewController alloc] initWithNibName:@"MasterViewController_iPhone" bundle:nil] autorelease]; self.navigationController = [[[UINavigationController alloc] initWithRootViewController:masterViewController] autorelease]; self.window.rootViewController = self.navigationController; } else { MasterViewController *masterViewController = [[[MasterViewController alloc] initWithNibName:@"MasterViewController_iPad" bundle:nil] autorelease]; UINavigationController *masterNavigationController = [[[UINavigationController alloc] initWithRootViewController:masterViewController] autorelease]; DetailViewController *detailViewController = [[[DetailViewController alloc] initWithNibName:@"DetailViewController_iPad" bundle:nil] autorelease]; UINavigationController *detailNavigationController = [[[UINavigationController alloc] initWithRootViewController:detailViewController] autorelease]; masterViewController.detailViewController = detailViewController; self.splitViewController = [[[UISplitViewController alloc] init] autorelease]; self.splitViewController.delegate = detailViewController; self.splitViewController.viewControllers = [NSArray arrayWithObjects:masterNavigationController, detailNavigationController, nil]; self.window.rootViewController = self.splitViewController; } [self.window makeKeyAndVisible]; return YES; } - (void)applicationWillResignActive:(UIApplication *) __unused application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - (void)applicationDidEnterBackground:(UIApplication *) __unused application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - (void)applicationWillEnterForeground:(UIApplication *) __unused application { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - (void)applicationDidBecomeActive:(UIApplication *) __unused application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - (void)applicationWillTerminate:(UIApplication *) __unused application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } @end CocoaTouchApplication-Info.plist000066400000000000000000000035071266132464200337460ustar00rootroot00000000000000qbs-src-1.4.5/examples/cocoa-touch-application/CocoaTouchApplication CFBundleDevelopmentRegion en CFBundleDisplayName ${PRODUCT_NAME} CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier com.petroules.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1.0 LSRequiresIPhoneOS UIRequiredDeviceCapabilities armv7 UIStatusBarTintParameters UINavigationBar Style UIBarStyleDefault Translucent UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight CocoaTouchApplication-Prefix.pch000066400000000000000000000033321266132464200337230ustar00rootroot00000000000000qbs-src-1.4.5/examples/cocoa-touch-application/CocoaTouchApplication/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import #ifndef __IPHONE_4_0 #warning "This project uses features only available in iOS SDK 4.0 and later." #endif #ifdef __OBJC__ #import #import #endif qbs-src-1.4.5/examples/cocoa-touch-application/CocoaTouchApplication/Default-568h@2x.png000066400000000000000000000442421266132464200310010ustar00rootroot00000000000000PNG  IHDRpz$iCCPICC Profile8UoT>oR? XGůUS[IJ*$:7鶪O{7@Hkk?<kktq݋m6nƶد-mR;`zv x#=\% oYRڱ#&?>ҹЪn_;j;$}*}+(}'}/LtY"$].9⦅%{_a݊]hk5'SN{<_ t jM{-4%TńtY۟R6#v\喊x:'HO3^&0::m,L%3:qVE t]~Iv6Wٯ) |ʸ2]G4(6w‹$"AEv m[D;Vh[}چN|3HS:KtxU'D;77;_"e?Yqxl+ pHYs  iTXtXML:com.adobe.xmp 1 5 72 1 72 640 1 1136 2012-07-27T15:07:06 Pixelmator 2.0.5 )q?7IDATx=eQqÙ87;;' RBR(JWw^8w<漏7 @^~:;;>9O @F{}w~|}}ޣ#@~<=9G p;*O_8>^#@ ƻZjLZ9:\oR? XGůUS[IJ*$:7鶪O{7@Hkk?<kktq݋m6nƶد-mR;`zv x#=\% oYRڱ#&?>ҹЪn_;j;$}*}+(}'}/LtY"$].9⦅%{_a݊]hk5'SN{<_ t jM{-4%TńtY۟R6#v\喊x:'HO3^&0::m,L%3:qVE t]~Iv6Wٯ) |ʸ2]G4(6w‹$"AEv m[D;Vh[}چN|3HS:KtxU'D;77;_"e?Yqxl+ pHYs  iTXtXML:com.adobe.xmp 1 5 72 1 72 320 1 480 2012-07-27T15:07:80 Pixelmator 2.0.5 X="IDATxICQDDKIq/L {nov}y>(oR? XGůUS[IJ*$:7鶪O{7@Hkk?<kktq݋m6nƶد-mR;`zv x#=\% oYRڱ#&?>ҹЪn_;j;$}*}+(}'}/LtY"$].9⦅%{_a݊]hk5'SN{<_ t jM{-4%TńtY۟R6#v\喊x:'HO3^&0::m,L%3:qVE t]~Iv6Wٯ) |ʸ2]G4(6w‹$"AEv m[D;Vh[}چN|3HS:KtxU'D;77;_"e?Yqxl+ pHYs  iTXtXML:com.adobe.xmp 1 5 72 1 72 640 1 960 2012-07-27T15:07:37 Pixelmator 2.0.5 PF5IDATx1e HH܎;qoV..Vb&a^p s3;i^;ޟy!@ <>_{x}~\_Wg @܆vW=̻o]yoλ͇ @vU>yO7ן}* p|W}w}5蛿CaW] @>FmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@0  0" GmM @@W>0  @nVjLJޞy @ܞxޝ<x| @7$pߧ:yOߜ' @~y7O/> @!p[_4lIENDB`qbs-src-1.4.5/examples/cocoa-touch-application/CocoaTouchApplication/DetailViewController.h000066400000000000000000000035251266132464200321160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import @interface DetailViewController : UIViewController { id _detailItem; UILabel *_detailDescriptionLabel; UIPopoverController *_masterPopoverController; } @property (nonatomic, retain) id detailItem; @property (nonatomic, retain) IBOutlet UILabel *detailDescriptionLabel; @end qbs-src-1.4.5/examples/cocoa-touch-application/CocoaTouchApplication/DetailViewController.m000066400000000000000000000100071266132464200321140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import "DetailViewController.h" @interface DetailViewController () @property (nonatomic, retain) UIPopoverController *masterPopoverController; - (void)configureView; @end @implementation DetailViewController @synthesize detailItem = _detailItem; @synthesize detailDescriptionLabel = _detailDescriptionLabel; @synthesize masterPopoverController = _masterPopoverController; - (void)dealloc { [_detailItem release]; [_detailDescriptionLabel release]; [_masterPopoverController release]; [super dealloc]; } #pragma mark - Managing the detail item - (void)setDetailItem:(id)newDetailItem { if (_detailItem != newDetailItem) { [_detailItem release]; _detailItem = [newDetailItem retain]; // Update the view. [self configureView]; } if (self.masterPopoverController != nil) { [self.masterPopoverController dismissPopoverAnimated:YES]; } } - (void)configureView { // Update the user interface for the detail item. if (self.detailItem) { self.detailDescriptionLabel.text = [self.detailItem description]; } } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self configureView]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.title = NSLocalizedString(@"Detail", @"Detail"); } return self; } #pragma mark - Split view - (void)splitViewController:(UISplitViewController *) __unused splitController willHideViewController:(UIViewController *) __unused viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController { barButtonItem.title = NSLocalizedString(@"Master", @"Master"); [self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES]; self.masterPopoverController = popoverController; } - (void)splitViewController:(UISplitViewController *) __unused splitController willShowViewController:(UIViewController *) __unused viewController invalidatingBarButtonItem:(UIBarButtonItem *) __unused barButtonItem { // Called when the view is shown again in the split view, invalidating the button and popover controller. [self.navigationItem setLeftBarButtonItem:nil animated:YES]; self.masterPopoverController = nil; } @end qbs-src-1.4.5/examples/cocoa-touch-application/CocoaTouchApplication/MasterViewController.h000066400000000000000000000034161266132464200321460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import @class DetailViewController; @interface MasterViewController : UITableViewController { NSMutableArray *_objects; DetailViewController *_detailViewController; } @property (nonatomic, retain) DetailViewController *detailViewController; @end qbs-src-1.4.5/examples/cocoa-touch-application/CocoaTouchApplication/MasterViewController.m000066400000000000000000000140071266132464200321510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import "MasterViewController.h" #import "DetailViewController.h" @implementation MasterViewController @synthesize detailViewController = _detailViewController; - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.title = NSLocalizedString(@"Master", @"Master"); if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { self.clearsSelectionOnViewWillAppear = NO; self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0); } } return self; } - (void)dealloc { [_detailViewController release]; [_objects release]; [super dealloc]; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. self.navigationItem.leftBarButtonItem = self.editButtonItem; UIBarButtonItem *addButton = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)] autorelease]; self.navigationItem.rightBarButtonItem = addButton; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)insertNewObject:(id) __unused sender { if (!_objects) { _objects = [[NSMutableArray alloc] init]; } [_objects insertObject:[NSDate date] atIndex:0]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; } #pragma mark - Table View - (NSInteger)numberOfSectionsInTableView:(UITableView *) __unused tableView { return 1; } - (NSInteger)tableView:(UITableView *) __unused tableView numberOfRowsInSection:(NSInteger) __unused section { return _objects.count; } // Customize the appearance of table view cells. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; } } NSDate *object = [_objects objectAtIndex:indexPath.row]; cell.textLabel.text = [object description]; return cell; } - (BOOL)tableView:(UITableView *) __unused tableView canEditRowAtIndexPath:(NSIndexPath *) __unused indexPath { // Return NO if you do not want the specified item to be editable. return YES; } - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { [_objects removeObjectAtIndex:indexPath.row]; [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; } else if (editingStyle == UITableViewCellEditingStyleInsert) { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view. } } /* // Override to support rearranging the table view. - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { } */ /* // Override to support conditional rearranging of the table view. - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { // Return NO if you do not want the item to be re-orderable. return YES; } */ - (void)tableView:(UITableView *) __unused tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSDate *object = [_objects objectAtIndex:indexPath.row]; if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { if (!self.detailViewController) { self.detailViewController = [[[DetailViewController alloc] initWithNibName:@"DetailViewController_iPhone" bundle:nil] autorelease]; } self.detailViewController.detailItem = object; [self.navigationController pushViewController:self.detailViewController animated:YES]; } else { self.detailViewController.detailItem = object; } } @end qbs-src-1.4.5/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj/000077500000000000000000000000001266132464200273665ustar00rootroot00000000000000DetailViewController_iPad.xib000066400000000000000000000317011266132464200350530ustar00rootroot00000000000000qbs-src-1.4.5/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj 1536 12A206j 2519 1172.1 613.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1856 IBNSLayoutConstraint IBProxyObject IBUILabel IBUIView com.apple.InterfaceBuilder.IBCocoaTouchPlugin PluginDependencyRecalculationVersion IBFilesOwner IBIPadFramework IBFirstResponder IBIPadFramework 274 298 {{20, 495}, {728, 18}} 3 MQA YES NO IBIPadFramework 1 10 Detail view content goes here 1 MCAwIDAAA 1 1 4 Helvetica 14 16 {{0, 20}, {768, 1004}} NO 2 IBIPadFramework view 12 0 -1 File's Owner -2 8 10 0 10 1 0.0 1000 5 22 2 6 0 6 1 20 1000 8 29 3 5 0 5 1 20 1000 8 29 3 81 94 97 98 DetailViewController com.apple.InterfaceBuilder.IBCocoaTouchPlugin UIResponder com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin 98 0 IBIPadFramework YES 3 YES 1856 DetailViewController_iPhone.xib000066400000000000000000000351701266132464200354240ustar00rootroot00000000000000qbs-src-1.4.5/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj 1536 12A269 2835 1187 624.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1919 IBNSLayoutConstraint IBProxyObject IBUILabel IBUIView com.apple.InterfaceBuilder.IBCocoaTouchPlugin PluginDependencyRecalculationVersion IBFilesOwner IBCocoaTouchFramework IBFirstResponder IBCocoaTouchFramework 274 298 {{20, 265}, {280, 18}} 3 MQA YES NO IBCocoaTouchFramework Detail view content goes here 1 MCAwIDAAA darkTextColor 1 10 1 1 4 Helvetica 14 16 {{0, 20}, {320, 548}} 3 MQA 2 IBUIScreenMetrics YES {320, 568} {568, 320} IBCocoaTouchFramework Retina 4 Full Screen 2 IBCocoaTouchFramework view 3 detailDescriptionLabel 6 0 1 10 0 10 1 0.0 1000 5 22 2 6 0 6 1 20 1000 8 29 3 5 0 5 1 20 1000 8 29 3 -1 File's Owner -2 4 7 9 11 DetailViewController com.apple.InterfaceBuilder.IBCocoaTouchPlugin UIResponder com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 0 IBCocoaTouchFramework YES 3 YES 1919 qbs-src-1.4.5/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj/InfoPlist.strings000066400000000000000000000000541266132464200327070ustar00rootroot00000000000000/* Localized versions of Info.plist keys */ MasterViewController_iPad.xib000066400000000000000000000206341266132464200351070ustar00rootroot00000000000000qbs-src-1.4.5/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj 1536 12A206j 2519 1172.1 613.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1856 IBProxyObject IBUITableView com.apple.InterfaceBuilder.IBCocoaTouchPlugin PluginDependencyRecalculationVersion IBFilesOwner IBIPadFramework IBFirstResponder IBIPadFramework 274 {{0, 20}, {320, 832}} 3 MQA YES 2 IBUISplitViewMasterSimulatedSizeMetrics YES {320, 852} {320, 768} IBIPadFramework Master IBUISplitViewController IBUISplitViewControllerContentSizeLocation IBUISplitViewControllerContentSizeLocationMaster IBIPadFramework YES 1 0 YES 44 22 22 view 3 dataSource 4 delegate 5 0 -1 File's Owner -2 2 MasterViewController com.apple.InterfaceBuilder.IBCocoaTouchPlugin UIResponder com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin 5 0 IBIPadFramework YES 3 YES 1856 MasterViewController_iPhone.xib000066400000000000000000000200351266132464200354470ustar00rootroot00000000000000qbs-src-1.4.5/examples/cocoa-touch-application/CocoaTouchApplication/en.lproj 1536 12A269 2835 1187 624.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin 1919 IBProxyObject IBUITableView com.apple.InterfaceBuilder.IBCocoaTouchPlugin PluginDependencyRecalculationVersion IBFilesOwner IBCocoaTouchFramework IBFirstResponder IBCocoaTouchFramework 274 {{0, 20}, {320, 548}} 3 MQA YES IBUIScreenMetrics YES {320, 568} {568, 320} IBCocoaTouchFramework Retina 4 Full Screen 2 IBCocoaTouchFramework YES 1 0 YES 44 22 22 view 3 dataSource 4 delegate 5 0 -1 File's Owner -2 2 MasterViewController com.apple.InterfaceBuilder.IBCocoaTouchPlugin UIResponder com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin 5 0 IBCocoaTouchFramework YES 3 YES 1919 qbs-src-1.4.5/examples/cocoa-touch-application/CocoaTouchApplication/main.m000066400000000000000000000034251266132464200267450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import #import "AppDelegate.h" int main(int argc, char *argv[]) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; int retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); [pool release]; return retVal; } qbs-src-1.4.5/examples/code-generator/000077500000000000000000000000001266132464200176155ustar00rootroot00000000000000qbs-src-1.4.5/examples/code-generator/code-generator.qbs000066400000000000000000000056251266132464200232320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ import qbs Project { // A code generator that outputs a "Hello World" C++ program. CppApplication { name: "hwgen" files: ["hwgen.cpp"] bundle.isBundle: false } // Generate and build a hello-world application. CppApplication { name: "hello-world" Depends { name: "hwgen" } Rule { inputs: ["qbs"] // needed to trigger this rule Artifact { filePath: "main.cpp" fileTags: ["cpp"] } prepare: { var hwgen; for (var i in product.dependencies) { var dep = product.dependencies[i]; if (dep.name != "hwgen") continue; hwgen = dep.buildDirectory + "/" + dep.targetName; } var cmd = new Command(hwgen, [output.filePath]); cmd.description = "generating C++ source"; return cmd; } } } } qbs-src-1.4.5/examples/code-generator/hwgen.cpp000066400000000000000000000005111266132464200214260ustar00rootroot00000000000000#include int main(int argc, char **argv) { if (argc < 2) return 1; FILE *f = fopen(argv[1], "w"); if (!f) return 2; fprintf(f, "#include \n\n" "int main()\n" "{\n printf(\"Hello World!\\n\");\n return 0;\n}\n"); fclose(f); return 0; } qbs-src-1.4.5/examples/collidingmice/000077500000000000000000000000001266132464200175215ustar00rootroot00000000000000qbs-src-1.4.5/examples/collidingmice/collidingmice.qbs000066400000000000000000000042271266132464200230370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ import qbs 1.0 Application { name : "CollidingMice" destinationDirectory: "bin" Depends { name: "Qt" submodules: ["widgets"] } files : [ "main.cpp", "mouse.cpp", "mouse.h", "mice.qrc" ] } qbs-src-1.4.5/examples/collidingmice/images/000077500000000000000000000000001266132464200207665ustar00rootroot00000000000000qbs-src-1.4.5/examples/collidingmice/images/cheese.jpg000066400000000000000000000057251266132464200227350ustar00rootroot00000000000000JFIFHHAdobed@      ^^   s!1AQa"q2B#R3b$r%C4Scs5D'6Tdt& EFVU(eufv7GWgw8HXhx)9IYiy*:JZjzm!1AQa"q2#BRbr3$4CS%cs5DT &6E'dtU7()󄔤euFVfvGWgw8HXhx9IYiy*:JZjz ?Ao<7k)nrM ȂAZF"7Pcv`Ht=F V1`kIQȑ„4ŎwɁlIb:N~e/'z?J Qy?=q-ҁj{d&apJJt"t0Uԇnی ;@ bJѨ| +|=ໞYbB!%O,̼ITk+[-:+ e)QN!|gN=NͶP7D'!#ai\ݽ;vJۘ#,G- J/9fqP!yEI9|HYh>R'KbIlQҞݜe>)Zr#1q_>y"L`Rv%SIEhۜRdaЩfA Z=5 1{|34jzNM<5 ZW5 k-9$.N}H%A]#JC)zzzt ԋK}N UfZ`~'<\'|+҆Z'`x(!ۓ56iBbR]"@jrO4*ܹ<@|rBe.e@?>:3s1 .ʵXlE!o& zU덡} 4ڸyrRO]OL<;գ8֣x]BG^׹*]ٶ5(VH_Dx6c6##͒T|@`\=B* TJT{cJwQl*kKxd$o`W=QxS/$q$liRnK}Qmb4r2$&1fh5;ɮ9 $2HҞ؀@t9=Թ'x4XTɵ*Ƈ4Rczn{L\&жqр"j)$PV%#y);P<*ޡPPīU(A^JSЂ(AanGaFgOߙ~.!$LTS#3$ً'jF4`5"ǻ0/8vB{\KQmj!jeEz岘csꖑCkk_101ʌz1Ro}[.i1!#lqJ]|J~'29-NxC0/2k^e- FQx{vP[թy죌˫?vx =t=A">$FAppU v׆Qr4 yku&l޵w*SrYQQZFₔڞ,2<7q'm\E|OCILɩҊⴂ7ğCoo7w=U9ӏMOy9/a>^ܐeL+$B|wGߕ~+;;H~‰G-}[{'P)d}麻Sʴ㙜%DF5o*w b I>id!eiqbs-src-1.4.5/examples/collidingmice/main.cpp000066400000000000000000000055271266132464200211620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mouse.h" #include #include #include #include #include #include static const int MouseCount = 7; //! [0] int main(int argc, char **argv) { QApplication app(argc, argv); qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); //! [0] //! [1] QGraphicsScene scene; scene.setSceneRect(-300, -300, 600, 600); //! [1] //! [2] scene.setItemIndexMethod(QGraphicsScene::NoIndex); //! [2] //! [3] for (int i = 0; i < MouseCount; ++i) { Mouse *mouse = new Mouse; mouse->setPos(::sin((i * 6.28) / MouseCount) * 200, ::cos((i * 6.28) / MouseCount) * 200); scene.addItem(mouse); } //! [3] //! [4] QGraphicsView view(&scene); view.setRenderHint(QPainter::Antialiasing); view.setBackgroundBrush(QPixmap(":/images/cheese.jpg")); //! [4] //! [5] view.setCacheMode(QGraphicsView::CacheBackground); view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); view.setDragMode(QGraphicsView::ScrollHandDrag); //! [5] //! [6] view.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Colliding Mice")); view.resize(400, 300); view.show(); QTimer timer; QObject::connect(&timer, SIGNAL(timeout()), &scene, SLOT(advance())); timer.start(1000 / 33); return app.exec(); } //! [6] qbs-src-1.4.5/examples/collidingmice/mice.qrc000066400000000000000000000001411266132464200211410ustar00rootroot00000000000000 images/cheese.jpg qbs-src-1.4.5/examples/collidingmice/mouse.cpp000066400000000000000000000133151266132464200213600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mouse.h" #include #include #include #include static const double Pi = 3.14159265358979323846264338327950288419717; static double TwoPi = 2.0 * Pi; static qreal normalizeAngle(qreal angle) { while (angle < 0) angle += TwoPi; while (angle > TwoPi) angle -= TwoPi; return angle; } //! [0] Mouse::Mouse() : angle(0), speed(0), mouseEyeDirection(0), color(qrand() % 256, qrand() % 256, qrand() % 256) { setRotation(qrand() % (360 * 16)); } //! [0] //! [1] QRectF Mouse::boundingRect() const { qreal adjust = 0.5; return QRectF(-18 - adjust, -22 - adjust, 36 + adjust, 60 + adjust); } //! [1] //! [2] QPainterPath Mouse::shape() const { QPainterPath path; path.addRect(-10, -20, 20, 40); return path; } //! [2] //! [3] void Mouse::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { // Body painter->setBrush(color); painter->drawEllipse(-10, -20, 20, 40); // Eyes painter->setBrush(Qt::white); painter->drawEllipse(-10, -17, 8, 8); painter->drawEllipse(2, -17, 8, 8); // Nose painter->setBrush(Qt::black); painter->drawEllipse(QRectF(-2, -22, 4, 4)); // Pupils painter->drawEllipse(QRectF(-8.0 + mouseEyeDirection, -17, 4, 4)); painter->drawEllipse(QRectF(4.0 + mouseEyeDirection, -17, 4, 4)); // Ears painter->setBrush(scene()->collidingItems(this).isEmpty() ? Qt::darkYellow : Qt::red); painter->drawEllipse(-17, -12, 16, 16); painter->drawEllipse(1, -12, 16, 16); // Tail QPainterPath path(QPointF(0, 20)); path.cubicTo(-5, 22, -5, 22, 0, 25); path.cubicTo(5, 27, 5, 32, 0, 30); path.cubicTo(-5, 32, -5, 42, 0, 35); painter->setBrush(Qt::NoBrush); painter->drawPath(path); } //! [3] //! [4] void Mouse::advance(int step) { if (!step) return; //! [4] // Don't move too far away //! [5] QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0)); if (lineToCenter.length() > 150) { qreal angleToCenter = ::acos(lineToCenter.dx() / lineToCenter.length()); if (lineToCenter.dy() < 0) angleToCenter = TwoPi - angleToCenter; angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2); if (angleToCenter < Pi && angleToCenter > Pi / 4) { // Rotate left angle += (angle < -Pi / 2) ? 0.25 : -0.25; } else if (angleToCenter >= Pi && angleToCenter < (Pi + Pi / 2 + Pi / 4)) { // Rotate right angle += (angle < Pi / 2) ? 0.25 : -0.25; } } else if (::sin(angle) < 0) { angle += 0.25; } else if (::sin(angle) > 0) { angle -= 0.25; //! [5] //! [6] } //! [6] // Try not to crash with any other mice //! [7] QList dangerMice = scene()->items(QPolygonF() << mapToScene(0, 0) << mapToScene(-30, -50) << mapToScene(30, -50)); foreach (QGraphicsItem *item, dangerMice) { if (item == this) continue; QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0)); qreal angleToMouse = ::acos(lineToMouse.dx() / lineToMouse.length()); if (lineToMouse.dy() < 0) angleToMouse = TwoPi - angleToMouse; angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2); if (angleToMouse >= 0 && angleToMouse < Pi / 2) { // Rotate right angle += 0.5; } else if (angleToMouse <= TwoPi && angleToMouse > (TwoPi - Pi / 2)) { // Rotate left angle -= 0.5; //! [7] //! [8] } //! [8] //! [9] } //! [9] // Add some random movement //! [10] if (dangerMice.size() > 1 && (qrand() % 10) == 0) { if (qrand() % 1) angle += (qrand() % 100) / 500.0; else angle -= (qrand() % 100) / 500.0; } //! [10] //! [11] speed += (-50 + qrand() % 100) / 100.0; qreal dx = ::sin(angle) * 10; mouseEyeDirection = (qAbs(dx / 5) < 1) ? 0 : dx / 5; setRotation(rotation() + dx); setPos(mapToParent(0, -(3 + sin(speed) * 3))); } //! [11] qbs-src-1.4.5/examples/collidingmice/mouse.h000066400000000000000000000036701266132464200210300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MOUSE_H #define MOUSE_H #include //! [0] class Mouse : public QGraphicsItem { public: Mouse(); QRectF boundingRect() const; QPainterPath shape() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); protected: void advance(int step); private: qreal angle; qreal speed; qreal mouseEyeDirection; QColor color; }; //! [0] #endif qbs-src-1.4.5/examples/examples.qbs000066400000000000000000000044201266132464200172440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ import qbs Project { references: [ "app-and-lib/app_and_lib.qbs", "cocoa-application/CocoaApplication.qbs", "code-generator/code-generator.qbs", "collidingmice/collidingmice.qbs", "helloworld-complex/hello.qbs", "helloworld-minimal/hello.qbs", "helloworld-qt/hello.qbs", "install-bundle/install-bundle.qbs", ] } qbs-src-1.4.5/examples/helloworld-complex/000077500000000000000000000000001266132464200205375ustar00rootroot00000000000000qbs-src-1.4.5/examples/helloworld-complex/hello.qbs000066400000000000000000000054311266132464200223540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ import qbs 1.0 Project { property bool hasSpecialFeature: true Application { name: 'HelloWorld-Complex' Depends { name: 'cpp' } cpp.defines: ['SOMETHING'] files: [ "src/foo.h", "src/foo.cpp" ] Group { condition: project.hasSpecialFeature prefix: "src/" files: ["specialfeature.cpp", "specialfeature.h"] } Group { cpp.defines: { var defines = outer.concat([ 'HAVE_MAIN_CPP', cpp.debugInformation ? '_DEBUG' : '_RELEASE' ]); if (project.hasSpecialFeature) defines.push("HAS_SPECIAL_FEATURE"); return defines; } prefix: "src/" files: [ 'main.cpp' ] } } } qbs-src-1.4.5/examples/helloworld-complex/src/000077500000000000000000000000001266132464200213265ustar00rootroot00000000000000qbs-src-1.4.5/examples/helloworld-complex/src/foo.cpp000066400000000000000000000037721266132464200226260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ #ifndef SOMETHING # error missing define SOMETHING #endif int someUsefulFunction() { return 156; } qbs-src-1.4.5/examples/helloworld-complex/src/foo.h000066400000000000000000000001001266132464200222510ustar00rootroot00000000000000#ifndef FOO_H #define FOO_H int someUsefulFunction(); #endif qbs-src-1.4.5/examples/helloworld-complex/src/main.cpp000066400000000000000000000045221266132464200227610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ #include "foo.h" #ifdef HAS_SPECIAL_FEATURE #include "specialfeature.h" #endif #include #ifndef HAVE_MAIN_CPP # error missing define HAVE_MAIN_CPP #endif #ifndef SOMETHING # error missing define SOMETHING #endif int main() { someUsefulFunction(); #ifdef _DEBUG puts("Hello World! (debug version)"); #else puts("Hello World! (release version)"); #endif #ifdef HAS_SPECIAL_FEATURE bragAboutSpecialFeature(); #endif } qbs-src-1.4.5/examples/helloworld-complex/src/specialfeature.cpp000066400000000000000000000040371266132464200250320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ #include "specialfeature.h" #include void bragAboutSpecialFeature() { std::cout << "I have a special feature!" << std::endl; } qbs-src-1.4.5/examples/helloworld-complex/src/specialfeature.h000066400000000000000000000001451266132464200244730ustar00rootroot00000000000000#ifndef HELLO_SPECIAL_FEATURE #define HELLO_SPECIAL_FEATURE void bragAboutSpecialFeature(); #endif qbs-src-1.4.5/examples/helloworld-minimal/000077500000000000000000000000001266132464200205165ustar00rootroot00000000000000qbs-src-1.4.5/examples/helloworld-minimal/hello.qbs000066400000000000000000000037431266132464200223370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ import qbs CppApplication { name: "HelloWorld-minimal" files: "main.cpp" } qbs-src-1.4.5/examples/helloworld-minimal/main.cpp000066400000000000000000000037421266132464200221540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ #include int main() { std::cout << "Hello, World!" << std::endl; } qbs-src-1.4.5/examples/helloworld-qt/000077500000000000000000000000001266132464200175145ustar00rootroot00000000000000qbs-src-1.4.5/examples/helloworld-qt/hello.qbs000066400000000000000000000037351266132464200213360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ import qbs QtApplication { name: "HelloWorld-Qt" files: "main.cpp" } qbs-src-1.4.5/examples/helloworld-qt/main.cpp000066400000000000000000000040771266132464200211540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ #include #include #include int main() { QTextStream(stdout) << QCoreApplication::translate("hello", "Hello, World!") << endl; } qbs-src-1.4.5/examples/install-bundle/000077500000000000000000000000001266132464200176345ustar00rootroot00000000000000qbs-src-1.4.5/examples/install-bundle/coreutils.cpp000066400000000000000000000000651266132464200223520ustar00rootroot00000000000000#include "coreutils.h" int foo() { return 42; } qbs-src-1.4.5/examples/install-bundle/coreutils.h000066400000000000000000000000661266132464200220200ustar00rootroot00000000000000#ifdef _WIN32 __declspec(dllexport) #endif int foo(); qbs-src-1.4.5/examples/install-bundle/install-bundle.qbs000066400000000000000000000037501266132464200232650ustar00rootroot00000000000000import qbs import qbs.FileInfo Project { CppApplication { Depends { name: "coreutils" } Depends { name: "Qt"; submodules: ["core", "gui", "widgets"] } name: "window" targetName: bundle.isBundle ? "Window" : "window" files: ["main.cpp"] property bool install: true property string installDir: bundle.isBundle ? "Applications" : (qbs.targetOS.contains("windows") ? "" : "bin") Group { fileTagsFilter: ["application"] qbs.install: install qbs.installDir: bundle.isBundle ? FileInfo.joinPaths(installDir, FileInfo.path(bundle.executablePath)) : installDir } Group { fileTagsFilter: ["infoplist"] qbs.install: install && bundle.isBundle && !bundle.embedInfoPlist qbs.installDir: FileInfo.joinPaths(installDir, FileInfo.path(bundle.infoPlistPath)) } Group { fileTagsFilter: ["pkginfo"] qbs.install: install && bundle.isBundle qbs.installDir: FileInfo.joinPaths(installDir, FileInfo.path(bundle.pkgInfoPath)) } } DynamicLibrary { Depends { name: "cpp" } name: "coreutils" targetName: bundle.isBundle ? "CoreUtils" : "coreutils" files: ["coreutils.cpp", "coreutils.h"] property bool install: true property string installDir: bundle.isBundle ? "Library/Frameworks" : (qbs.targetOS.contains("windows") ? "" : "lib") Group { fileTagsFilter: ["dynamiclibrary", "dynamiclibrary_symlink", "dynamiclibrary_import"] qbs.install: install qbs.installDir: bundle.isBundle ? FileInfo.joinPaths(installDir, FileInfo.path(bundle.executablePath)) : installDir } Group { fileTagsFilter: ["infoplist"] qbs.install: install && bundle.isBundle && !bundle.embedInfoPlist qbs.installDir: FileInfo.joinPaths(installDir, FileInfo.path(bundle.infoPlistPath)) } } } qbs-src-1.4.5/examples/install-bundle/main.cpp000066400000000000000000000002611266132464200212630ustar00rootroot00000000000000#include #include int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget window; window.show(); return app.exec(); } qbs-src-1.4.5/qbs-resources/000077500000000000000000000000001266132464200156765ustar00rootroot00000000000000qbs-src-1.4.5/qbs-resources/imports/000077500000000000000000000000001266132464200173735ustar00rootroot00000000000000qbs-src-1.4.5/qbs-resources/imports/QbsApp.qbs000066400000000000000000000012001266132464200212610ustar00rootroot00000000000000import qbs QbsProduct { Depends { name: "qbscore" } Depends { name: "cpp" } type: "application" consoleApplication: true destinationDirectory: "bin" cpp.includePaths: [ "../shared", // for the logger ] cpp.cxxLanguageVersion: "c++11" Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: project.appInstallDir } Group { name: "logging" prefix: "../shared/logging/" files: [ "coloredoutput.cpp", "coloredoutput.h", "consolelogger.cpp", "consolelogger.h" ] } } qbs-src-1.4.5/qbs-resources/imports/QbsAutotest.qbs000066400000000000000000000010721266132464200223600ustar00rootroot00000000000000import qbs QtApplication { type: ["application", "autotest"] consoleApplication: true property string testName name: "tst_" + testName Depends { name: "Qt.test" } Depends { name: "qbscore" } cpp.includePaths: "../../../src" cpp.cxxLanguageVersion: "c++11" destinationDirectory: "bin" Group { name: "logging" prefix: "../../../src/app/shared/logging/" files: [ "coloredoutput.cpp", "coloredoutput.h", "consolelogger.cpp", "consolelogger.h" ] } } qbs-src-1.4.5/qbs-resources/imports/QbsFunctions/000077500000000000000000000000001266132464200220115ustar00rootroot00000000000000qbs-src-1.4.5/qbs-resources/imports/QbsFunctions/functions.js000066400000000000000000000012271266132464200243610ustar00rootroot00000000000000function qbsVersion() { return "1.4.5"; } function versionIsAtLeast(actualVersion, expectedVersion) { var actualVersionParts = actualVersion.split('.').map(function(item) { return parseInt(item, 10); }); var expectedVersionParts = expectedVersion.split('.').map(function(item) { return parseInt(item, 10); }); for (var i = 0; i < expectedVersionParts.length; ++i) { if (actualVersionParts[i] > expectedVersionParts[i]) return true; if (actualVersionParts[i] < expectedVersionParts[i]) return false; } return i === expectedVersionParts.length || expectedVersionParts[i] === 0; } qbs-src-1.4.5/qbs-resources/imports/QbsLibrary.qbs000066400000000000000000000021241266132464200221530ustar00rootroot00000000000000import qbs import QbsFunctions QbsProduct { Depends { name: "cpp" } Depends { name: "bundle" } version: QbsFunctions.qbsVersion() type: Qt.core.staticBuild ? "staticlibrary" : "dynamiclibrary" targetName: (qbs.enableDebugCode && qbs.targetOS.contains("windows")) ? (name + 'd') : name destinationDirectory: qbs.targetOS.contains("windows") ? "bin" : project.libDirName cpp.defines: base.concat(type == "staticlibrary" ? ["QBS_STATIC_LIB"] : ["QBS_LIBRARY"]) cpp.installNamePrefix: "@rpath" cpp.visibility: "minimal" cpp.cxxLanguageVersion: "c++11" bundle.isBundle: false property string headerInstallPrefix: "/include/qbs" Group { fileTagsFilter: product.type.concat("dynamiclibrary_symlink") qbs.install: true qbs.installDir: project.libInstallDir } Export { Depends { name: "cpp" } Depends { name: "Qt"; submodules: ["core"] } cpp.rpaths: project.libRPaths cpp.includePaths: [product.sourceDirectory] cpp.defines: product.type === "staticlibrary" ? ["QBS_STATIC_LIB"] : [] } } qbs-src-1.4.5/qbs-resources/imports/QbsProduct.qbs000066400000000000000000000004361266132464200221730ustar00rootroot00000000000000import qbs import QbsFunctions Product { Depends { name: "Qt.core" } property string minimumQtVersion: "5.1.0" cpp.defines: ["QT_NO_CAST_FROM_ASCII", "QT_NO_PROCESS_COMBINED_ARGUMENT_START"] condition: QbsFunctions.versionIsAtLeast(Qt.core.version, minimumQtVersion) } qbs-src-1.4.5/qbs.pro000066400000000000000000000025271266132464200144160ustar00rootroot00000000000000defineTest(minQtVersion) { maj = $$1 min = $$2 patch = $$3 isEqual(QT_MAJOR_VERSION, $$maj) { isEqual(QT_MINOR_VERSION, $$min) { isEqual(QT_PATCH_VERSION, $$patch) { return(true) } greaterThan(QT_PATCH_VERSION, $$patch) { return(true) } } greaterThan(QT_MINOR_VERSION, $$min) { return(true) } } greaterThan(QT_MAJOR_VERSION, $$maj) { return(true) } return(false) } !minQtVersion(5, 1, 0) { message("Cannot build qbs with Qt version $${QT_VERSION}.") error("Use at least Qt 5.1.0.") } TEMPLATE = subdirs corelib.file = src/lib/corelib/corelib.pro setupqtprofilelib.subdir = src/lib/qtprofilesetup setupqtprofilelib.depends = corelib src_app.subdir = src/app src_app.depends = setupqtprofilelib src_libexec.subdir = src/libexec src_plugins.subdir = src/plugins tests.depends = corelib src_plugins SUBDIRS += \ corelib\ setupqtprofilelib\ src_app\ src_libexec\ src_plugins\ static.pro\ tests OTHER_FILES += \ doc/*.qdoc \ doc/reference/*.qdoc \ doc/reference/items/*.qdoc \ doc/reference/jsextensions/*.qdoc \ doc/reference/modules/*.qdoc \ doc/qbs.qdocconf \ doc/config/qbs-project.qdocconf include(qbs_version.pri) include(doc/doc.pri) qbs-src-1.4.5/qbs.qbs000066400000000000000000000042101266132464200143720ustar00rootroot00000000000000import qbs 1.0 Project { minimumQbsVersion: "1.4" qbsSearchPaths: ["qbs-resources"] property bool enableUnitTests: false property bool enableProjectFileUpdates: false property bool enableRPath: true property bool installApiHeaders: true property bool withExamples: false property string libDirName: "lib" property string appInstallDir: "bin" property string libInstallDir: qbs.targetOS.contains("windows") ? "bin" : libDirName property string libexecInstallDir: "libexec/qbs" property string relativeLibexecPath: "../" + libexecInstallDir property string relativePluginsPath: "../" + libDirName property string relativeSearchPath: ".." property stringList libRPaths: { if (!enableRPath) return undefined; if (qbs.targetOS.contains("linux")) return ["$ORIGIN/../" + libDirName]; if (qbs.targetOS.contains("osx")) return ["@loader_path/../" + libDirName] } property string resourcesInstallDir: "" property string pluginsInstallDir: libDirName references: [ "doc/doc.qbs", "share/share.qbs", "src/src.qbs", "tests/auto/auto.qbs", "tests/fuzzy-test/fuzzy-test.qbs", "tests/benchmarker/benchmarker.qbs", ] SubProject { filePath: "examples/examples.qbs" Properties { condition: parent.withExamples } } AutotestRunner { Depends { name: "Qt.core" } environment: { var env = base; if (qbs.hostOS.contains("windows") && qbs.targetOS.contains("windows")) { var path = ""; for (var i = 0; i < env.length; ++i) { if (env[i].startsWith("PATH=")) { path = env[i].substring(5); break; } } path = Qt.core.binPath + ";" + path; var arrayElem = "PATH=" + path; if (i < env.length) env[i] = arrayElem; else env.push(arrayElem); } return env; } } } qbs-src-1.4.5/qbs_version.pri000066400000000000000000000001631266132464200161470ustar00rootroot00000000000000QBS_VERSION = 1.4.5 QBS_VERSION_MAJ = $$section(QBS_VERSION, ., 0, 0) DEFINES += QBS_VERSION=\\\"$$QBS_VERSION\\\" qbs-src-1.4.5/share/000077500000000000000000000000001266132464200142035ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/000077500000000000000000000000001266132464200147705ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/imports/000077500000000000000000000000001266132464200164655ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/imports/qbs/000077500000000000000000000000001266132464200172525ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/imports/qbs/BundleTools/000077500000000000000000000000001266132464200215045ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/imports/qbs/BundleTools/bundle-tools.js000066400000000000000000000060761266132464200244620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = loadExtension("qbs.FileInfo"); var DarwinTools = loadExtension("qbs.DarwinTools"); var PropertyList = loadExtension("qbs.PropertyList"); function destinationDirectoryForResource(product, input) { var path = product.destinationDirectory; var inputFilePath = FileInfo.joinPaths(input.baseDir, input.fileName); var key = DarwinTools.localizationKey(inputFilePath); if (key) { path = FileInfo.joinPaths(path, localizedResourcesFolderPath(product, key)); var subPath = DarwinTools.relativeResourcePath(inputFilePath); if (subPath && subPath !== '.') path = FileInfo.joinPaths(path, subPath); } else { path = FileInfo.joinPaths(path, product.moduleProperty("bundle", "unlocalizedResourcesFolderPath")); } return path; } function localizedResourcesFolderPath(product, key) { return FileInfo.joinPaths(product.moduleProperty("bundle", "unlocalizedResourcesFolderPath"), key + product.moduleProperty("bundle", "localizedResourcesFolderSuffix")); } function infoPlistContents(infoPlistFilePath) { if (infoPlistFilePath === undefined) return undefined; var plist = new PropertyList(); try { plist.readFromFile(infoPlistFilePath); return plist.toObject(); } finally { plist.clear(); } } function infoPlistFormat(infoPlistFilePath) { if (infoPlistFilePath === undefined) return undefined; var plist = new PropertyList(); try { plist.readFromFile(infoPlistFilePath); return plist.format(); } finally { plist.clear(); } } qbs-src-1.4.5/share/qbs/imports/qbs/DarwinTools/000077500000000000000000000000001266132464200215175ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/imports/qbs/DarwinTools/darwin-tools.js000066400000000000000000000156421266132464200245070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = loadExtension("qbs.FileInfo"); /** * Returns the most appropriate Apple platform name given a targetOS list. * Possible platform names include macosx, iphoneos, and iphonesimulator. */ function applePlatformName(targetOSList) { if (targetOSList.contains("ios-simulator")) return "iphonesimulator"; else if (targetOSList.contains("ios")) return "iphoneos"; else if (targetOSList.contains("osx")) return "macosx"; throw("No Apple platform corresponds to target OS list: " + targetOSList); } /** * Replace characters unsafe for use in a domain name with a '-' character (RFC 1034). */ function rfc1034(inStr) { // ### Remove in Qbs 1.5 print("WARNING: DarwinTools.rfc1034 is deprecated; use qbs.rfc1034Identifier instead"); return qbs.rfc1034Identifier(inStr); } /** * Returns the localization of the resource at the given path, * or undefined if the path does not contain an {xx}.lproj path segment. */ function localizationKey(path) { return _resourceFileProperties(path)[0]; } /** * Returns the path of a localized resource at the given path, * relative to its containing {xx}.lproj directory, or '.' * if the resource is unlocalized (not contained in an lproj directory). */ function relativeResourcePath(path) { return _resourceFileProperties(path)[1]; } function _resourceFileProperties(path) { var lprojKey = ".lproj/"; var lproj = path.indexOf(lprojKey); if (lproj >= 0) { // The slash preceding XX.lproj var slashIndex = path.slice(0, lproj).lastIndexOf('/'); if (slashIndex >= 0) { var localizationKey = path.slice(slashIndex + 1, lproj); var relativeResourcePath = FileInfo.path(path.slice(lproj + lprojKey.length)); return [ localizationKey, relativeResourcePath ]; } } return [ undefined, '.' ]; } /** * Recursively perform variable replacements in an environment dictionary. * * JSON.stringify(expandPlistEnvironmentVariables({a:"$(x)3$$(y)",b:{t:"%$(y) $(k)"}}, * {x:"X",y:"Y"}, true)) * Warning undefined variable k in variable expansion * => {"a":"X3$Y","b":{"t":"%Y $(k)"}} */ function expandPlistEnvironmentVariables(obj, env, warn) { // Possible syntaxes for wrapping an environment variable name var syntaxes = [ {"open": "${", "close": "}"}, {"open": "$(", "close": ")"}, {"open": "@", "close": "@"} ]; /** * Finds the first index of a replacement starting with one of the supported syntaxes * This is needed so we don't do recursive substitutions */ function indexOfReplacementStart(syntaxes, str, offset) { var syntax; var idx = str.length; for (var i in syntaxes) { var j = str.indexOf(syntaxes[i].open, offset); if (j !== -1 && j < idx) { syntax = syntaxes[i]; idx = j; } } return { "syntax": syntax, "index": idx === str.length ? -1 : idx }; } function expandRecursive(obj, env, checked) { checked.push(obj); for (var key in obj) { var value = obj[key]; var type = typeof(value); if (type === "object") { if (checked.indexOf(value) !== -1) continue; expandRecursive(value, env, checked); } if (type !== "string") continue; var repl = indexOfReplacementStart(syntaxes, value); var i = repl.index; var changes = false; while (i !== -1) { var j = value.indexOf(repl.syntax.close, i + repl.syntax.open.length); if (j === -1) break; var varParts = value.slice(i + repl.syntax.open.length, j).split(':'); var varName = varParts[0]; var varFormatter = varParts[1]; var varValue = env[varName]; if (undefined === varValue) { // skip replacement if (warn) print("Warning undefined variable ",varName, " in variable expansion"); } else { changes = true; varValue = String(varValue); if (varFormatter !== undefined) varFormatter = varFormatter.toLowerCase(); if (varFormatter === "rfc1034identifier") varValue = qbs.rfc1034Identifier(varValue); value = value.slice(0, i) + varValue + value.slice(j + repl.syntax.close.length); // avoid recursive substitutions to avoid potentially infinite loops i += varValue.length; } repl = indexOfReplacementStart(syntaxes, value, i + repl.syntax.close.length); i = repl.index; } if (changes) obj[key] = value; } } expandRecursive(obj, env, []); return obj; } /** * Recursively removes any undefined, null, or empty string values from the property list. */ function cleanPropertyList(plist) { if (typeof(plist) !== "object") return; for (var key in plist) { if (plist[key] === undefined || plist[key] === null || plist[key] === "") delete plist[key]; else cleanPropertyList(plist[key]); } } qbs-src-1.4.5/share/qbs/imports/qbs/FileInfo/000077500000000000000000000000001266132464200207455ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/imports/qbs/FileInfo/fileinfo.js000066400000000000000000000074631266132464200231100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var _windowsAbsolutePathPattern = new RegExp("^[a-z,A-Z]:[/,\\\\]"); var _removeDoubleSlashesPattern = new RegExp("/{2,}", "g"); function path(fp) { if (fp === '/') return fp; // Yes, this will be wrong for "clever" unix users calling their directory 'c:'. Boohoo. if (fp.length === 3 && fp.slice(-2) === ":/") return fp; var last = fp.lastIndexOf('/'); if (last < 0) return '.'; return fp.slice(0, last); } function fileName(fph) { var fp = fph.toString(); var last = fp.lastIndexOf('/'); if (last < 0) return fp; return fp.slice(last + 1); } function baseName(fph) { var fn = fileName(fph); return fn.split('.')[0]; } function completeBaseName(fph) { var fn = fileName(fph); var last = fn.lastIndexOf('.'); if (last < 0) return fn; else return fn.slice(0, last); } function relativePath(base, rel) { var basel = base.split('/'); var rell = rel.split('/'); var i; for (i = basel.length; i-- >= 0;) { if (basel[i] === '.' || basel[i] === '') basel.splice(i, 1); } for (i = rell.length; i-- >= 0;) { if (rell[i] === '.' || rell[i] === '') rell.splice(i, 1); } i = 0; while (i < basel.length && i < rell.length && basel[i] === rell[i]) i++; var j = i; var r = []; for (; i < basel.length; i++) r.push(".."); for (; j < rell.length; j++) r.push(rell[j]); return r.join('/'); } function isAbsolutePath(path) { if (!path) return false; return (path.charAt(0) === '/' || _windowsAbsolutePathPattern.test(path)); } function toWindowsSeparators(str) { return str.toString().replace(/\//g, '\\'); } function fromWindowsSeparators(str) { return str.toString().replace(/\\/g, '/'); } function toNativeSeparators(str, os) { return os.contains("windows") ? toWindowsSeparators(str) : str; } function fromNativeSeparators(str, os) { return os.contains("windows") ? fromWindowsSeparators(str) : str; } function joinPaths() { function pathFilter(path) { return path && typeof path === "string"; } var paths = Array.prototype.slice.call(arguments, 0).filter(pathFilter); var joinedPaths = paths.join('/'); return joinedPaths.replace(_removeDoubleSlashesPattern, '/'); } qbs-src-1.4.5/share/qbs/imports/qbs/ModUtils/000077500000000000000000000000001266132464200210125ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/imports/qbs/ModUtils/utils.js000066400000000000000000000317141266132464200225160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = loadExtension("qbs.FileInfo"); /** * Given a list of file tags, returns the file tag (one of [c, cpp, objc, objcpp]) * corresponding to the C-family language the file should be compiled as. * * If no such tag is found, undefined is returned. If more than one match is * found, an exception is thrown. */ function fileTagForTargetLanguage(fileTags) { var srcTags = ["c", "cpp", "objc", "objcpp", "asm", "asm_cpp"]; var pchTags = ["c_pch", "cpp_pch", "objc_pch", "objcpp_pch"]; var canonicalTag = undefined; var foundTagCount = 0; for (var i = 0; i < fileTags.length; ++i) { var idx = srcTags.indexOf(fileTags[i]); if (idx === -1) idx = pchTags.indexOf(fileTags[i]); if (idx !== -1) { canonicalTag = srcTags[idx]; if (++foundTagCount > 1) break; } } if (foundTagCount > 1) throw ("source files cannot be identified as more than one language"); return foundTagCount == 1 ? canonicalTag : undefined; } /** * Returns the name of a language-specific property given the file tag * for that property, and the base property name. * * If \a fileTag is undefined, the language-agnostic property name is returned. * * @param propertyName flags, platformFlags, precompiledHeader * @param fileTag c, cpp, objc, objcpp */ function languagePropertyName(propertyName, fileTag) { if (!fileTag) fileTag = "common"; var map = { "c": { "flags": "cFlags", "platformFlags": "platformCFlags", "precompiledHeader": "cPrecompiledHeader" }, "cpp": { "flags": "cxxFlags", "platformFlags": "platformCxxFlags", "precompiledHeader": "cxxPrecompiledHeader" }, "objc": { "flags": "objcFlags", "platformFlags": "platformObjcFlags", "precompiledHeader": "objcPrecompiledHeader" }, "objcpp": { "flags": "objcxxFlags", "platformFlags": "platformObjcxxFlags", "precompiledHeader": "objcxxPrecompiledHeader" }, "common": { "flags": "commonCompilerFlags", "platformFlags": "platformCommonCompilerFlags", "precompiledHeader": "precompiledHeader" } }; var lang = map[fileTag]; if (!lang) return propertyName; return lang[propertyName] || propertyName; } function moduleProperties(config, key, langFilter) { return config.moduleProperties(config.moduleName, languagePropertyName(key, langFilter)) } function modulePropertiesFromArtifacts(product, artifacts, moduleName, propertyName, langFilter) { var result = product.moduleProperties(moduleName, languagePropertyName(propertyName, langFilter)) for (var i in artifacts) result = result.concat(artifacts[i].moduleProperties(moduleName, languagePropertyName(propertyName, langFilter))) return result } function moduleProperty(product, propertyName, langFilter) { return product.moduleProperty(product.moduleName, languagePropertyName(propertyName, langFilter)) } /** * Returns roughly the same value as moduleProperty for a product, but ensures that all of the * given input artifacts share the same value of said property, as a sort of sanity check. * * This allows us to verify that users do not, for example, try to set different values on input * artifacts for which the value is input specific (not product specific), but which must be the * same for all inputs. */ function modulePropertyFromArtifacts(product, artifacts, moduleName, propertyName, langFilter) { var values = [product.moduleProperty(moduleName, languagePropertyName(propertyName, langFilter))]; for (var i in artifacts) { var value = artifacts[i].moduleProperty(moduleName, languagePropertyName(propertyName, langFilter)); if (!values.contains(value)) { values.push(value); } } if (values.length !== 1) { throw "The value of " + [moduleName, propertyName].join(".") + " must be identical for the following input artifacts: " + artifacts.map(function (artifact) { return artifact.filePath; }); } return values[0]; } function dumpProperty(key, value, level) { var indent = ""; for (var k = 0; k < level; ++k) indent += " "; print(indent + key + ": " + value); } function traverseObject(obj, func, level) { if (!level) level = 0; var i, children = {}; for (i in obj) { if (typeof(obj[i]) === "object" && !(obj[i] instanceof Array)) children[i] = obj[i]; else func.apply(this, [i, obj[i], level]); } level++; for (i in children) { func.apply(this, [i, children[i], level - 1]); traverseObject(children[i], func, level); } level--; } function dumpObject(obj, description) { if (!description) description = "object dump"; print("+++++++++ " + description + " +++++++++"); traverseObject(obj, dumpProperty); } function concatAll() { var result = []; for (var i = 0; i < arguments.length; ++i) { var arg = arguments[i]; if (arg === undefined) continue; else if (arg instanceof Array) result = result.concat(arg); else result.push(arg); } return result; } /** * Flattens an environment dictionary (string keys to arrays or strings) * into a string list containing items like \c key=value1:value2:value3 */ function flattenEnvironmentDictionary(dict, pathListSeparator) { var list = []; for (var i in dict) list.push(i + "=" + dict[i]); return list; } var EnvironmentVariable = (function () { function EnvironmentVariable(name, separator, convertPathSeparators) { if (!name) throw "EnvironmentVariable c'tor needs a name as first argument."; this.name = name; this.value = getEnv(name).toString(); this.separator = separator || ""; this.convertPathSeparators = convertPathSeparators || false; } EnvironmentVariable.prototype.prepend = function (v) { if (this.value.length > 0 && this.value.charAt(0) !== this.separator) this.value = this.separator + this.value; if (this.convertPathSeparators) v = FileInfo.toWindowsSeparators(v); this.value = v + this.value; }; EnvironmentVariable.prototype.append = function (v) { if (this.value.length > 0) this.value += this.separator; if (this.convertPathSeparators) v = FileInfo.toWindowsSeparators(v); this.value += v; }; EnvironmentVariable.prototype.set = function () { putEnv(this.name, this.value); }; EnvironmentVariable.prototype.unset = function () { unsetEnv(this.name); }; return EnvironmentVariable; })(); var PropertyValidator = (function () { function PropertyValidator(moduleName) { this.requiredProperties = {}; this.propertyValidators = []; if (!moduleName) throw "PropertyValidator c'tor needs a module name as a first argument."; this.moduleName = moduleName; } PropertyValidator.prototype.setRequiredProperty = function (propertyName, propertyValue, message) { this.requiredProperties[propertyName] = { propertyValue: propertyValue, message: message }; }; PropertyValidator.prototype.addRangeValidator = function (propertyName, propertyValue, min, max, allowFloats) { var message = []; if (min !== undefined) message.push(">= " + min); if (max !== undefined) message.push("<= " + max); this.addCustomValidator(propertyName, propertyValue, function (value) { if (typeof value !== "number") return false; if (!allowFloats && value % 1 !== 0) return false; if (min !== undefined && value < min) return false; if (max !== undefined && value > max) return false; return true; }, "must be " + (!allowFloats ? "an integer " : "") + message.join(" and ")); }; PropertyValidator.prototype.addVersionValidator = function (propertyName, propertyValue, minComponents, maxComponents, allowSuffixes) { if (minComponents !== undefined && (typeof minComponents !== "number" || minComponents % 1 !== 0 || minComponents < 1)) throw "minComponents must be at least 1"; if (maxComponents !== undefined && (typeof maxComponents !== "number" || maxComponents % 1 !== 0 || maxComponents < minComponents)) throw "maxComponents must be >= minComponents"; this.addCustomValidator(propertyName, propertyValue, function (value) { if (typeof value !== "string") return false; return value && value.match("^[0-9]+(\\.[0-9]+){" + ((minComponents - 1) || 0) + "," + ((maxComponents - 1) || "") + "}" + (!allowSuffixes ? "$" : "")) !== null; }, "must be a version number with " + minComponents + " to " + maxComponents + " components"); }; PropertyValidator.prototype.addCustomValidator = function (propertyName, propertyValue, validator, message) { this.propertyValidators.push({ propertyName: propertyName, propertyValue: propertyValue, validator: validator, message: message }); }; PropertyValidator.prototype.validate = function (throwOnError) { var i; var lines; // Find any missing properties var missingProperties = {}; for (i in this.requiredProperties) { var propValue = this.requiredProperties[i].propertyValue; if (propValue === undefined || propValue === null || propValue === "") { missingProperties[i] = this.requiredProperties[i]; } } // Find any properties that don't satisfy their validator function var invalidProperties = {}; for (var j = 0; j < this.propertyValidators.length; ++j) { var v = this.propertyValidators[j]; if (!v.validator(v.propertyValue)) { var messages = invalidProperties[v.propertyName] || []; messages.push(v.message); invalidProperties[v.propertyName] = messages; } } var errorMessage = ""; if (Object.keys(missingProperties).length > 0) { errorMessage += "The following properties are not set. Set them in your profile or product:\n"; lines = []; for (i in missingProperties) { var obj = missingProperties[i]; lines.push(this.moduleName + "." + i + ((obj && obj.message) ? (": " + obj.message) : "")); } errorMessage += lines.join("\n"); } if (Object.keys(invalidProperties).length > 0) { if (errorMessage) errorMessage += "\n"; errorMessage += "The following properties have invalid values:\n"; lines = []; for (i in invalidProperties) { for (j in invalidProperties[i]) { lines.push(this.moduleName + "." + i + ": " + invalidProperties[i][j]); } } errorMessage += lines.join("\n"); } if (throwOnError !== false && errorMessage.length > 0) throw errorMessage; return errorMessage.length == 0; }; return PropertyValidator; })(); qbs-src-1.4.5/share/qbs/imports/qbs/PathTools/000077500000000000000000000000001266132464200211675ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/imports/qbs/PathTools/path-tools.js000066400000000000000000000154101266132464200236200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = loadExtension("qbs.FileInfo"); function applicationFileName(product) { return product.moduleProperty("cpp", "executablePrefix") + product.targetName + product.moduleProperty("cpp", "executableSuffix"); } function applicationFilePath(product) { if (product.moduleProperty("bundle", "isBundle")) return product.moduleProperty("bundle", "executablePath"); else return applicationFileName(product); } function loadableModuleFileName(product) { return product.moduleProperty("cpp", "loadableModulePrefix") + product.targetName + product.moduleProperty("cpp", "loadableModuleSuffix"); } function loadableModuleFilePath(product) { if (product.moduleProperty("bundle", "isBundle")) return product.moduleProperty("bundle", "executablePath"); else return loadableModuleFileName(product); } function staticLibraryFileName(product) { return product.moduleProperty("cpp", "staticLibraryPrefix") + product.targetName + product.moduleProperty("cpp", "staticLibrarySuffix"); } function staticLibraryFilePath(product) { if (product.moduleProperty("bundle", "isBundle")) return product.moduleProperty("bundle", "executablePath"); else return staticLibraryFileName(product); } function dynamicLibraryFileName(product, version, maxParts) { // If no override version was given, use the product's version // We specifically want to differentiate between undefined and i.e. // empty string as empty string should be taken to mean "no version" // and undefined should be taken to mean "use the product's version" // (which could still end up being "no version") if (version === undefined) version = product.moduleProperty("cpp", "internalVersion"); // If we have a version number, potentially strip off some components maxParts = parseInt(maxParts, 10); if (maxParts === 0) version = undefined; else if (maxParts && version) version = version.split('.').slice(0, maxParts).join('.'); // Start with prefix + name (i.e. libqbs, qbs) var fileName = product.moduleProperty("cpp", "dynamicLibraryPrefix") + product.targetName; // For Darwin platforms, append the version number if there is one (i.e. libqbs.1.0.0) var targetOS = product.moduleProperty("qbs", "targetOS"); if (version && targetOS.contains("darwin")) { fileName += "." + version; version = undefined; } // Append the suffix (i.e. libqbs.1.0.0.dylib, libqbs.so, qbs.dll) fileName += product.moduleProperty("cpp", "dynamicLibrarySuffix"); // For non-Darwin Unix platforms, append the version number if there is one (i.e. libqbs.so.1.0.0) if (version && targetOS.contains("unix") && !targetOS.contains("darwin")) fileName += "." + version; return fileName; } function dynamicLibraryFilePath(product, version, maxParts) { if (product.moduleProperty("bundle", "isBundle")) return product.moduleProperty("bundle", "executablePath"); else return dynamicLibraryFileName(product, version, maxParts); } function importLibraryFilePath(product) { return product.moduleProperty("cpp", "dynamicLibraryPrefix") + product.targetName + product.moduleProperty("cpp", "dynamicLibraryImportSuffix"); } function debugInfoFileName(product) { if (product.moduleProperty("bundle", "isBundle")) return product.moduleProperty("bundle", "bundleName") + product.moduleProperty("cpp", "debugInfoSuffix"); else if (product.type.contains("application")) return applicationFileName(product) + product.moduleProperty("cpp", "debugInfoSuffix"); else if (product.type.contains("dynamiclibrary")) return dynamicLibraryFileName(product) + product.moduleProperty("cpp", "debugInfoSuffix"); else if (product.type.contains("loadablemodule")) return loadableModuleFileName(product) + product.moduleProperty("cpp", "debugInfoSuffix"); else if (product.type.contains("staticlibrary")) return staticLibraryFileName(product) + product.moduleProperty("cpp", "debugInfoSuffix"); else return product.targetName + product.moduleProperty("cpp", "debugInfoSuffix"); } // Returns whether the string looks like a library filename function isLibraryFileName(product, fileName, prefix, suffixes, isShared) { var suffix, i; var os = product.moduleProperty("qbs", "targetOS"); for (i = 0; i < suffixes.length; ++i) { suffix = suffixes[i]; if (isShared && os.contains("unix") && !os.contains("darwin")) suffix += "(\\.[0-9]+){0,3}"; if (fileName.match("^" + prefix + ".+?\\" + suffix + "$")) return true; } return false; } function frameworkExecutablePath(frameworkPath) { var suffix = ".framework"; var isAbsoluteFrameworkPath = frameworkPath.slice(-suffix.length) === suffix; if (isAbsoluteFrameworkPath) { var frameworkName = FileInfo.fileName(frameworkPath).slice(0, -suffix.length); return FileInfo.joinPaths(frameworkPath, frameworkName); } return undefined; } // pathList is also a string, using the respective separator function prependOrSetPath(path, pathList, separator) { if (!pathList || pathList.length === 0) return path; return path + separator + pathList; } qbs-src-1.4.5/share/qbs/imports/qbs/Probes/000077500000000000000000000000001266132464200205045ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/imports/qbs/Probes/AndroidNdkProbe.qbs000066400000000000000000000047641266132464200242330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.File import qbs.FileInfo PathProbe { // Inputs property stringList hostOS: qbs.hostOS environmentPaths: qbs.getEnv("ANDROID_NDK_ROOT") // Outputs property var hostArch configure: { var i, j; for (i in environmentPaths) { var platforms = []; if (hostOS.contains("windows")) platforms.push("windows-x86_64", "windows"); if (hostOS.contains("darwin")) platforms.push("darwin-x86_64", "darwin-x86"); if (hostOS.contains("linux")) platforms.push("linux-x86_64", "linux-x86"); for (j in platforms) { if (File.exists(FileInfo.joinPaths(environmentPaths[i], "prebuilt", platforms[j]))) { path = environmentPaths[i]; hostArch = platforms[j]; found = true; return; } } } } } qbs-src-1.4.5/share/qbs/imports/qbs/Probes/AndroidSdkProbe.qbs000066400000000000000000000041321266132464200242250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.File import qbs.FileInfo PathProbe { environmentPaths: qbs.getEnv("ANDROID_HOME") // Outputs property string buildToolsVersion property string platform configure: { var i; for (i in environmentPaths) { if (File.exists(FileInfo.joinPaths(environmentPaths[i], "tools", "android"))) { path = environmentPaths[i]; buildToolsVersion = undefined; // not yet implemented platform = undefined; // not yet implemented found = true; return; } } } } qbs-src-1.4.5/share/qbs/imports/qbs/Probes/BinaryProbe.qbs000066400000000000000000000031321266132464200234260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs 1.0 PathProbe { platformPaths: undefined platformEnvironmentPaths: [ "PATH" ] } qbs-src-1.4.5/share/qbs/imports/qbs/Probes/FrameworkProbe.qbs000066400000000000000000000034301266132464200241400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs 1.0 PathProbe { platformPaths: [ "~/Library/Frameworks", "/usr/local/lib", "/Library/Frameworks", "/System/Library/Frameworks" ] nameFilter: { return function(name) { return name + ".framework"; } } } qbs-src-1.4.5/share/qbs/imports/qbs/Probes/IncludeProbe.qbs000066400000000000000000000033021266132464200235640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs 1.0 PathProbe { pathSuffixes: [ "include" ] platformEnvironmentPaths: { if (qbs.toolchain.contains('msvc')) return [ "INCLUDE" ]; return undefined; } } qbs-src-1.4.5/share/qbs/imports/qbs/Probes/JdkProbe.qbs000066400000000000000000000043561266132464200227230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.File import qbs.FileInfo import qbs.Process import "../../../modules/java/utils.js" as JavaUtils PathProbe { // Inputs property stringList hostOS: qbs.hostOS property string architecture: qbs.architecture environmentPaths: qbs.getEnv("JAVA_HOME") platformPaths: [ "/usr/lib/jvm/default-java", // Debian/Ubuntu "/etc/alternatives/java_sdk_openjdk", // Fedora "/usr/lib/jvm/default" // Arch ] // Outputs property var version configure: { path = JavaUtils.findJdkPath(hostOS, architecture, environmentPaths, platformPaths); if (path) version = JavaUtils.findJdkVersion(FileInfo.joinPaths(path, "bin", "javac")); found = path && version; } } qbs-src-1.4.5/share/qbs/imports/qbs/Probes/NodeJsProbe.qbs000066400000000000000000000036211266132464200233670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.FileInfo BinaryProbe { names: ["nodejs", "node" + (qbs.hostOS.contains("windows") ? ".exe" : "")] platformPaths: base.concat(qbs.hostOS.contains("windows") ? [FileInfo.joinPaths(qbs.getEnv("PROGRAMFILES"), "nodejs"), FileInfo.joinPaths(qbs.getEnv("PROGRAMFILES(X86)"), "nodejs")] : []) } qbs-src-1.4.5/share/qbs/imports/qbs/Probes/PathProbe.qbs000066400000000000000000000065711266132464200231100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs 1.0 import qbs.File import qbs.FileInfo import qbs.ModUtils Probe { // Inputs property stringList names property var nameFilter property pathList pathPrefixes property stringList pathSuffixes property pathList platformPaths: [ '/usr', '/usr/local' ] property pathList environmentPaths property pathList platformEnvironmentPaths // Output property string path property string filePath property string fileName configure: { if (!names) throw '"names" must be specified'; var _names = ModUtils.concatAll(names); if (nameFilter) _names = _names.map(nameFilter); // FIXME: Suggest how to obtain paths from system var _paths = ModUtils.concatAll(pathPrefixes, platformPaths); // FIXME: Add getenv support var envs = ModUtils.concatAll(platformEnvironmentPaths, environmentPaths); for (var i = 0; i < envs.length; ++i) { var value = qbs.getEnv(envs[i]) || ''; if (value.length > 0) _paths = _paths.concat(value.split(qbs.pathListSeparator)); } var _suffixes = ModUtils.concatAll('', pathSuffixes); for (i = 0; i < _names.length; ++i) { for (var j = 0; j < _paths.length; ++j) { for (var k = 0; k < _suffixes.length; ++k) { var _filePath = FileInfo.joinPaths(_paths[j], _suffixes[k], _names[i]); if (File.exists(_filePath)) { found = true; path = FileInfo.joinPaths(_paths[j], _suffixes[k]); filePath = _filePath; fileName = _names[i]; return; } } } } found = false; path = undefined; filePath = undefined; fileName = undefined; } } qbs-src-1.4.5/share/qbs/imports/qbs/Probes/PkgConfigProbe.qbs000066400000000000000000000061221266132464200240530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs 1.0 import qbs.Process import qbs.FileInfo Probe { // Inputs property string executable: 'pkg-config' property string name property string minVersion property string exactVersion property string maxVersion // Output property stringList cflags property stringList libs configure: { if (!name) throw '"name" must be specified'; var p = new Process(); try { var args = [ name ]; if (minVersion !== undefined) args.push(name + ' >= ' + minVersion); if (exactVersion !== undefined) args.push(name + ' = ' + exactVersion); if (maxVersion !== undefined) args.push(name + ' <= ' + maxVersion); if (p.exec(executable, args.concat([ '--cflags' ])) === 0) { cflags = p.readStdOut().trim(); if (cflags === "") cflags = undefined; else cflags = cflags.split(/\s/); if (p.exec(executable, args.concat([ '--libs' ])) === 0) { libs = p.readStdOut().trim(); if (libs === "") libs = undefined; else libs = libs.split(/\s/); found = true; print("PkgConfigProbe: found library " + name); return; } } found = false; cflags = undefined; libs = undefined; } finally { p.close(); } } } qbs-src-1.4.5/share/qbs/imports/qbs/Probes/TypeScriptProbe.qbs000066400000000000000000000070271266132464200243170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.File import qbs.FileInfo import qbs.ModUtils import "../../../modules/typescript/typescript.js" as TypeScript BinaryProbe { id: tsc names: ["tsc"] // Inputs property path nodejsToolchainInstallPath // Outputs property var version configure: { if (!nodejsToolchainInstallPath) throw '"nodejsToolchainInstallPath" must be specified'; // HACK: Duplicated from PathProbe.qbs if (!names) throw '"names" must be specified'; var _names = ModUtils.concatAll(names); if (nameFilter) _names = _names.map(nameFilter); // FIXME: Suggest how to obtain paths from system var _paths = ModUtils.concatAll(pathPrefixes, platformPaths); // FIXME: Add getenv support var envs = ModUtils.concatAll(platformEnvironmentPaths, environmentPaths); for (var i = 0; i < envs.length; ++i) { var value = qbs.getEnv(envs[i]) || ''; if (value.length > 0) _paths = _paths.concat(value.split(qbs.pathListSeparator)); } var _suffixes = ModUtils.concatAll('', pathSuffixes); for (i = 0; i < _names.length; ++i) { for (var j = 0; j < _paths.length; ++j) { for (var k = 0; k < _suffixes.length; ++k) { var _filePath = FileInfo.joinPaths(_paths[j], _suffixes[k], _names[i]); if (File.exists(_filePath)) { found = true; filePath = File.canonicalFilePath(_filePath); fileName = FileInfo.fileName(filePath); path = FileInfo.path(filePath); version = TypeScript.findTscVersion(filePath, nodejsToolchainInstallPath); return; } } } } found = false; path = undefined; filePath = undefined; fileName = undefined; version = undefined; // HACK: Duplicated from PathProbe.qbs } } qbs-src-1.4.5/share/qbs/imports/qbs/UnixUtils/000077500000000000000000000000001266132464200212165ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/imports/qbs/UnixUtils/unix-utils.js000066400000000000000000000046611266132464200237040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = loadExtension("qbs.FileInfo"); function soname(product, outputFileName) { if (product.moduleProperty("qbs", "targetOS").contains("darwin")) { if (product.moduleProperty("bundle", "isBundle")) outputFileName = product.moduleProperty("bundle", "executablePath"); var prefix = product.moduleProperty("cpp", "installNamePrefix"); if (prefix) outputFileName = FileInfo.joinPaths(prefix, outputFileName); return outputFileName; } function majorVersion(version, defaultValue) { var n = parseInt(version, 10); return isNaN(n) ? defaultValue : n; } var version = product.moduleProperty("cpp", "internalVersion"); if (version) { var major = majorVersion(version); if (major) { return outputFileName.substr(0, outputFileName.length - version.length) + major; } } return outputFileName; } qbs-src-1.4.5/share/qbs/imports/qbs/WindowsUtils/000077500000000000000000000000001266132464200217255ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/imports/qbs/WindowsUtils/windows-utils.js000066400000000000000000000052111266132464200251120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ function characterSetDefines(charset) { var defines = []; if (charset === "unicode") defines.push("UNICODE", "_UNICODE"); else if (charset === "mbcs") defines.push("_MBCS"); return defines; } function isValidWindowsVersion(systemVersion) { // Add new Windows versions to this list when they are released var realVersions = [ '6.3', '6.2', '6.1', '6.0', '5.2', '5.1', '5.0', '4.0' ]; for (i in realVersions) if (systemVersion === realVersions[i]) return true; return false; } function getWindowsVersionInFormat(systemVersion, format) { if (!isValidWindowsVersion(systemVersion)) return undefined; var major = parseInt(systemVersion.split('.')[0]); var minor = parseInt(systemVersion.split('.')[1]); if (format === 'hex') { return '0x' + major + (minor < 10 ? '0' : '') + minor; } else if (format === 'subsystem') { // http://msdn.microsoft.com/en-us/library/fcc1zstk.aspx return major + '.' + (minor < 10 ? '0' : '') + minor; } else { throw ("Unrecognized Windows version format " + format + ". Must be in {hex, subsystem}."); } } qbs-src-1.4.5/share/qbs/imports/qbs/base/000077500000000000000000000000001266132464200201645ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/imports/qbs/base/AndroidApk.qbs000066400000000000000000000054041266132464200227120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.FileInfo Product { type: ["android.apk"] Depends { name: "Android.sdk" } property string packageName: name property bool automaticSources: true property bool legacyLayout: false property path sourceSetDir: legacyLayout ? undefined : "src/main" property path resourcesDir: FileInfo.joinPaths(sourceSetDir, "res") property path assetsDir: FileInfo.joinPaths(sourceSetDir, "assets") property path sourcesDir: FileInfo.joinPaths(sourceSetDir, legacyLayout ? "src" : "java") property path manifestFile: FileInfo.joinPaths(sourceSetDir, "AndroidManifest.xml") Group { name: "java sources" condition: product.automaticSources prefix: product.sourcesDir + '/' files: "**/*.java" } Group { name: "android resources" condition: product.automaticSources fileTags: ["android.resources"] prefix: product.resourcesDir + '/' files: "**/*" } Group { name: "android assets" condition: product.automaticSources fileTags: ["android.assets"] prefix: product.assetsDir + '/' files: "**/*" } Group { name: "manifest" condition: product.automaticSources files: [manifestFile] } } qbs-src-1.4.5/share/qbs/imports/qbs/base/Application.qbs000066400000000000000000000041221266132464200231350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { type: { if (isForAndroid && !consoleApplication) return ["dynamiclibrary", "android.nativelibrary"]; return ["application"]; } property bool isForAndroid: qbs.targetOS.contains("android") property stringList architectures: isForAndroid ? ["armv5"] : undefined Depends { name: "Android.ndk"; condition: isForAndroid } Depends { name: "bundle" } Depends { name: "cpp"; condition: isForAndroid } profiles: isForAndroid ? architectures.map(function(arch) { return project.profile + '-' + arch; }) : [project.profile] } qbs-src-1.4.5/share/qbs/imports/qbs/base/ApplicationExtension.qbs000066400000000000000000000043261266132464200250400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs XPCService { type: base.concat(["applicationextension"]) cpp.entryPoint: "_NSExtensionMain" cpp.frameworks: base.concat(["/System/Library/PrivateFrameworks/PlugInKit.framework"]) cpp.requireAppExtensionSafeApi: true xpcServiceType: undefined property var extensionAttributes property string extensionPointIdentifier property string extensionPrincipalClass bundle.infoPlist: { var infoPlist = base; infoPlist["NSExtension"] = { "NSExtensionAttributes": extensionAttributes || {}, "NSExtensionPointIdentifier": extensionPointIdentifier, "NSExtensionPrincipalClass": extensionPrincipalClass }; return infoPlist; } } qbs-src-1.4.5/share/qbs/imports/qbs/base/AutotestRunner.qbs000066400000000000000000000046011266132464200236760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.ModUtils Product { name: "autotest-runner" type: ["autotest-result"] builtByDefault: false property stringList arguments: [] property stringList environment: ModUtils.flattenEnvironmentDictionary(qbs.commonRunEnvironment) property bool limitToSubProject: true Depends { productTypes: "autotest" limitToSubProject: product.limitToSubProject } Rule { inputsFromDependencies: "application" Artifact { filePath: qbs.getHash(input.filePath) + ".result.dummy" // Will never exist. fileTags: "autotest-result" alwaysUpdated: false } prepare: { var cmd = new Command(input.filePath, product.arguments); cmd.description = "Running test " + input.fileName; cmd.environment = product.environment; return cmd; } } } qbs-src-1.4.5/share/qbs/imports/qbs/base/CppApplication.qbs000066400000000000000000000030631266132464200236030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs 1.0 Application { Depends { name: "cpp" } } qbs-src-1.4.5/share/qbs/imports/qbs/base/DynamicLibrary.qbs000066400000000000000000000031411266132464200236030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs Library { type: ["dynamiclibrary"].concat(isForAndroid ? ["android.nativelibrary"] : []) } qbs-src-1.4.5/share/qbs/imports/qbs/base/InstallPackage.qbs000066400000000000000000000052321266132464200235570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.TextFile Product { type: ["archiver.archive"] builtByDefault: false Depends { name: "archiver" } archiver.type: "tar" archiver.workingDirectory: qbs.installRoot Rule { multiplex: true inputsFromDependencies: ["installable"] Artifact { filePath: product.name + ".tarlist" fileTags: ["archiver.input-list"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode =function() { var ofile = new TextFile(output.filePath, TextFile.WriteOnly); for (var i = 0; i < inputs["installable"].length; ++i) { var inp = inputs["installable"][i]; var installedFilePath = inp.moduleProperty("qbs", "installDir") + '/' + inp.fileName; while (installedFilePath[0] === '/') installedFilePath = installedFilePath.substring(1); ofile.writeLine(installedFilePath); } ofile.close(); }; return [cmd]; } } } qbs-src-1.4.5/share/qbs/imports/qbs/base/JavaClassCollection.qbs000066400000000000000000000030701266132464200245560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "java" } type: ["java.class"] } qbs-src-1.4.5/share/qbs/imports/qbs/base/JavaJarFile.qbs000066400000000000000000000031251266132464200230120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "java" } type: ["java.jar"] property string entryPoint } qbs-src-1.4.5/share/qbs/imports/qbs/base/Library.qbs000066400000000000000000000042251266132464200223020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { type: { if (qbs.targetOS.contains("ios") && parseInt(cpp.minimumIosVersion, 10) < 8) return ["staticlibrary"]; return ["dynamiclibrary"].concat(isForAndroid ? ["android.nativelibrary"] : []); } property bool isForAndroid: qbs.targetOS.contains("android") property stringList architectures: isForAndroid ? ["armv5"] : undefined Depends { name: "Android.ndk"; condition: isForAndroid } Depends { name: "bundle" } Depends { name: "cpp"; condition: isForAndroid } profiles: isForAndroid ? architectures.map(function(arch) { return project.profile + '-' + arch; }) : [project.profile] } qbs-src-1.4.5/share/qbs/imports/qbs/base/LoadableModule.qbs000066400000000000000000000032011266132464200235400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs Product { Depends { name: "bundle" } type: qbs.targetOS.contains("darwin") ? ["loadablemodule"] : ["dynamiclibrary"] } qbs-src-1.4.5/share/qbs/imports/qbs/base/NSISSetup.qbs000066400000000000000000000031441266132464200224720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "nsis"; condition: qbs.targetOS.contains("windows") } type: ["nsissetup"] } qbs-src-1.4.5/share/qbs/imports/qbs/base/NodeJSApplication.qbs000066400000000000000000000030411266132464200241770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "nodejs" } } qbs-src-1.4.5/share/qbs/imports/qbs/base/QtApplication.qbs000066400000000000000000000030651266132464200234470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs CppApplication { Depends { name: "Qt.core" } } qbs-src-1.4.5/share/qbs/imports/qbs/base/QtGuiApplication.qbs000066400000000000000000000034111266132464200241070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs CppApplication { Depends { name: "Qt.gui" } Depends { name: "Qt" submodules: Qt.gui.defaultQpaPlugin condition: linkDefaultQpaPlugin && Qt.gui.defaultQpaPlugin } property bool linkDefaultQpaPlugin: Qt.gui.isStaticLibrary } qbs-src-1.4.5/share/qbs/imports/qbs/base/StaticLibrary.qbs000066400000000000000000000030521266132464200234470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs Library { type: ["staticlibrary"] } qbs-src-1.4.5/share/qbs/imports/qbs/base/WindowsInstallerPackage.qbs000066400000000000000000000031351266132464200254610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "wix"; condition: qbs.targetOS.contains("windows") } type: ["msi"] } qbs-src-1.4.5/share/qbs/imports/qbs/base/WindowsSetupPackage.qbs000066400000000000000000000031421266132464200246220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ Product { Depends { name: "wix"; condition: qbs.targetOS.contains("windows") } type: ["wixsetup"] } qbs-src-1.4.5/share/qbs/imports/qbs/base/XPCService.qbs000066400000000000000000000035771266132464200226620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs Application { type: base.concat(["xpcservice"]) condition: qbs.targetOS.contains("darwin") property string xpcServiceType: "Application" bundle.infoPlist: { var infoPlist = base; if (xpcServiceType) { infoPlist["XPCService"] = { "ServiceType": xpcServiceType }; } return infoPlist; } } qbs-src-1.4.5/share/qbs/modules/000077500000000000000000000000001266132464200164405ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/modules/Android/000077500000000000000000000000001266132464200200205ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/modules/Android/ndk/000077500000000000000000000000001266132464200205745ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/modules/Android/ndk/ndk.qbs000066400000000000000000000270121266132464200220610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Probes import qbs.TextFile import "utils.js" as NdkUtils Module { Depends { name: "cpp" } Probes.AndroidNdkProbe { id: ndkProbe environmentPaths: [ndkDir].concat(base) } readonly property string abi: NdkUtils.androidAbi(qbs.architecture) PropertyOptions { name: "abi" description: "Corresponds to the 'APP_ABI' variable in an Android.mk file." allowedValues: ["arm64-v8a", "armeabi", "armeabi-v7a", "mips", "mips64", "x86", "x86_64"] } property string appStl: "system" PropertyOptions { name: "stlType" description: "Corresponds to the 'APP_STL' variable in an Android.mk file." allowedValues: [ "system", "gabi++_static", "gabi++_shared", "stlport_static", "stlport_shared", "gnustl_static", "gnustl_shared", "c++_static", "c++_shared" ] } property string toolchainVersion: "4.9" PropertyOptions { name: "toolchainVersion" description: "Corresponds to the 'NDK_TOOLCHAIN_VERSION' variable in an Android.mk file." } property string hostArch: ndkProbe.hostArch property string toolchainDir: NdkUtils.toolchainDir(qbs.toolchain, toolchainVersion, abi) property bool enableExceptions: appStl !== "system" property bool enableRtti: appStl !== "system" property bool hardFloat property string ndkDir: ndkProbe.path property string platform: "android-9" // Internal properties. property int platformVersion: { if (platform) { var match = platform.match(/^android-([0-9]+)$/); if (match !== null) { return parseInt(match[1], 10); } } } property stringList abis: { var list = ["armeabi", "armeabi-v7a"]; if (platformVersion >= 9) list.push("mips", "x86"); if (platformVersion >= 21) list.push("arm64-v8a", "mips64", "x86_64"); return list; } property stringList defines: ["ANDROID"] property string buildProfile: (abi === "armeabi-v7a" && hardFloat) ? (abi + "-hard") : abi property string cxxStlBaseDir: FileInfo.joinPaths(ndkDir, "sources/cxx-stl") property string gabiBaseDir: FileInfo.joinPaths(cxxStlBaseDir, "gabi++") property string stlPortBaseDir: FileInfo.joinPaths(cxxStlBaseDir, "stlport") property string gnuStlBaseDir: FileInfo.joinPaths(cxxStlBaseDir, "gnu-libstdc++", toolchainVersion) property string llvmStlBaseDir: FileInfo.joinPaths(cxxStlBaseDir, "llvm-libc++") property string stlBaseDir: { if (appStl.startsWith("gabi++_")) return gabiBaseDir; else if (appStl.startsWith("stlport_")) return stlPortBaseDir; else if (appStl.startsWith("gnustl_")) return gnuStlBaseDir; else if (appStl.startsWith("c++_")) return llvmStlBaseDir; return undefined; } property string stlLibsDir: { if (stlBaseDir) { var infix = buildProfile; if (armMode === "thumb") infix = FileInfo.joinPaths(infix, "thumb"); return FileInfo.joinPaths(stlBaseDir, "libs", infix); } return undefined; } property string sharedStlFilePath: (stlLibsDir && appStl.endsWith("_shared")) ? FileInfo.joinPaths(stlLibsDir, cpp.dynamicLibraryPrefix + appStl + cpp.dynamicLibrarySuffix) : undefined property string staticStlFilePath: (stlLibsDir && appStl.endsWith("_static")) ? FileInfo.joinPaths(stlLibsDir, cpp.staticLibraryPrefix + appStl + cpp.staticLibrarySuffix) : undefined property string gdbserverFileName: "gdbserver" property string armMode: abi.startsWith("armeabi") ? (qbs.buildVariant === "debug" ? "arm" : "thumb") : undefined; PropertyOptions { name: "armModeType" description: "Determines the instruction set for armeabi configurations." allowedValues: ["arm", "thumb"] } cpp.toolchainInstallPath: FileInfo.joinPaths(ndkDir, "toolchains", toolchainDir, "prebuilt", hostArch, "bin") cpp.toolchainPrefix: NdkUtils.toolchainPrefix(qbs.toolchain, abi) qbs.optimization: ["armeabi", "armeabi-v7a"].contains(abi) ? "small" : base cpp.commonCompilerFlags: NdkUtils.commonCompilerFlags(qbs.buildVariant, abi, hardFloat, armMode) cpp.linkerFlags: NdkUtils.commonLinkerFlags(abi, hardFloat) cpp.cxxFlags: { var flags = []; if (enableExceptions) flags.push("-fexceptions"); else flags.push("-fno-exceptions"); if (enableRtti) flags.push("-frtti"); else flags.push("-fno-rtti"); return flags; } cpp.libraryPaths: { var prefix = FileInfo.joinPaths(cpp.sysroot, "usr"); var paths = []; if (abi === "mips64" || abi === "x86_64") // no lib64 for arm64-v8a paths.push(FileInfo.joinPaths(prefix, "lib64")); paths.push(FileInfo.joinPaths(prefix, "lib")); return paths; } cpp.dynamicLibraries: { var libs = ["c"]; if (!hardFloat) libs.push("m"); if (sharedStlFilePath) libs.push(sharedStlFilePath); return libs; } cpp.staticLibraries: { var libs = ["gcc"]; if (hardFloat) libs.push("m_hard"); if (staticStlFilePath) libs.push(staticStlFilePath); return libs; } cpp.systemIncludePaths: { var includes = []; if (appStl === "system") { includes.push(FileInfo.joinPaths(cxxStlBaseDir, "system", "include")); } else if (appStl.startsWith("gabi++")) { includes.push(FileInfo.joinPaths(gabiBaseDir, "include")); } else if (appStl.startsWith("stlport")) { includes.push(FileInfo.joinPaths(stlPortBaseDir, "stlport")); } else if (appStl.startsWith("gnustl")) { includes.push(FileInfo.joinPaths(gnuStlBaseDir, "include")); includes.push(FileInfo.joinPaths(gnuStlBaseDir, "libs", buildProfile, "include")); includes.push(FileInfo.joinPaths(gnuStlBaseDir, "include", "backward")); } else if (appStl.startsWith("c++_")) { includes.push(FileInfo.joinPaths(llvmStlBaseDir, "libcxx", "include")); includes.push(FileInfo.joinPaths(llvmStlBaseDir + "abi", "libcxxabi", "include")); } return includes; } cpp.defines: { var list = defines; if (hardFloat) list.push("_NDK_MATH_NO_SOFTFP=1"); return list; } cpp.sysroot: FileInfo.joinPaths(ndkDir, "platforms", platform, "arch-" + NdkUtils.abiNameToDirName(abi)) Rule { inputs: ["dynamiclibrary"] outputFileTags: ["android.nativelibrary", "android.gdbserver-info", "android.stl-info"] outputArtifacts: { var artifacts = [{ filePath: FileInfo.joinPaths("stripped-libs", inputs["dynamiclibrary"][0].fileName), fileTags: ["android.nativelibrary"] }]; if (product.moduleProperty("qbs", "buildVariant") === "debug") { artifacts.push({ filePath: "android.gdbserver-info.txt", fileTags: ["android.gdbserver-info"] }); } var stlFilePath = ModUtils.moduleProperty(product, "sharedStlFilePath"); if (stlFilePath) artifacts.push({filePath: "android.stl-info.txt", fileTags: ["android.stl-info"]}); return artifacts; } prepare: { var stlFilePath = ModUtils.moduleProperty(product, "sharedStlFilePath"); var copyCmd = new JavaScriptCommand(); copyCmd.silent = true; copyCmd.stlFilePath = stlFilePath; copyCmd.sourceCode = function() { File.copy(inputs["dynamiclibrary"][0].filePath, outputs["android.nativelibrary"][0].filePath); var destDir = FileInfo.joinPaths("lib", ModUtils.moduleProperty(product, "abi")); if (product.moduleProperty("qbs", "buildVariant") === "debug") { var arch = ModUtils.moduleProperty(product, "abi"); arch = NdkUtils.abiNameToDirName(arch); var srcPath = FileInfo.joinPaths(ModUtils.moduleProperty(product, "ndkDir"), "prebuilt/android-" + arch, "gdbserver/gdbserver"); var targetPath = FileInfo.joinPaths(destDir, ModUtils.moduleProperty(product, "gdbserverFileName")); var infoFile = new TextFile(outputs["android.gdbserver-info"][0].filePath, TextFile.WriteOnly); infoFile.writeLine(srcPath); infoFile.writeLine(targetPath); infoFile.close(); } if (stlFilePath) { var srcPath = stlFilePath; var targetPath = FileInfo.joinPaths(destDir, FileInfo.fileName(srcPath)); var infoFile = new TextFile(outputs["android.stl-info"][0].filePath, TextFile.WriteOnly); infoFile.writeLine(srcPath); infoFile.writeLine(targetPath); infoFile.close(); } } var stripArgs = ["--strip-unneeded", outputs["android.nativelibrary"][0].filePath]; if (stlFilePath) stripArgs.push(stlFilePath); var stripCmd = new Command(product.moduleProperty("cpp", "stripPath"), stripArgs); stripCmd.description = "Stripping unneeded symbols from " + outputs["android.nativelibrary"][0].fileName; return [copyCmd, stripCmd]; } } } qbs-src-1.4.5/share/qbs/modules/Android/ndk/utils.js000066400000000000000000000114301266132464200222710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ function abiNameToDirName(abiName) { if (abiName.startsWith("armeabi")) return "arm"; if (abiName.startsWith("arm64")) return "arm64"; return abiName; } function androidAbi(arch) { if (arch === "x86" || arch === "x86_64") return arch; return { "arm64": "arm64-v8a", "armv5": "armeabi", "armv7": "armeabi-v7a", "mipsel": "mips", "mips64el": "mips64" }[arch]; } function toolchainDir(toolchain, version, abi) { if (toolchain && toolchain.contains("clang")) return "llvm-" + version; if (["x86", "x86_64"].contains(abi)) return abi + "-" + version; return toolchainPrefix(toolchain, abi) + version; } function toolchainPrefix(toolchain, abi) { if (toolchain && toolchain.contains("clang")) return undefined; return { "arm64-v8a": "aarch64-linux-android-", "armeabi": "arm-linux-androideabi-", "armeabi-v7a": "arm-linux-androideabi-", // same prefix as above "mips": "mipsel-linux-android-", "mips64": "mips64el-linux-android-", "x86": "i686-linux-android-", "x86_64": "x86_64-linux-android-" }[abi]; } function commonCompilerFlags(buildVariant, abi, hardFloat, armMode) { var flags = ["-ffunction-sections", "-funwind-tables", "-no-canonical-prefixes", "-Wa,--noexecstack", "-Werror=format-security"]; if (buildVariant === "debug") flags.push("-fno-omit-frame-pointer", "-fno-strict-aliasing"); if (buildVariant === "release") flags.push("-fomit-frame-pointer"); if (abi === "arm64-v8a") { flags.push("-fpic", "-fstack-protector", "-funswitch-loops", "-finline-limit=300"); if (buildVariant === "release") flags.push("-fstrict-aliasing"); } if (abi === "armeabi" || abi === "armeabi-v7a") { flags.push("-fpic", "-fstack-protector", "-finline-limit=64"); if (abi === "armeabi") flags.push("-march=armv5te", "-mtune=xscale", "-msoft-float"); if (abi === "armeabi-v7a") { flags.push("-march=armv7-a", "-mfpu=vfpv3-d16"); flags.push(hardFloat ? "-mhard-float" : "-mfloat-abi=softfp"); } if (buildVariant === "release") flags.push("-fno-strict-aliasing"); } if (abi === "mips" || abi === "mips64") { flags.push("-fpic", "-finline-functions", "-fmessage-length=0", "-fno-inline-functions-called-once", "-fgcse-after-reload", "-frerun-cse-after-loop", "-frename-registers"); if (buildVariant === "release") flags.push("-funswitch-loops", "-finline-limit=300", "-fno-strict-aliasing"); } if (abi === "x86" || abi === "x86_64") { flags.push("-fstack-protector", "-funswitch-loops", "-finline-limit=300"); if (buildVariant === "release") flags.push("-fstrict-aliasing"); } if (armMode) flags.push("-m" + armMode); return flags; } function commonLinkerFlags(abi, hardFloat) { var flags = ["-no-canonical-prefixes", "-Wl,-z,noexecstack", "-Wl,-z,relro", "-Wl,-z,now"]; if (abi === "armeabi-v7a") { flags.push("-march=armv7-a", "-Wl,--fix-cortex-a8"); if (hardFloat) flags.push("-Wl,-no-warn-mismatch"); } return flags; } qbs-src-1.4.5/share/qbs/modules/Android/sdk/000077500000000000000000000000001266132464200206015ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/modules/Android/sdk/sdk.qbs000066400000000000000000000316551266132464200221030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Probes import qbs.TextFile import "utils.js" as SdkUtils Module { Probes.AndroidSdkProbe { id: sdkProbe environmentPaths: [sdkDir].concat(base) } Probes.AndroidNdkProbe { id: ndkProbe environmentPaths: [ndkDir].concat(base) } property path sdkDir: sdkProbe.path property path ndkDir: ndkProbe.path property string buildToolsVersion: sdkProbe.buildToolsVersion property var buildToolsVersionParts: buildToolsVersion ? buildToolsVersion.split('.').map(function(item) { return parseInt(item, 10); }) : [] property int buildToolsVersionMajor: buildToolsVersionParts[0] property int buildToolsVersionMinor: buildToolsVersionParts[1] property int buildToolsVersionPatch: buildToolsVersionParts[2] property string platform: sdkProbe.platform // Internal properties. property int platformVersion: { if (platform) { var match = platform.match(/^android-([0-9]+)$/); if (match !== null) { return parseInt(match[1], 10); } } } property string platformJavaVersion: { if (platformVersion >= 21) return "1.7"; return "1.5"; } property path buildToolsDir: { var path = FileInfo.joinPaths(sdkDir, "build-tools", buildToolsVersion); if (buildToolsVersionMajor >= 23) return FileInfo.joinPaths(path, "bin"); return path; } property path aaptFilePath: FileInfo.joinPaths(buildToolsDir, "aapt") property path aidlFilePath: FileInfo.joinPaths(buildToolsDir, "aidl") property path dxFilePath: FileInfo.joinPaths(buildToolsDir, "dx") property path zipalignFilePath: FileInfo.joinPaths(buildToolsDir, "zipalign") property path androidJarFilePath: FileInfo.joinPaths(sdkDir, "platforms", platform, "android.jar") property path generatedJavaFilesBaseDir: FileInfo.joinPaths(product.buildDirectory, "gen") property path generatedJavaFilesDir: FileInfo.joinPaths(generatedJavaFilesBaseDir, product.packageName.split('.').join('/')) Depends { name: "java" } java.languageVersion: platformJavaVersion java.runtimeVersion: platformJavaVersion java.bootClassPaths: androidJarFilePath // QBS-833 workaround Probes.JdkProbe { id: jdk; environmentPaths: [java.jdkPath].concat(base) } java.jdkPath: jdk.path java.compilerVersion: jdk.version ? jdk.version[1] : undefined FileTagger { patterns: ["AndroidManifest.xml"] fileTags: ["android.manifest"] } FileTagger { patterns: ["*.aidl"] fileTags: ["android.aidl"] } Rule { inputs: ["android.aidl"] Artifact { filePath: FileInfo.joinPaths(qbs.getHash(input.filePath), input.completeBaseName + ".java") fileTags: ["java.java"] } prepare: { var aidl = ModUtils.moduleProperty(product, "aidlFilePath"); cmd = new Command(aidl, [input.filePath, output.filePath]); cmd.description = "Processing " + input.fileName; return [cmd]; } } Rule { multiplex: true inputs: ["android.resources", "android.assets", "android.manifest"] outputFileTags: ["android.ap_", "java.java"] outputArtifacts: { var artifacts = [{ filePath: product.name + ".ap_", fileTags: ["android.ap_"] }]; var resources = inputs["android.resources"]; if (resources && resources.length) { artifacts.push({ filePath: FileInfo.joinPaths( ModUtils.moduleProperty(product, "generatedJavaFilesDir"), "R.java"), fileTags: ["java.java"] }); } return artifacts; } prepare: { var manifestFilePath = inputs["android.manifest"][0].filePath; var args = ["package", "-f", "-m", "--no-crunch", "-M", manifestFilePath, "-I", ModUtils.moduleProperty(product, "androidJarFilePath"), "-F", outputs["android.ap_"][0].filePath, "--generate-dependencies"]; var resources = inputs["android.resources"]; if (resources && resources.length) args.push("-S", product.resourcesDir, "-J", ModUtils.moduleProperty(product, "generatedJavaFilesBaseDir")); if (product.moduleProperty("qbs", "buildVariant") === "debug") args.push("--debug-mode"); if (File.exists(product.assetsDir)) args.push("-A", product.assetsDir); var cmd = new Command(ModUtils.moduleProperty(product, "aaptFilePath"), args); cmd.description = "Processing resources"; return [cmd]; } } Rule { inputs: ["android.manifest"] // FIXME: Workaround for the fact that rules need inputs Artifact { filePath: FileInfo.joinPaths(ModUtils.moduleProperty(product, "generatedJavaFilesDir"), "BuildConfig.java") fileTags: ["java.java"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Generating BuildConfig.java"; cmd.sourceCode = function() { var debugValue = product.moduleProperty("qbs", "buildVariant") === "debug" ? "true" : "false"; var ofile = new TextFile(output.filePath, TextFile.WriteOnly); ofile.writeLine("package " + product.packageName + ";") ofile.writeLine("public final class BuildConfig {"); ofile.writeLine(" public final static boolean DEBUG = " + debugValue + ";"); ofile.writeLine("}"); ofile.close(); }; return [cmd]; } } Rule { multiplex: true inputs: ["java.class"] Artifact { filePath: "classes.dex" fileTags: ["android.dex"] } prepare: { var dxFilePath = ModUtils.moduleProperty(product, "dxFilePath"); var args = ["--dex", "--output", output.filePath, product.moduleProperty("java", "classFilesDir")]; var cmd = new Command(dxFilePath, args); cmd.description = "Creating " + output.fileName; return [cmd]; } } Rule { multiplex: true inputsFromDependencies: [ "android.gdbserver-info", "android.stl-info", "android.nativelibrary" ] outputFileTags: ["android.gdbserver", "android.stl", "android.nativelibrary-deployed"] outputArtifacts: { var libArtifacts = []; if (inputs["android.nativelibrary"]) { for (var i = 0; i < inputs["android.nativelibrary"].length; ++i) { var inp = inputs["android.nativelibrary"][i]; var destDir = FileInfo.joinPaths("lib", inp.moduleProperty("Android.ndk", "abi")); libArtifacts.push({ filePath: FileInfo.joinPaths(destDir, inp.fileName), fileTags: ["android.nativelibrary-deployed"] }); } } var gdbServerArtifacts = SdkUtils.outputArtifactsFromInfoFiles(inputs, product, "android.gdbserver-info", "android.gdbserver"); var stlArtifacts = SdkUtils.outputArtifactsFromInfoFiles(inputs, product, "android.stl-info", "android.deployed-stl"); return libArtifacts.concat(gdbServerArtifacts).concat(stlArtifacts); } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Pre-packaging native binaries"; cmd.sourceCode = function() { if (inputs["android.nativelibrary"]) { for (var i = 0; i < inputs["android.nativelibrary"].length; ++i) { for (var j = 0; j < outputs["android.nativelibrary-deployed"].length; ++j) { var inp = inputs["android.nativelibrary"][i]; var outp = outputs["android.nativelibrary-deployed"][j]; var inpAbi = inp.moduleProperty("Android.ndk", "abi"); var outpAbi = FileInfo.fileName(outp.baseDir); if (inp.fileName === outp.fileName && inpAbi === outpAbi) { File.copy(inp.filePath, outp.filePath); break; } } } } var pathsSpecs = SdkUtils.sourceAndTargetFilePathsFromInfoFiles(inputs, product, "android.gdbserver-info"); for (i = 0; i < pathsSpecs.sourcePaths.length; ++i) File.copy(pathsSpecs.sourcePaths[i], pathsSpecs.targetPaths[i]); pathsSpecs = SdkUtils.sourceAndTargetFilePathsFromInfoFiles(inputs, product, "android.stl-info"); for (i = 0; i < pathsSpecs.sourcePaths.length; ++i) File.copy(pathsSpecs.sourcePaths[i], pathsSpecs.targetPaths[i]); }; return [cmd]; } } // TODO: ApkBuilderMain is deprecated. Do we have to provide our own tool directly // accessing com.android.sdklib.build.ApkBuilder or is there a simpler way? Rule { multiplex: true inputs: [ "android.dex", "android.ap_", "android.gdbserver", "android.stl", "android.nativelibrary-deployed" ] Artifact { filePath: product.name + ".apk.unaligned" fileTags: ["android.apk.unaligned"] } prepare: { var args = ["-classpath", FileInfo.joinPaths(ModUtils.moduleProperty(product, "sdkDir"), "tools/lib/sdklib.jar"), "com.android.sdklib.build.ApkBuilderMain", output.filePath, "-z", inputs["android.ap_"][0].filePath, "-f", inputs["android.dex"][0].filePath]; if (product.moduleProperty("qbs", "buildVariant") === "debug") args.push("-d"); if (inputs["android.nativelibrary-deployed"]) args.push("-nf", FileInfo.joinPaths(product.buildDirectory, "lib")); var cmd = new Command(product.moduleProperty("java", "interpreterFilePath"), args); cmd.description = "Generating " + output.fileName; return [cmd]; } } Rule { multiplex: true inputs: ["android.apk.unaligned"] Artifact { filePath: product.name + ".apk" fileTags: ["android.apk"] } prepare: { var zipalign = ModUtils.moduleProperty(product, "zipalignFilePath"); var args = ["-f", "4", inputs["android.apk.unaligned"][0].filePath, output.filePath]; var cmd = new Command(zipalign, args); cmd.description = "Creating " + output.fileName; return [cmd]; } } } qbs-src-1.4.5/share/qbs/modules/Android/sdk/utils.js000066400000000000000000000052511266132464200223020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = loadExtension("qbs.FileInfo"); var TextFile = loadExtension("qbs.TextFile"); function sourceAndTargetFilePathsFromInfoFiles(inputs, product, inputTag) { var sourceFilePaths = []; var targetFilePaths = []; var inputsLength = inputs[inputTag] ? inputs[inputTag].length : 0; for (var i = 0; i < inputsLength; ++i) { var infoFile = new TextFile(inputs[inputTag][i].filePath, TextFile.ReadOnly); var sourceFilePath = infoFile.readLine(); var targetFilePath = FileInfo.joinPaths(product.buildDirectory, infoFile.readLine()); if (!targetFilePaths.contains(targetFilePath)) { sourceFilePaths.push(sourceFilePath); targetFilePaths.push(targetFilePath); } infoFile.close(); } return { sourcePaths: sourceFilePaths, targetPaths: targetFilePaths }; } function outputArtifactsFromInfoFiles(inputs, product, inputTag, outputTag) { var pathSpecs = sourceAndTargetFilePathsFromInfoFiles(inputs, product, inputTag) var artifacts = []; for (i = 0; i < pathSpecs.targetPaths.length; ++i) artifacts.push({filePath: pathSpecs.targetPaths[i], fileTags: [outputTag]}); return artifacts; } qbs-src-1.4.5/share/qbs/modules/archiver/000077500000000000000000000000001266132464200202435ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/modules/archiver/archiver.qbs000066400000000000000000000175511266132464200225660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.File import qbs.FileInfo import qbs.Probes Module { // jar is a suitable fallback for creating zip files as they are the same format // This will most likely end up being used on Windows Depends { name: "java"; required: false } // QBS-833 workaround Probes.JdkProbe { id: jdk; environmentPaths: [java.jdkPath].concat(base) } java.jdkPath: jdk.path java.compilerVersion: jdk.version ? jdk.version[1] : undefined Probes.BinaryProbe { id: zipProbe names: ["zip"] } property string type property string archiveBaseName: product.targetName property string workingDirectory property stringList flags: [] property path outputDirectory: product.destinationDirectory property string archiveExtension: { if (type === "7zip") return "7z"; if (type == "tar") { var extension = "tar"; if (compressionType !== "none") extension += "." + compressionType; return extension; } if (type === "zip") return "zip"; return undefined; } property string command: { if (type === "7zip") return "7z"; if (type === "tar") return "tar"; if (type === "zip") { // Prefer zip (probably Info-Zip) and fall back to jar when it's not available // (as is the likely case on Windows) if (zipProbe.found) return zipProbe.filePath; if (java.present) return java.jarFilePath; } return undefined; } property string compressionLevel property string compressionType: { if (type === "tar") return "gz"; return undefined; } PropertyOptions { name: "type" description: "The type of archive to create." allowedValues: ["7zip", "tar", "zip"] } PropertyOptions { name: "compressionLevel" description: "How much effort to put into compression.\n" + "Higher numbers mean smaller archive files at the cost of taking more time.\n" + "This property is only used for the '7zip' and 'zip' types.\n" + "'7zip' only supports 0 and odd numbers." allowedValues: [undefined, "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] } PropertyOptions { name: "compressionType" description: "The compression format to use.\n" + "For tar archives, the respective tool needs to be present.\n" + "This property is only used for the 'tar' and 'zip' types." allowedValues: ["none", "gz", "bz2", "Z", "xz", "deflate", "store"] } Rule { inputs: ["archiver.input-list"] Artifact { filePath: FileInfo.joinPaths(product.moduleProperty("archiver", "outputDirectory"), product.moduleProperty("archiver", "archiveBaseName") + '.' + product.moduleProperty("archiver", "archiveExtension")); fileTags: ["archiver.archive"] } prepare: { var binary = product.moduleProperty("archiver", "command"); var args = []; var commands = []; var type = product.moduleProperty("archiver", "type"); var compression = product.moduleProperty("archiver", "compressionType"); var compressionLevel = product.moduleProperty("archiver", "compressionLevel"); if (type === "7zip") { var rmCommand = new JavaScriptCommand(); rmCommand.silent = true; rmCommand.sourceCode = function() { if (File.exists(output.filePath)) File.remove(output.filePath); }; commands.push(rmCommand); args.push("a", "-y", "-mmt=on"); if (compressionLevel) args.push("-mx" + compressionLevel); args = args.concat(product.moduleProperty("archiver", "flags")); args.push(output.filePath); args.push("@" + input.filePath); } else if (type === "tar") { args.push("-c"); if (compression === "gz") args.push("-z"); else if (compression === "bz2") args.push("-j"); else if (compression === "Z") args.push("-Z"); else if (compression === "xz") args.push("-J"); args.push("-f", output.filePath, "-T", input.filePath); args = args.concat(product.moduleProperty("archiver", "flags")); } else if (type === "zip") { var binaryName = FileInfo.baseName(binary); if (binaryName === "jar") { if (compression === "none" || compressionLevel === "0") args.push("-0"); args.push("-cfM", output.filePath, "@" + input.filePath); } else if (binaryName === "zip") { // The "zip" program included with most Linux and Unix distributions // (including OS X) is Info-ZIP's Zip, so this should be fairly portable. if (compression === "none") { args.push("-0"); } else { compression = compression === "bz2" ? "bzip2" : compression; if (["store", "deflate", "bzip2"].contains(compression)) args.push("-Z", compression); if (compressionLevel) args.push("-" + compressionLevel); } args.push("-r", output.filePath, ".", "-i@" + input.filePath); } else { throw "Unknown zip tool '" + binaryName + "'"; } args = args.concat(product.moduleProperty("archiver", "flags")); } var archiverCommand = new Command(binary, args); archiverCommand.description = "Creating archive file " + output.fileName; archiverCommand.highlight = "linker"; archiverCommand.workingDirectory = product.moduleProperty("archiver", "workingDirectory"); commands.push(archiverCommand); return commands; } } } qbs-src-1.4.5/share/qbs/modules/bundle/000077500000000000000000000000001266132464200177115ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/modules/bundle/BundleModule.qbs000066400000000000000000000720111266132464200230000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.BundleTools import qbs.DarwinTools import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.PropertyList import qbs.TextFile Module { additionalProductTypes: ["bundle"] property bool isBundle: qbs.targetOS.contains("darwin") && (product.type.contains("application") || product.type.contains("dynamiclibrary") || product.type.contains("loadablemodule")) && !product.consoleApplication property bool isShallow: qbs.targetOS.contains("ios") && product.type.contains("application") property string identifierPrefix: "org.example" property string identifier: [identifierPrefix, qbs.rfc1034Identifier(product.targetName)].join(".") property string extension: { if (packageType === undefined) { return ""; } else if (packageType === "APPL") { return "app"; } else if (packageType === "XPC!") { if (product.type.contains("applicationextension")) return "appex"; return "xpc"; } else if (packageType === "FMWK") { return "framework"; } else{ return "bundle"; } // Also: kext, prefPane, qlgenerator, saver, mdimporter, or a custom extension } property string packageType: { if (product.type.contains("inapppurchase")) return undefined; if (product.type.contains("xpcservice")) return "XPC!"; if (product.type.contains("application")) return "APPL"; if (product.type.contains("dynamiclibrary") || product.type.contains("staticlibrary")) return "FMWK"; return "BNDL"; } property string signature: "????" // legacy creator code in Mac OS Classic (CFBundleSignature), can be ignored property string bundleName: product.targetName + (extension ? ("." + extension) : "") property string frameworkVersion: { if (packageType === "FMWK") { var n = parseInt(product.version, 10); return isNaN(n) ? 'A' : String(n); } } property pathList publicHeaders property pathList privateHeaders property pathList resources property path infoPlistFile property var infoPlist property bool processInfoPlist: true property bool embedInfoPlist: product.type.contains("application") && !isBundle property string infoPlistFormat: { if (qbs.targetOS.contains("osx")) return infoPlistFile ? "same-as-input" : "xml1"; else if (qbs.targetOS.contains("ios")) return "binary1"; } property string localizedResourcesFolderSuffix: ".lproj" property string lsregisterName: "lsregister" property string lsregisterPath: FileInfo.joinPaths( "/System/Library/Frameworks/CoreServices.framework" + "/Versions/A/Frameworks/LaunchServices.framework" + "/Versions/A/Support", lsregisterName); // all paths are relative to the directory containing the bundle readonly property string infoPlistPath: { var path; if (!isBundle) path = FileInfo.joinPaths(".tmp", product.name); else if (packageType === "FMWK") path = unlocalizedResourcesFolderPath; else if (product.type.contains("inapppurchase")) path = bundleName; else path = contentsFolderPath; return FileInfo.joinPaths(path, product.type.contains("inapppurchase") ? "ContentInfo.plist" : "Info.plist"); } readonly property string pkgInfoPath: FileInfo.joinPaths(packageType === "FMWK" ? bundleName : contentsFolderPath, "PkgInfo") readonly property string versionPlistPath: FileInfo.joinPaths(packageType === "FMWK" ? unlocalizedResourcesFolderPath : contentsFolderPath, "version.plist") readonly property string executablePath: FileInfo.joinPaths(executableFolderPath, product.targetName) readonly property string executableFolderPath: (!isShallow && packageType !== "FMWK" && !isShallowContents) ? FileInfo.joinPaths(contentsFolderPath, "MacOS") : contentsFolderPath readonly property string executablesFolderPath: packageType === "FMWK" ? unlocalizedResourcesFolderPath : FileInfo.joinPaths(contentsFolderPath, !isShallowContents ? "Executables" : "") readonly property string frameworksFolderPath: FileInfo.joinPaths(contentsFolderPath, !isShallowContents ? "Frameworks" : "") readonly property string pluginsFolderPath: packageType === "FMWK" ? unlocalizedResourcesFolderPath : FileInfo.joinPaths(contentsFolderPath, !isShallowContents ? "PlugIns" : "") readonly property string privateHeadersFolderPath: FileInfo.joinPaths(contentsFolderPath, !isShallowContents ? "PrivateHeaders" : "") readonly property string publicHeadersFolderPath: FileInfo.joinPaths(contentsFolderPath, !isShallowContents ? "Headers" : "") readonly property string scriptsFolderPath: FileInfo.joinPaths(unlocalizedResourcesFolderPath, "Scripts") readonly property string sharedFrameworksFolderPath: FileInfo.joinPaths(contentsFolderPath, !isShallowContents ? "SharedFrameworks" : "") readonly property string sharedSupportFolderPath: packageType === "FMWK" ? unlocalizedResourcesFolderPath : FileInfo.joinPaths(contentsFolderPath, !isShallowContents ? "SharedSupport" : "") readonly property string unlocalizedResourcesFolderPath: isShallow ? contentsFolderPath : FileInfo.joinPaths(contentsFolderPath, !isShallowContents ? "Resources" : "") readonly property string contentsFolderPath: { if (packageType === "FMWK") return FileInfo.joinPaths(bundleName, "Versions", frameworkVersion); else if (!isShallow) return FileInfo.joinPaths(bundleName, "Contents"); return bundleName; } // private properties readonly property bool isShallowContents: product.type.contains("inapppurchase") readonly property var qmakeEnv: { return { "BUNDLEIDENTIFIER": identifier, "EXECUTABLE": product.targetName, "FULL_VERSION": product.version || "1.0", // CFBundleVersion "ICON": product.targetName, // ### QBS-73 "LIBRARY": product.targetName, "SHORT_VERSION": product.version || "1.0", // CFBundleShortVersionString "TYPEINFO": signature // CFBundleSignature }; } readonly property var defaultInfoPlist: { return { CFBundleDevelopmentRegion: "en", // default localization CFBundleDisplayName: product.targetName, // localizable CFBundleExecutable: product.targetName, CFBundleIdentifier: identifier, CFBundleInfoDictionaryVersion: "6.0", CFBundleName: product.targetName, // short display name of the bundle, localizable CFBundlePackageType: packageType, CFBundleShortVersionString: product.version || "1.0", // "release" version number, localizable CFBundleSignature: signature, // legacy creator code in Mac OS Classic, can be ignored CFBundleVersion: product.version || "1.0.0" // build version number, must be 3 octets }; } Rule { condition: qbs.targetOS.contains("darwin") multiplex: true inputs: ["qbs", "partial_infoplist"] outputFileTags: ["infoplist"] outputArtifacts: { var artifacts = []; if (ModUtils.moduleProperty(product, "isBundle") || ModUtils.moduleProperty(product, "embedInfoPlist")) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "infoPlistPath")), fileTags: ["infoplist"] }); } return artifacts; } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating Info.plist for " + product.name; cmd.highlight = "codegen"; cmd.partialInfoPlistFiles = inputs.partial_infoplist; cmd.infoPlistFile = ModUtils.moduleProperty(product, "infoPlistFile"); cmd.infoPlist = ModUtils.moduleProperty(product, "infoPlist") || {}; cmd.processInfoPlist = ModUtils.moduleProperty(product, "processInfoPlist"); cmd.infoPlistFormat = ModUtils.moduleProperty(product, "infoPlistFormat"); cmd.qmakeEnv = ModUtils.moduleProperty(product, "qmakeEnv"); cmd.platformPath = product.moduleProperty("cpp", "platformPath"); cmd.toolchainInstallPath = product.moduleProperty("cpp", "toolchainInstallPath"); cmd.buildEnv = product.moduleProperty("cpp", "buildEnv"); cmd.defines = product.moduleProperty("cpp", "defines"); cmd.platformDefines = product.moduleProperty("cpp", "platformDefines"); cmd.compilerDefines = product.moduleProperty("cpp", "compilerDefines"); cmd.allDefines = [].concat(cmd.defines || []).concat(cmd.platformDefines || []).concat(cmd.compilerDefines || []); cmd.platformInfoPlist = product.moduleProperty("cpp", "platformInfoPlist"); cmd.sdkSettingsPlist = product.moduleProperty("cpp", "sdkSettingsPlist"); cmd.toolchainInfoPlist = product.moduleProperty("cpp", "toolchainInfoPlist"); cmd.sysroot = product.moduleProperty("qbs", "sysroot"); cmd.osBuildVersion = product.moduleProperty("qbs", "hostOSBuildVersion"); cmd.sourceCode = function() { var plist, process, key, i; // Contains the combination of default, file, and in-source keys and values // Start out with the contents of this file as the "base", if given var aggregatePlist = BundleTools.infoPlistContents(infoPlistFile) || {}; // Add local key-value pairs (overrides equivalent keys specified in the file if // one was given) for (key in infoPlist) { if (infoPlist.hasOwnProperty(key)) aggregatePlist[key] = infoPlist[key]; } // Do some postprocessing if desired if (processInfoPlist) { // Add default values to the aggregate plist if the corresponding keys // for those values are not already present var defaultValues = ModUtils.moduleProperty(product, "defaultInfoPlist"); for (key in defaultValues) { if (defaultValues.hasOwnProperty(key) && !(key in aggregatePlist)) aggregatePlist[key] = defaultValues[key]; } var defaultValues = product.moduleProperty("cpp", "defaultInfoPlist"); for (key in defaultValues) { if (defaultValues.hasOwnProperty(key) && !(key in aggregatePlist)) aggregatePlist[key] = defaultValues[key]; } // Add keys from platform's Info.plist if not already present var platformInfo = {}; if (platformPath) { if (File.exists(platformInfoPlist)) { plist = new PropertyList(); try { plist.readFromFile(platformInfoPlist); platformInfo = plist.toObject(); } finally { plist.clear(); } var additionalProps = platformInfo["AdditionalInfo"]; for (key in additionalProps) { if (additionalProps.hasOwnProperty(key) && !(key in aggregatePlist)) // override infoPlist? aggregatePlist[key] = defaultValues[key]; } props = platformInfo['OverrideProperties']; for (key in props) { aggregatePlist[key] = props[key]; } if (product.moduleProperty("qbs", "targetOS").contains("ios")) { key = "UIDeviceFamily"; if (key in platformInfo && !(key in aggregatePlist)) aggregatePlist[key] = platformInfo[key]; } } else { print("warning: platform path given but no platform Info.plist found"); } } else { print("no platform path specified"); } var sdkSettings = {}; if (sysroot) { if (File.exists(sdkSettingsPlist)) { plist = new PropertyList(); try { plist.readFromFile(sdkSettingsPlist); sdkSettings = plist.toObject(); } finally { plist.clear(); } } else { print("warning: sysroot (SDK path) given but no SDKSettings.plist found"); } } else { print("no sysroot (SDK path) specified"); } var toolchainInfo = {}; if (toolchainInstallPath && File.exists(toolchainInfoPlist)) { plist = new PropertyList(); try { plist.readFromFile(toolchainInfoPlist); toolchainInfo = plist.toObject(); } finally { plist.clear(); } } else { print("could not find a ToolchainInfo.plist near the toolchain install path"); } aggregatePlist["BuildMachineOSBuild"] = osBuildVersion; // setup env env = { "SDK_NAME": sdkSettings["CanonicalName"], "XCODE_VERSION_ACTUAL": toolchainInfo["DTXcode"], "SDK_PRODUCT_BUILD_VERSION": toolchainInfo["DTPlatformBuild"], "GCC_VERSION": platformInfo["DTCompiler"], "XCODE_PRODUCT_BUILD_VERSION": platformInfo["DTPlatformBuild"], "PLATFORM_PRODUCT_BUILD_VERSION": platformInfo["ProductBuildVersion"], } env["MAC_OS_X_PRODUCT_BUILD_VERSION"] = osBuildVersion; for (key in buildEnv) env[key] = buildEnv[key]; for (key in qmakeEnv) env[key] = qmakeEnv[key]; for (i = 0; i < allDefines.length; ++i) { var parts = allDefines[i].split('='); env[parts[0]] = parts[1]; } DarwinTools.expandPlistEnvironmentVariables(aggregatePlist, env, true); // Add keys from partial Info.plists from asset catalogs, XIBs, and storyboards for (i in partialInfoPlistFiles) { var partialInfoPlist = BundleTools.infoPlistContents(partialInfoPlistFiles[i].filePath) || {}; for (key in partialInfoPlist) { if (partialInfoPlist.hasOwnProperty(key)) aggregatePlist[key] = partialInfoPlist[key]; } } } // Anything with an undefined or otherwise empty value should be removed // Only JSON-formatted plists can have null values, other formats error out // This also follows Xcode behavior DarwinTools.cleanPropertyList(aggregatePlist); if (infoPlistFormat === "same-as-input" && infoPlistFile) infoPlistFormat = BundleTools.infoPlistFormat(infoPlistFile); var validFormats = [ "xml1", "binary1", "json" ]; if (!validFormats.contains(infoPlistFormat)) throw("Invalid Info.plist format " + infoPlistFormat + ". " + "Must be in [xml1, binary1, json]."); // Write the plist contents in the format appropriate for the current platform plist = new PropertyList(); try { plist.readFromObject(aggregatePlist); plist.writeToFile(outputs.infoplist[0].filePath, infoPlistFormat); } finally { plist.clear(); } } return cmd; } } Rule { condition: qbs.targetOS.contains("darwin") multiplex: true inputs: ["infoplist"] outputFileTags: ["pkginfo"] outputArtifacts: { var artifacts = []; if (ModUtils.moduleProperty(product, "isBundle")) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "pkgInfoPath")), fileTags: ["pkginfo"] }); } return artifacts; } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating PkgInfo for " + product.name; cmd.highlight = "codegen"; cmd.sourceCode = function() { var infoPlist = BundleTools.infoPlistContents(inputs.infoplist[0].filePath); var pkgType = infoPlist['CFBundlePackageType']; if (!pkgType) throw("CFBundlePackageType not found in Info.plist; this should not happen"); var pkgSign = infoPlist['CFBundleSignature']; if (!pkgSign) throw("CFBundleSignature not found in Info.plist; this should not happen"); var pkginfo = new TextFile(outputs.pkginfo[0].filePath, TextFile.WriteOnly); pkginfo.write(pkgType + pkgSign); pkginfo.close(); } return cmd; } } Rule { condition: qbs.targetOS.contains("darwin") multiplex: true inputs: ["infoplist", "pkginfo", "hpp", "icns", "resourcerules", "ipa", "compiled_nib", "compiled_storyboard", "compiled_assetcatalog"] outputFileTags: ["bundle", "bundle.symlink.headers", "bundle.symlink.private-headers", "bundle.symlink.resources", "bundle.symlink.executable", "bundle.symlink.version", "bundle.hpp", "bundle.resource"] outputArtifacts: { var i, artifacts = []; if (ModUtils.moduleProperty(product, "isBundle")) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName")), fileTags: ["bundle"] }); var packageType = ModUtils.moduleProperty(product, "packageType"); if (packageType === "FMWK") { var publicHeaders = ModUtils.moduleProperties(product, "publicHeaders"); if (publicHeaders && publicHeaders.length) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), "Headers"), fileTags: ["bundle.symlink.headers"] }); } var privateHeaders = ModUtils.moduleProperties(product, "privateHeaders"); if (privateHeaders && privateHeaders.length) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), "PrivateHeaders"), fileTags: ["bundle.symlink.private-headers"] }); } artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), "Resources"), fileTags: ["bundle.symlink.resources"] }); artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), product.targetName), fileTags: ["bundle.symlink.executable"] }); artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), "Versions", "Current"), fileTags: ["bundle.symlink.version"] }); } var headerTypes = ["public", "private"]; for (var h in headerTypes) { var sources = ModUtils.moduleProperties(product, headerTypes[h] + "Headers"); var destination = FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, headerTypes[h] + "HeadersFolderPath")); for (i in sources) { artifacts.push({ filePath: FileInfo.joinPaths(destination, FileInfo.fileName(sources[i])), fileTags: ["bundle.hpp"] }); } } sources = ModUtils.moduleProperties(product, "resources"); for (i in sources) { destination = BundleTools.destinationDirectoryForResource(product, {baseDir: FileInfo.path(sources[i]), fileName: FileInfo.fileName(sources[i])}); artifacts.push({ filePath: FileInfo.joinPaths(destination, FileInfo.fileName(sources[i])), fileTags: ["bundle.resource"] }); } } return artifacts; } prepare: { var i, cmd, commands = []; var packageType = ModUtils.moduleProperty(product, "packageType"); var bundleType = "bundle"; if (packageType === "APPL") bundleType = "application"; if (packageType === "FMWK") bundleType = "framework"; var bundles = outputs.bundle; for (i in bundles) { cmd = new Command("mkdir", ["-p", bundles[i].filePath]); cmd.description = "creating " + bundleType + " " + product.targetName; commands.push(cmd); cmd = new Command("touch", ["-c", bundles[i].filePath]); cmd.silent = true; commands.push(cmd); } // Product is unbundled if (commands.length === 0) { cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function () { }; commands.push(cmd); } var symlinks = outputs["bundle.symlink.version"]; for (i in symlinks) { cmd = new Command("ln", ["-sfn", ModUtils.moduleProperty(product, "frameworkVersion"), symlinks[i].filePath]); cmd.silent = true; commands.push(cmd); } var publicHeaders = outputs["bundle.symlink.headers"]; for (i in publicHeaders) { cmd = new Command("ln", ["-sfn", "Versions/Current/Headers", publicHeaders[i].filePath]); cmd.silent = true; commands.push(cmd); } var privateHeaders = outputs["bundle.symlink.private-headers"]; for (i in privateHeaders) { cmd = new Command("ln", ["-sfn", "Versions/Current/PrivateHeaders", privateHeaders[i].filePath]); cmd.silent = true; commands.push(cmd); } var resources = outputs["bundle.symlink.resources"]; for (i in resources) { cmd = new Command("ln", ["-sfn", "Versions/Current/Resources", resources[i].filePath]); cmd.silent = true; commands.push(cmd); } var executables = outputs["bundle.symlink.executable"]; for (i in executables) { cmd = new Command("ln", ["-sf", FileInfo.joinPaths("Versions", "Current", product.targetName), executables[i].filePath]); cmd.silent = true; commands.push(cmd); } cmd = new JavaScriptCommand(); cmd.description = "copying public headers"; cmd.highlight = "filegen"; cmd.sources = ModUtils.moduleProperties(product, "publicHeaders"); cmd.destination = FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "publicHeadersFolderPath")); cmd.sourceCode = function() { var i; for (var i in sources) { File.copy(sources[i], FileInfo.joinPaths(destination, FileInfo.fileName(sources[i]))); } }; if (cmd.sources && cmd.sources.length) commands.push(cmd); cmd = new JavaScriptCommand(); cmd.description = "copying private headers"; cmd.highlight = "filegen"; cmd.sources = ModUtils.moduleProperties(product, "privateHeaders"); cmd.destination = FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "privateHeadersFolderPath")); cmd.sourceCode = function() { var i; for (var i in sources) { File.copy(sources[i], FileInfo.joinPaths(destination, FileInfo.fileName(sources[i]))); } }; if (cmd.sources && cmd.sources.length) commands.push(cmd); cmd = new JavaScriptCommand(); cmd.description = "copying resources"; cmd.highlight = "filegen"; cmd.sources = ModUtils.moduleProperties(product, "resources"); cmd.sourceCode = function() { var i; for (var i in sources) { var destination = BundleTools.destinationDirectoryForResource(product, {baseDir: FileInfo.path(sources[i]), fileName: FileInfo.fileName(sources[i])}); File.copy(sources[i], FileInfo.joinPaths(destination, FileInfo.fileName(sources[i]))); } }; if (cmd.sources && cmd.sources.length) commands.push(cmd); if (product.type.contains("application") && product.moduleProperty("qbs", "hostOS").contains("darwin")) { for (i in bundles) { cmd = new Command(ModUtils.moduleProperty(product, "lsregisterPath"), ["-f", bundles[i].filePath]); cmd.description = "register " + ModUtils.moduleProperty(product, "bundleName"); commands.push(cmd); } } return commands; } } } qbs-src-1.4.5/share/qbs/modules/cpp/000077500000000000000000000000001266132464200172225ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/modules/cpp/CppModule.qbs000066400000000000000000000266461266132464200216370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ // base for Cpp modules import qbs.ModUtils Module { condition: false property int compilerVersionMajor property int compilerVersionMinor property int compilerVersionPatch property string warningLevel : 'all' // 'none', 'all' property bool treatWarningsAsErrors : false property string architecture: qbs.architecture property string optimization: qbs.optimization property bool debugInformation: qbs.debugInformation property bool separateDebugInformation: false property pathList prefixHeaders property path precompiledHeader property path cPrecompiledHeader: precompiledHeader property path cxxPrecompiledHeader: precompiledHeader // ### default to undefined on non-Apple platforms for now - QBS-346 property path objcPrecompiledHeader: qbs.targetOS.contains("darwin") ? precompiledHeader : undefined property path objcxxPrecompiledHeader: qbs.targetOS.contains("darwin") ? precompiledHeader : undefined property path precompiledHeaderDir: product.buildDirectory property stringList defines property stringList platformDefines: qbs.enableDebugCode ? [] : ["NDEBUG"] property stringList compilerDefines PropertyOptions { name: "compilerDefines" description: "preprocessor macros that are defined when using this particular compiler" } property string windowsApiCharacterSet property string minimumWindowsVersion PropertyOptions { name: "minimumWindowsVersion" description: "A version number in the format [major].[minor] indicating the earliest \ version of Windows that the product should run on. Defines WINVER, \ _WIN32_WINNT, and _WIN32_WINDOWS, and applies a version number to the \ linker flags /SUBSYSTEM and /OSVERSION for MSVC or \ -Wl,--major-subsystem-version, -Wl,--minor-subsystem-version, \ -Wl,--major-os-version and -Wl,--minor-os-version for MinGW. \ If undefined, compiler defaults will be used." } property string minimumOsxVersion PropertyOptions { name: "minimumOsxVersion" description: "a version number in the format [major].[minor] indicating the earliest \ version of OS X that the product should run on. passes -mmacosx-version-min= \ to the compiler. if undefined, compiler defaults will be used." } property string minimumIosVersion PropertyOptions { name: "minimumIosVersion" description: "a version number in the format [major].[minor] indicating the earliest \ version of iOS that the product should run on. passes -miphoneos-version-min= \ to the compiler. if undefined, compiler defaults will be used." } property string minimumAndroidVersion PropertyOptions { name: "minimumAndroidVersion" description: "a version number in the format [major].[minor] indicating the earliest \ version of Android that the product should run on. this value is converted into an SDK \ version which is then written to AndroidManifest.xml." } property string maximumAndroidVersion PropertyOptions { name: "maximumAndroidVersion" description: "a version number in the format [major].[minor] indicating the latest \ version of Android that the product should run on. this value is converted into an SDK \ version which is then written to AndroidManifest.xml. if undefined, no upper limit will \ be set." } property string installNamePrefix PropertyOptions { name: "installNamePrefix" description: "The prefix for the internal install name (LC_ID_DYLIB) of a dynamic library \ on Darwin (OS X and iOS)." } property pathList includePaths property pathList systemIncludePaths property pathList libraryPaths property pathList frameworkPaths property pathList systemFrameworkPaths property pathList linkerScripts property string compilerName property string compilerPath: compilerName property var compilerPathByLanguage property stringList compilerWrapper property string linkerName property string linkerPath: linkerName property string staticLibraryPrefix property string dynamicLibraryPrefix property string loadableModulePrefix property string executablePrefix property string staticLibrarySuffix property string dynamicLibrarySuffix property string loadableModuleSuffix property string executableSuffix property string debugInfoSuffix property bool createSymlinks: true property stringList dynamicLibraries // list of names, will be linked with -lname property stringList staticLibraries // list of static library files property stringList frameworks // list of frameworks, will be linked with '-framework ' property stringList weakFrameworks // list of weakly-linked frameworks, will be linked with '-weak_framework ' property stringList rpaths property bool useRPaths: true property stringList cppFlags PropertyOptions { name: "cppFlags" description: "additional flags for the C preprocessor" } property stringList cFlags PropertyOptions { name: "cFlags" description: "additional flags for the C compiler" } property stringList cxxFlags PropertyOptions { name: "cxxFlags" description: "additional flags for the C++ compiler" } property stringList objcFlags PropertyOptions { name: "objcFlags" description: "additional flags for the Objective-C compiler" } property stringList objcxxFlags PropertyOptions { name: "objcxxFlags" description: "additional flags for the Objective-C++ compiler" } property stringList commonCompilerFlags PropertyOptions { name: "commonCompilerFlags" description: "flags added to all compilation independently of the language" } property stringList linkerFlags PropertyOptions { name: "linkerFlags" description: "additional linker flags" } property bool positionIndependentCode PropertyOptions { name: "positionIndependentCode" description: "generate position independent code" } property string entryPoint PropertyOptions { name: "entryPoint" description: "entry point symbol for an executable or dynamic library" } property string runtimeLibrary PropertyOptions { name: "runtimeLibrary" description: "determine which runtime library to use" allowedValues: ['static', 'dynamic'] } property string visibility: 'default' PropertyOptions { name: "visibility" description: "export symbols visibility level" allowedValues: ['default', 'hidden', 'hiddenInlines', 'minimal'] } property string cLanguageVersion PropertyOptions { name: "cLanguageVersion" allowedValues: ["c89", "c99", "c11"] description: "The version of the C standard with which the code must comply." } property string cxxLanguageVersion PropertyOptions { name: "cxxLanguageVersion" allowedValues: ["c++98", "c++11", "c++14"] description: "The version of the C++ standard with which the code must comply." } property string cxxStandardLibrary PropertyOptions { name: "cxxStandardLibrary" allowedValues: ["libstdc++", "libc++"] description: "version of the C++ standard library to use" } // Platform properties. Those are intended to be set by the toolchain setup // and are prepended to the corresponding user properties. property stringList platformCommonCompilerFlags property stringList platformCFlags property stringList platformCxxFlags property stringList platformObjcFlags property stringList platformObjcxxFlags property stringList platformLinkerFlags // OS X and iOS properties property bool buildIpa: !qbs.targetOS.contains('ios-simulator') property string signingIdentity property path provisioningProfile property string xcodeSdkName property string xcodeSdkVersion property bool automaticReferenceCounting PropertyOptions { name: "automaticReferenceCounting" description: "whether to enable Automatic Reference Counting (ARC) for Objective-C" } property bool requireAppExtensionSafeApi PropertyOptions { name: "requireAppExtensionSafeApi" description: "whether to require app-extension-safe APIs only" } property bool allowUnresolvedSymbols: false FileTagger { patterns: ["*.c"] fileTags: ["c"] } FileTagger { patterns: ["*.C", "*.cpp", "*.cxx", "*.c++", "*.cc"] fileTags: ["cpp"] } FileTagger { patterns: ["*.m"] fileTags: ["objc"] } FileTagger { patterns: ["*.mm"] fileTags: ["objcpp"] } FileTagger { patterns: ["*.h", "*.H", "*.hpp", "*.hxx", "*.h++"] fileTags: ["hpp"] } validate: { var validator = new ModUtils.PropertyValidator("cpp"); validator.addCustomValidator("architecture", architecture, function (value) { return !architecture || architecture === canonicalArchitecture(architecture); }, "'" + architecture + "' is invalid. You must use the canonical name '" + canonicalArchitecture(architecture) + "'"); validator.validate(); } setupRunEnvironment: { var env = qbs.commonRunEnvironment; for (var i in env) { var v = new ModUtils.EnvironmentVariable(i, qbs.pathListSeparator, qbs.hostOS.contains("windows")); v.value = env[i]; v.set(); } } } qbs-src-1.4.5/share/qbs/modules/cpp/DarwinGCC.qbs000066400000000000000000000112461266132464200214760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.ModUtils UnixGCC { condition: false compilerDefines: ["__GNUC__=4", "__APPLE__"] loadableModulePrefix: "" loadableModuleSuffix: ".bundle" dynamicLibrarySuffix: ".dylib" separateDebugInformation: true debugInfoSuffix: ".dSYM" validate: { if (qbs.sysroot) { var validator = new ModUtils.PropertyValidator("cpp"); validator.setRequiredProperty("xcodeSdkName", xcodeSdkName); validator.setRequiredProperty("xcodeSdkVersion", xcodeSdkVersion); validator.validate(); } } setupBuildEnvironment: { var v = new ModUtils.EnvironmentVariable("PATH", ":", false); if (platformPath) { v.prepend(platformPath + "/Developer/usr/bin"); var platformPathL = platformPath.split("/"); platformPathL.pop(); platformPathL.pop(); var devPath = platformPathL.join("/") v.prepend(devPath + "/usr/bin"); v.set(); } for (var key in buildEnv) { v = new ModUtils.EnvironmentVariable(key); v.value = buildEnv[key]; v.set(); } } property var defaultInfoPlist: { var dict = {}; if (qbs.targetOS.contains("osx")) { dict["NSPrincipalClass"] = "NSApplication"; // needed for Retina display support if (minimumOsxVersion) dict["LSMinimumSystemVersion"] = minimumOsxVersion; } if (qbs.targetOS.contains("ios")) { dict["LSRequiresIPhoneOS"] = true; // architectures supported, to support iPhone 3G for example one has to add // armv6 to the list and also compile for it (with Xcode 4.4.1 or earlier) if (!qbs.targetOS.contains("ios-simulator")) dict["UIRequiredDeviceCapabilities"] = [ "armv7" ]; var orientations = [ "UIInterfaceOrientationPortrait", "UIInterfaceOrientationLandscapeLeft", "UIInterfaceOrientationLandscapeRight" ]; dict["UISupportedInterfaceOrientations"] = orientations; orientations.splice(1, 0, "UIInterfaceOrientationPortraitUpsideDown"); dict["UISupportedInterfaceOrientations~ipad"] = orientations; } return dict; } // private properties readonly property var buildEnv: { var env = { "EXECUTABLE_NAME": product.targetName, "LANG": "en_US.US-ASCII", "PRODUCT_NAME": product.name } if (qbs.targetOS.contains("ios") && minimumIosVersion) env["IPHONEOS_DEPLOYMENT_TARGET"] = minimumIosVersion; if (qbs.targetOS.contains("osx") && minimumOsxVersion) env["MACOSX_DEPLOYMENT_TARGET"] = minimumOsxVersion; return env; } readonly property path platformInfoPlist: platformPath ? [platformPath, "Info.plist"].join("/") : undefined readonly property path sdkSettingsPlist: sysroot ? [sysroot, "SDKSettings.plist"].join("/") : undefined readonly property path toolchainInfoPlist: toolchainInstallPath ? [toolchainInstallPath, "../../ToolchainInfo.plist"].join("/") : undefined } qbs-src-1.4.5/share/qbs/modules/cpp/GenericGCC.qbs000066400000000000000000000336111266132464200216260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs 1.0 import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.PathTools import qbs.Process import qbs.UnixUtils import qbs.WindowsUtils import 'gcc.js' as Gcc CppModule { condition: false cxxStandardLibrary: { if (cxxLanguageVersion && qbs.toolchain.contains("clang")) { return cxxLanguageVersion !== "c++98" ? "libc++" : "libstdc++"; } } property stringList transitiveSOs property string toolchainPrefix property path toolchainInstallPath compilerName: cxxCompilerName linkerName: cxxCompilerName property string archiverName: 'ar' property string nmName: 'nm' property string objcopyName: "objcopy" property string stripName: "strip" property string dsymutilName: "dsymutil" property path sysroot: qbs.sysroot property path platformPath property string exportedSymbolsCheckMode: "ignore-undefined" PropertyOptions { name: "exportedSymbolsCheckMode" allowedValues: ["strict", "ignore-undefined"] description: "Controls when we consider an updated dynamic library as changed with " + "regards to other binaries depending on it. The default is \"ignore-undefined\", " + "which means we do not care about undefined symbols being added or removed. " + "If you do care about that, e.g. because you link dependent products with an option " + "such as \"--no-undefined\", then you should set this property to \"strict\"." } property string toolchainPathPrefix: { var path = '' if (toolchainInstallPath) { path += toolchainInstallPath if (path.substr(-1) !== '/') path += '/' } if (toolchainPrefix) path += toolchainPrefix return path } property string cCompilerName: executablePrefix + (qbs.toolchain.contains("clang") ? "clang" : "gcc") + executableSuffix property string cxxCompilerName: executablePrefix + (qbs.toolchain.contains("clang") ? "clang++" : "g++") + executableSuffix compilerPathByLanguage: { return { "c": toolchainPathPrefix + cCompilerName, "cpp": toolchainPathPrefix + cxxCompilerName, "objc": toolchainPathPrefix + cCompilerName, "objcpp": toolchainPathPrefix + cxxCompilerName }; } compilerPath: toolchainPathPrefix + compilerName linkerPath: toolchainPathPrefix + linkerName property path archiverPath: { return toolchainPathPrefix + archiverName } property path nmPath: { return toolchainPathPrefix + nmName } property string objcopyPath: toolchainPathPrefix + objcopyName property string stripPath: toolchainPathPrefix + stripName property string dsymutilPath: toolchainPathPrefix + dsymutilName property stringList dsymutilFlags readonly property bool shouldCreateSymlinks: { return createSymlinks && internalVersion && qbs.targetOS.contains("unix"); } readonly property string internalVersion: { if (product.version === undefined) return undefined; if (typeof product.version !== "string" || !product.version.match(/^([0-9]+\.){0,3}[0-9]+$/)) throw("product.version must be a string in the format x[.y[.z[.w]] " + "where each component is an integer"); var maxVersionParts = 3; var versionParts = product.version.split('.').slice(0, maxVersionParts); // pad if necessary for (var i = versionParts.length; i < maxVersionParts; ++i) versionParts.push("0"); return versionParts.join('.'); } validate: { var validator = new ModUtils.PropertyValidator("cpp"); validator.setRequiredProperty("architecture", architecture, "you might want to re-run 'qbs-setup-toolchains'"); validator.validate(); } Rule { id: dynamicLibraryLinker multiplex: true inputs: ["obj"] inputsFromDependencies: ["dynamiclibrary_copy", "staticlibrary"] outputFileTags: ["dynamiclibrary", "dynamiclibrary_symlink", "dynamiclibrary_copy", "debuginfo"] outputArtifacts: { var lib = { filePath: product.destinationDirectory + "/" + PathTools.dynamicLibraryFilePath(product), fileTags: ["dynamiclibrary"] }; var libCopy = { // Copy of libfoo for smart re-linking. filePath: product.destinationDirectory + "/.socopy/" + PathTools.dynamicLibraryFilePath(product), fileTags: ["dynamiclibrary_copy"], alwaysUpdated: false, cpp: { transitiveSOs: Gcc.collectTransitiveSos(inputs) } }; var artifacts = [lib, libCopy]; if (ModUtils.moduleProperty(product, "shouldCreateSymlinks") && !product.moduleProperty("bundle", "isBundle")) { for (var i = 0; i < 3; ++i) { var symlink = { filePath: product.destinationDirectory + "/" + PathTools.dynamicLibraryFileName(product, undefined, i), fileTags: ["dynamiclibrary_symlink"] }; if (i > 0 && artifacts[i-1].filePath == symlink.filePath) break; // Version number has less than three components. artifacts.push(symlink); } } if (ModUtils.moduleProperty(product, "separateDebugInformation")) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.debugInfoFileName(product)), fileTags: ["debuginfo"] }); } return artifacts; } prepare: { return Gcc.prepareLinker.apply(this, arguments); } } Rule { id: staticLibraryLinker multiplex: true inputs: ["obj"] inputsFromDependencies: ["dynamiclibrary", "staticlibrary"] Artifact { filePath: product.destinationDirectory + "/" + PathTools.staticLibraryFilePath(product) fileTags: ["staticlibrary"] cpp.staticLibraries: { var result = []; for (var i in inputs.staticlibrary) { var lib = inputs.staticlibrary[i] result = Gcc.concatLibs(result, [lib.filePath].concat( ModUtils.moduleProperties(lib, 'staticLibraries'))); } result = Gcc.concatLibs(result, ModUtils.moduleProperties(product, 'staticLibraries')); return result } cpp.dynamicLibraries: { var result = []; for (var i in inputs.dynamiclibrary) result.push(inputs.dynamiclibrary[i].filePath); result = result.concat(ModUtils.moduleProperties(product, 'dynamicLibraries')); return result } } prepare: { var args = ['rcs', output.filePath]; for (var i in inputs.obj) args.push(inputs.obj[i].filePath); var cmd = new Command(ModUtils.moduleProperty(product, "archiverPath"), args); cmd.description = 'creating ' + output.fileName; cmd.highlight = 'linker' cmd.responseFileUsagePrefix = '@'; return cmd; } } Rule { id: loadableModuleLinker multiplex: true inputs: { var tags = ["obj"]; if (product.type.contains("application") && product.moduleProperty("qbs", "targetOS").contains("darwin") && product.moduleProperty("bundle", "embedInfoPlist")) tags.push("infoplist"); return tags; } inputsFromDependencies: ["dynamiclibrary_copy", "framework_copy", "staticlibrary"] outputFileTags: ["loadablemodule", "debuginfo", "dsym"] outputArtifacts: { var app = { filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.loadableModuleFilePath(product)), fileTags: ["loadablemodule"] } var artifacts = [app]; if (!product.moduleProperty("qbs", "targetOS").contains("darwin") && ModUtils.moduleProperty(product, "separateDebugInformation")) { artifacts.push({ filePath: app.filePath + ".debug", fileTags: ["debuginfo"] }); } if (ModUtils.moduleProperty(product, "buildDsym")) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.dwarfDsymFileName(product)), fileTags: ["dsym"] }); } return artifacts; } prepare: { return Gcc.prepareLinker.apply(this, arguments); } } Rule { id: applicationLinker multiplex: true inputs: { var tags = ["obj"]; if (product.type.contains("application") && product.moduleProperty("qbs", "targetOS").contains("darwin") && product.moduleProperty("bundle", "embedInfoPlist")) tags.push("infoplist"); return tags; } inputsFromDependencies: ["dynamiclibrary_copy", "staticlibrary"] outputFileTags: ["application", "debuginfo"] outputArtifacts: { var app = { filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.applicationFilePath(product)), fileTags: ["application"] } var artifacts = [app]; if (ModUtils.moduleProperty(product, "separateDebugInformation")) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, PathTools.debugInfoFileName(product)), fileTags: ["debuginfo"] }); } return artifacts; } prepare: { return Gcc.prepareLinker.apply(this, arguments); } } Rule { id: compiler inputs: ["cpp", "c", "objcpp", "objc", "asm", "asm_cpp"] auxiliaryInputs: ["hpp"] explicitlyDependsOn: ["c_pch", "cpp_pch", "objc_pch", "objcpp_pch"] Artifact { fileTags: ["obj"] filePath: ".obj/" + qbs.getHash(input.baseDir) + "/" + input.fileName + ".o" } prepare: { return Gcc.prepareCompiler.apply(this, arguments); } } Transformer { condition: cPrecompiledHeader !== undefined inputs: cPrecompiledHeader Artifact { filePath: product.name + "_c.gch" fileTags: "c_pch" } prepare: { return Gcc.prepareCompiler.apply(this, arguments); } } Transformer { condition: cxxPrecompiledHeader !== undefined inputs: cxxPrecompiledHeader Artifact { filePath: product.name + "_cpp.gch" fileTags: "cpp_pch" } prepare: { return Gcc.prepareCompiler.apply(this, arguments); } } Transformer { condition: objcPrecompiledHeader !== undefined inputs: objcPrecompiledHeader Artifact { filePath: product.name + "_objc.gch" fileTags: "objc_pch" } prepare: { return Gcc.prepareCompiler.apply(this, arguments); } } Transformer { condition: objcxxPrecompiledHeader !== undefined inputs: objcxxPrecompiledHeader Artifact { filePath: product.name + "_objcpp.gch" fileTags: "objcpp_pch" } prepare: { return Gcc.prepareCompiler.apply(this, arguments); } } FileTagger { patterns: "*.s" fileTags: ["asm"] } FileTagger { patterns: "*.S" fileTags: ["asm_cpp"] } FileTagger { patterns: "*.sx" fileTags: ["asm_cpp"] } } qbs-src-1.4.5/share/qbs/modules/cpp/UnixGCC.qbs000066400000000000000000000034651266132464200212010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs 1.0 GenericGCC { condition: false staticLibraryPrefix: "lib" dynamicLibraryPrefix: "lib" loadableModulePrefix: "lib" executablePrefix: "" staticLibrarySuffix: ".a" dynamicLibrarySuffix: ".so" loadableModuleSuffix: "" executableSuffix: "" debugInfoSuffix: ".debug" } qbs-src-1.4.5/share/qbs/modules/cpp/gcc.js000066400000000000000000000666601266132464200203320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var File = loadExtension("qbs.File"); var FileInfo = loadExtension("qbs.FileInfo"); var ModUtils = loadExtension("qbs.ModUtils"); var PathTools = loadExtension("qbs.PathTools"); var UnixUtils = loadExtension("qbs.UnixUtils"); var WindowsUtils = loadExtension("qbs.WindowsUtils"); function linkerFlags(product, inputs) { var libraryPaths = ModUtils.moduleProperties(product, 'libraryPaths'); var dynamicLibraries = ModUtils.moduleProperties(product, "dynamicLibraries"); var staticLibraries = ModUtils.modulePropertiesFromArtifacts(product, inputs.staticlibrary, 'cpp', 'staticLibraries'); var linkerScripts = ModUtils.moduleProperties(product, 'linkerScripts'); var frameworks = ModUtils.moduleProperties(product, 'frameworks'); var weakFrameworks = ModUtils.moduleProperties(product, 'weakFrameworks'); var rpaths = (product.moduleProperty("cpp", "useRPaths") !== false) ? ModUtils.moduleProperties(product, 'rpaths') : undefined; var args = [], i; if (rpaths && rpaths.length) args.push('-Wl,-rpath,' + rpaths.join(",-rpath,")); // Add filenames of internal library dependencies to the lists var staticLibsFromInputs = inputs.staticlibrary ? inputs.staticlibrary.map(function(a) { return a.filePath; }) : []; staticLibraries = concatLibsFromArtifacts(staticLibraries, inputs.staticlibrary); var dynamicLibsFromInputs = inputs.dynamiclibrary_copy ? inputs.dynamiclibrary_copy.map(function(a) { return a.filePath; }) : []; dynamicLibraries = concatLibsFromArtifacts(dynamicLibraries, inputs.dynamiclibrary_copy); // Flags for library search paths if (libraryPaths) args = args.concat(libraryPaths.map(function(path) { return '-L' + path })); if (linkerScripts) args = args.concat(linkerScripts.map(function(path) { return '-T' + path })); for (i in staticLibraries) { if (staticLibsFromInputs.contains(staticLibraries[i]) || File.exists(staticLibraries[i])) { args.push(staticLibraries[i]); } else { args.push('-l' + staticLibraries[i]); } } for (i in dynamicLibraries) { if (dynamicLibsFromInputs.contains(dynamicLibraries[i]) || File.exists(dynamicLibraries[i])) { args.push(dynamicLibraries[i]); } else { args.push('-l' + dynamicLibraries[i]); } } for (i in frameworks) { frameworkExecutablePath = PathTools.frameworkExecutablePath(frameworks[i]); if (File.exists(frameworkExecutablePath)) args.push(frameworkExecutablePath); else args = args.concat(['-framework', frameworks[i]]); } for (i in weakFrameworks) { frameworkExecutablePath = PathTools.frameworkExecutablePath(weakFrameworks[i]); if (File.exists(frameworkExecutablePath)) args = args.concat(['-weak_library', frameworkExecutablePath]); else args = args.concat(['-weak_framework', weakFrameworks[i]]); } var isDarwin = product.moduleProperty("qbs", "targetOS").contains("darwin"); var unresolvedSymbolsAction = isDarwin ? "error" : "ignore-in-shared-libs"; if (ModUtils.moduleProperty(product, "allowUnresolvedSymbols")) unresolvedSymbolsAction = isDarwin ? "suppress" : "ignore-all"; var unresolvedSymbolsKey = isDarwin ? "-undefined," : "--unresolved-symbols="; args.push("-Wl," + unresolvedSymbolsKey + unresolvedSymbolsAction); if (product.moduleProperty("qbs", "targetOS").contains('linux')) { var transitiveSOs = ModUtils.modulePropertiesFromArtifacts(product, inputs.dynamiclibrary_copy, 'cpp', 'transitiveSOs') var uniqueSOs = [].uniqueConcat(transitiveSOs) for (i in uniqueSOs) { // The real library is located one level up. args.push("-Wl,-rpath-link=" + FileInfo.path(FileInfo.path(uniqueSOs[i]))); } } if (product.moduleProperty("qbs", "toolchain").contains("clang")) { var stdlib = product.moduleProperty("cpp", "cxxStandardLibrary"); if (stdlib) { args.push("-stdlib=" + stdlib); } if (product.moduleProperty("qbs", "targetOS").contains("linux") && stdlib === "libc++") args.push("-lc++abi"); } return args; } // for compiler AND linker function configFlags(config) { var args = []; var arch = ModUtils.moduleProperty(config, "architecture") if (config.moduleProperty("qbs", "toolchain").contains("llvm") && config.moduleProperty("qbs", "targetOS").contains("darwin")) { args.push("-arch"); args.push(arch === "x86" ? "i386" : arch); } else { if (arch === 'x86_64') args.push('-m64'); else if (arch === 'x86') args.push('-m32'); } if (ModUtils.moduleProperty(config, "debugInformation")) args.push('-g'); var opt = ModUtils.moduleProperty(config, "optimization") if (opt === 'fast') args.push('-O2'); if (opt === 'small') args.push('-Os'); if (opt === 'none') args.push('-O0'); var warnings = ModUtils.moduleProperty(config, "warningLevel") if (warnings === 'none') args.push('-w'); if (warnings === 'all') { args.push('-Wall'); args.push('-Wextra'); } if (ModUtils.moduleProperty(config, "treatWarningsAsErrors")) args.push('-Werror'); var frameworkPaths = ModUtils.moduleProperties(config, 'frameworkPaths'); if (frameworkPaths) args = args.concat(frameworkPaths.map(function(path) { return '-F' + path })); var systemFrameworkPaths = ModUtils.moduleProperties(config, 'systemFrameworkPaths'); if (systemFrameworkPaths) args = args.concat(systemFrameworkPaths.map(function(path) { return '-iframework' + path })); return args; } // ### what we actually need here is something like product.usedFileTags // that contains all fileTags that have been used when applying the rules. function additionalCompilerFlags(product, input, output) { var includePaths = ModUtils.moduleProperties(input, 'includePaths'); var systemIncludePaths = ModUtils.moduleProperties(input, 'systemIncludePaths'); var platformDefines = ModUtils.moduleProperty(input, 'platformDefines'); var defines = ModUtils.moduleProperties(input, 'defines'); var EffectiveTypeEnum = { UNKNOWN: 0, LIB: 1, APP: 2 }; var effectiveType = EffectiveTypeEnum.UNKNOWN; var libTypes = {staticlibrary : 1, dynamiclibrary : 1}; var appTypes = {application : 1}; var i; for (i = product.type.length; --i >= 0;) { if (libTypes.hasOwnProperty(product.type[i]) !== -1) { effectiveType = EffectiveTypeEnum.LIB; break; } else if (appTypes.hasOwnProperty(product.type[i]) !== -1) { effectiveType = EffectiveTypeEnum.APP; break; } } var args = [] var positionIndependentCode = input.moduleProperty('cpp', 'positionIndependentCode') if (effectiveType === EffectiveTypeEnum.LIB) { if (positionIndependentCode !== false && !product.moduleProperty("qbs", "toolchain").contains("mingw")) args.push('-fPIC'); } else if (effectiveType === EffectiveTypeEnum.APP) { if (positionIndependentCode && !product.moduleProperty("qbs", "toolchain").contains("mingw")) args.push('-fPIE'); } else { throw ("The product's type must be in " + JSON.stringify( Object.getOwnPropertyNames(libTypes).concat(Object.getOwnPropertyNames(appTypes))) + ". But it is " + JSON.stringify(product.type) + '.'); } var cppFlags = ModUtils.moduleProperties(input, 'cppFlags'); for (i in cppFlags) args.push('-Wp,' + cppFlags[i]) if (platformDefines) args = args.concat(platformDefines.map(function(define) { return '-D' + define })); if (defines) args = args.concat(defines.map(function(define) { return '-D' + define })); if (includePaths) args = args.concat(includePaths.map(function(path) { return '-I' + path })); if (systemIncludePaths) args = args.concat(systemIncludePaths.map(function(path) { return '-isystem' + path })); var minimumWindowsVersion = ModUtils.moduleProperty(input, "minimumWindowsVersion"); if (minimumWindowsVersion && product.moduleProperty("qbs", "targetOS").contains("windows")) { var hexVersion = WindowsUtils.getWindowsVersionInFormat(minimumWindowsVersion, 'hex'); if (hexVersion) { var versionDefs = [ 'WINVER', '_WIN32_WINNT', '_WIN32_WINDOWS' ]; for (i in versionDefs) args.push('-D' + versionDefs[i] + '=' + hexVersion); } else { print('WARNING: Unknown Windows version "' + minimumWindowsVersion + '"'); } } args.push('-c'); args.push(input.filePath); args.push('-o'); args.push(output.filePath); return args } function additionalCompilerAndLinkerFlags(product) { var args = [] var sysroot = ModUtils.moduleProperty(product, "sysroot"); if (sysroot) { if (product.moduleProperty("qbs", "targetOS").contains("darwin")) args.push("-isysroot", sysroot); else args.push("--sysroot=" + sysroot); } var minimumOsxVersion = ModUtils.moduleProperty(product, "minimumOsxVersion"); if (minimumOsxVersion && product.moduleProperty("qbs", "targetOS").contains("osx")) args.push('-mmacosx-version-min=' + minimumOsxVersion); var minimumiOSVersion = ModUtils.moduleProperty(product, "minimumIosVersion"); if (minimumiOSVersion && product.moduleProperty("qbs", "targetOS").contains("ios")) { if (product.moduleProperty("qbs", "targetOS").contains("ios-simulator")) args.push('-mios-simulator-version-min=' + minimumiOSVersion); else args.push('-miphoneos-version-min=' + minimumiOSVersion); } var requireAppExtensionSafeApi = ModUtils.moduleProperty(product, "requireAppExtensionSafeApi"); if (requireAppExtensionSafeApi !== undefined && product.moduleProperty("qbs", "targetOS").contains("darwin")) { args.push(requireAppExtensionSafeApi ? "-fapplication-extension" : "-fno-application-extension"); } return args } // Returns the GCC language name equivalent to fileTag, accepted by the -x argument function languageName(fileTag) { if (fileTag === 'c') return 'c'; else if (fileTag === 'cpp') return 'c++'; else if (fileTag === 'objc') return 'objective-c'; else if (fileTag === 'objcpp') return 'objective-c++'; else if (fileTag === 'asm') return 'assembler'; else if (fileTag === 'asm_cpp') return 'assembler-with-cpp'; } function prepareCompiler(project, product, inputs, outputs, input, output) { function languageTagFromFileExtension(fileName) { var i = fileName.lastIndexOf('.'); if (i === -1) return; var m = { "c" : "c", "C" : "cpp", "cpp" : "cpp", "cxx" : "cpp", "c++" : "cpp", "cc" : "cpp", "m" : "objc", "mm" : "objcpp", "s" : "asm", "S" : "asm_cpp", "sx" : "asm_cpp" }; return m[fileName.substring(i + 1)]; } var i, c; // Determine which C-language we're compiling var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(output.fileTags)); if (!["c", "cpp", "objc", "objcpp", "asm", "asm_cpp"].contains(tag)) throw ("unsupported source language: " + tag); // Whether we're compiling a precompiled header or normal source file var pchOutput = outputs[tag + "_pch"] ? outputs[tag + "_pch"][0] : undefined; var args = configFlags(input); args.push('-pipe'); var useArc = ModUtils.moduleProperty(input, "automaticReferenceCounting"); if (useArc !== undefined && (tag === "objc" || tag === "objcpp")) { args.push(useArc ? "-fobjc-arc" : "-fno-objc-arc"); } var visibility = ModUtils.moduleProperty(input, 'visibility'); if (!product.type.contains('staticlibrary') && !product.moduleProperty("qbs", "toolchain").contains("mingw")) { if (visibility === 'hidden' || visibility === 'minimal') args.push('-fvisibility=hidden'); if ((visibility === 'hiddenInlines' || visibility === 'minimal') && tag === 'cpp') args.push('-fvisibility-inlines-hidden'); if (visibility === 'default') args.push('-fvisibility=default') } var prefixHeaders = ModUtils.moduleProperty(input, "prefixHeaders"); for (i in prefixHeaders) { args.push('-include'); args.push(prefixHeaders[i]); } var compilerPath; var compilerPathByLanguage = ModUtils.moduleProperty(input, "compilerPathByLanguage"); if (compilerPathByLanguage) compilerPath = compilerPathByLanguage[tag]; if (!compilerPath || tag !== languageTagFromFileExtension(input.fileName)) { // Only push '-x language' if we have to. args.push('-x'); args.push(languageName(tag) + (pchOutput ? '-header' : '')); } if (!compilerPath) { // fall back to main compiler compilerPath = ModUtils.moduleProperty(input, "compilerPath"); } args = args.concat(ModUtils.moduleProperties(input, 'platformFlags'), ModUtils.moduleProperties(input, 'flags'), ModUtils.moduleProperties(input, 'platformFlags', tag), ModUtils.moduleProperties(input, 'flags', tag)); if (!pchOutput && ModUtils.moduleProperty(product, 'precompiledHeader', tag)) { var pchFilePath = FileInfo.joinPaths( ModUtils.moduleProperty(product, "precompiledHeaderDir"), product.name + "_" + tag); args.push('-include', pchFilePath); } args = args.concat(additionalCompilerFlags(product, input, output)); args = args.concat(additionalCompilerAndLinkerFlags(product)); var wrapperArgs = ModUtils.moduleProperty(product, "compilerWrapper"); if (wrapperArgs && wrapperArgs.length > 0) { args.unshift(compilerPath); compilerPath = wrapperArgs.shift(); args = wrapperArgs.concat(args); } if (tag === "c" || tag === "objc") { var cVersion = ModUtils.moduleProperty(input, "cLanguageVersion"); if (cVersion) { var gccCVersionsMap = { "c89": "c89", "c99": "c99", "c11": "c1x" // Deprecated, but compatible with older gcc versions. }; args.push("-std=" + gccCVersionsMap[cVersion]); } } if (tag === "cpp" || tag === "objcpp") { var cxxVersion = ModUtils.moduleProperty(input, "cxxLanguageVersion"); if (cxxVersion) { var gccCxxVersionsMap = { "c++98": "c++98", "c++11": "c++0x", // Deprecated, but compatible with older gcc versions. "c++14": "c++1y" }; args.push("-std=" + gccCxxVersionsMap[cxxVersion]); } var cxxStandardLibrary = product.moduleProperty("cpp", "cxxStandardLibrary"); if (cxxStandardLibrary && product.moduleProperty("qbs", "toolchain").contains("clang")) { args.push("-stdlib=" + cxxStandardLibrary); } } var cmd = new Command(compilerPath, args); cmd.description = (pchOutput ? 'pre' : '') + 'compiling ' + input.fileName; if (pchOutput) cmd.description += ' (' + tag + ')'; cmd.highlight = "compiler"; cmd.responseFileUsagePrefix = '@'; return cmd; } // Concatenates two arrays of library names and preserves the dependency order that ld needs. function concatLibs(libs, deplibs) { var r = []; var s = {}; function addLibs(lst) { for (var i = lst.length; --i >= 0;) { var lib = lst[i]; if (!s[lib]) { s[lib] = true; r.unshift(lib); } } } addLibs(deplibs); addLibs(libs); return r; } function collectTransitiveSos(inputs) { var result = []; for (var i in inputs.dynamiclibrary_copy) { var lib = inputs.dynamiclibrary_copy[i]; var impliedLibs = ModUtils.moduleProperties(lib, 'transitiveSOs'); var libsToAdd = [lib.filePath].concat(impliedLibs); result = result.concat(libsToAdd); } result = concatLibs([], result); return result; } function prepareLinker(project, product, inputs, outputs, input, output) { var i, primaryOutput, cmd, commands = [], args = []; if (outputs.application) { primaryOutput = outputs.application[0]; } else if (outputs.dynamiclibrary) { primaryOutput = outputs.dynamiclibrary[0]; args.push("-shared"); if (product.moduleProperty("qbs", "targetOS").contains("linux")) { args.push("-Wl,--as-needed"); args.push("-Wl,-soname=" + UnixUtils.soname(product, primaryOutput.fileName)); } else if (product.moduleProperty("qbs", "targetOS").contains("darwin")) { args.push("-Wl,-install_name," + UnixUtils.soname(product, primaryOutput.fileName)); args.push("-Wl,-headerpad_max_install_names"); var internalVersion = product.moduleProperty("cpp", "internalVersion"); if (internalVersion) args.push("-current_version", internalVersion); } } else if (outputs.loadablemodule) { primaryOutput = outputs.loadablemodule[0]; args.push("-bundle"); if (product.moduleProperty("qbs", "targetOS").contains("darwin")) { args.push("-Wl,-headerpad_max_install_names"); } } if (product.moduleProperty("cpp", "entryPoint")) args.push("-Wl,-e," + product.moduleProperty("cpp", "entryPoint")); if (product.moduleProperty("qbs", "toolchain").contains("mingw")) { if (product.consoleApplication !== undefined) if (product.consoleApplication) args.push("-Wl,-subsystem,console"); else args.push("-Wl,-subsystem,windows"); var minimumWindowsVersion = ModUtils.moduleProperty(product, "minimumWindowsVersion"); if (minimumWindowsVersion) { var subsystemVersion = WindowsUtils.getWindowsVersionInFormat(minimumWindowsVersion, 'subsystem'); if (subsystemVersion) { var major = subsystemVersion.split('.')[0]; var minor = subsystemVersion.split('.')[1]; // http://sourceware.org/binutils/docs/ld/Options.html args.push("-Wl,--major-subsystem-version," + major); args.push("-Wl,--minor-subsystem-version," + minor); args.push("-Wl,--major-os-version," + major); args.push("-Wl,--minor-os-version," + minor); } else { print('WARNING: Unknown Windows version "' + minimumWindowsVersion + '"'); } } } if (inputs.infoplist) args.push("-sectcreate", "__TEXT", "__info_plist", inputs.infoplist[0].filePath); if (inputs.obj) args = args.concat(inputs.obj.map(function (obj) { return obj.filePath })); args = args.concat(configFlags(product)); args = args.concat(linkerFlags(product, inputs)); args = args.concat(additionalCompilerAndLinkerFlags(product)); args = args.concat(ModUtils.moduleProperties(product, 'platformLinkerFlags')); args = args.concat(ModUtils.moduleProperties(product, 'linkerFlags')); args.push("-o"); args.push(primaryOutput.filePath); cmd = new Command(ModUtils.moduleProperty(product, "linkerPath"), args); cmd.description = 'linking ' + primaryOutput.fileName; cmd.highlight = 'linker'; cmd.responseFileUsagePrefix = '@'; commands.push(cmd); if (outputs.debuginfo) { if (product.moduleProperty("qbs", "targetOS").contains("darwin")) { var flags = ModUtils.moduleProperty(product, "dsymutilFlags") || []; cmd = new Command(ModUtils.moduleProperty(product, "dsymutilPath"), flags.concat([ "-o", outputs.debuginfo[0].filePath, primaryOutput.filePath ])); cmd.description = "generating dSYM for " + product.name; commands.push(cmd); } else { cmd = new Command(ModUtils.moduleProperty(product, "objcopyPath"), [ "--only-keep-debug", primaryOutput.filePath, outputs.debuginfo[0].filePath ]); cmd.silent = true; commands.push(cmd); cmd = new Command(ModUtils.moduleProperty(product, "stripPath"), [ "--strip-debug", primaryOutput.filePath ]); cmd.silent = true; commands.push(cmd); cmd = new Command(ModUtils.moduleProperty(product, "objcopyPath"), [ "--add-gnu-debuglink=" + outputs.debuginfo[0].filePath, primaryOutput.filePath ]); cmd.silent = true; commands.push(cmd); } } if (outputs.dynamiclibrary) { // Update the copy, if any global symbols have changed. cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var sourceFilePath = outputs.dynamiclibrary[0].filePath; var targetFilePath = outputs.dynamiclibrary_copy[0].filePath; if (!File.exists(targetFilePath)) { File.copy(sourceFilePath, targetFilePath); return; } if (product.moduleProperty("qbs", "toolchain").contains("mingw")) { // mingw's nm tool does not work correctly. File.copy(sourceFilePath, targetFilePath); return; } var process = new Process(); var command = ModUtils.moduleProperty(product, "nmPath"); var args = ["-g", "-D", "-P"]; if (process.exec(command, args.concat(sourceFilePath), false) !== 0) { // Failure to run the nm tool is not fatal. We just fall back to the // "always relink" behavior. File.copy(sourceFilePath, targetFilePath); return; } var globalSymbolsSource = process.readStdOut(); if (process.exec(command, args.concat(targetFilePath), false) !== 0) { File.copy(sourceFilePath, targetFilePath); return; } var globalSymbolsTarget = process.readStdOut(); var globalSymbolsSourceLines = globalSymbolsSource.split('\n'); var globalSymbolsTargetLines = globalSymbolsTarget.split('\n'); if (globalSymbolsSourceLines.length !== globalSymbolsTargetLines.length) { var checkMode = ModUtils.moduleProperty(product, "exportedSymbolsCheckMode"); if (checkMode === "strict") { File.copy(sourceFilePath, targetFilePath); return; } // Collect undefined symbols and remove them from the symbol lists. // GNU nm has the "--defined" option for this purpose, but POSIX nm does not. args.push("-u"); if (process.exec(command, args.concat(sourceFilePath), false) !== 0) { File.copy(sourceFilePath, targetFilePath); return; } var undefinedSymbolsSource = process.readStdOut(); if (process.exec(command, args.concat(targetFilePath), false) !== 0) { File.copy(sourceFilePath, targetFilePath); return; } var undefinedSymbolsTarget = process.readStdOut(); process.close(); var undefinedSymbolsSourceLines = undefinedSymbolsSource.split('\n'); var undefinedSymbolsTargetLines = undefinedSymbolsTarget.split('\n'); globalSymbolsSourceLines = globalSymbolsSourceLines.filter(function(line) { return !undefinedSymbolsSourceLines.contains(line); }); globalSymbolsTargetLines = globalSymbolsTargetLines.filter(function(line) { return !undefinedSymbolsTargetLines.contains(line); }); if (globalSymbolsSourceLines.length !== globalSymbolsTargetLines.length) { File.copy(sourceFilePath, targetFilePath); return; } } while (globalSymbolsSourceLines.length > 0) { var sourceLine = globalSymbolsSourceLines.shift(); var targetLine = globalSymbolsTargetLines.shift(); var sourceLineElems = sourceLine.split(/\s+/); var targetLineElems = targetLine.split(/\s+/); if (sourceLineElems[0] !== targetLineElems[0] // Object name. || sourceLineElems[1] !== targetLineElems[1]) { // Object type File.copy(sourceFilePath, targetFilePath); return; } } } commands.push(cmd); // Create symlinks from {libfoo, libfoo.1, libfoo.1.0} to libfoo.1.0.0 var links = outputs["dynamiclibrary_symlink"]; var symlinkCount = links ? links.length : 0; for (i = 0; i < symlinkCount; ++i) { cmd = new Command("ln", ["-sf", primaryOutput.fileName, links[i].filePath]); cmd.highlight = "filegen"; cmd.description = "creating symbolic link '" + links[i].fileName + "'"; cmd.workingDirectory = FileInfo.path(primaryOutput.filePath); commands.push(cmd); } } return commands; } function concatLibsFromArtifacts(libs, artifacts) { if (!artifacts) return libs; var deps = artifacts.map(function (a) { return a.filePath; }); deps.reverse(); return concatLibs(deps, libs); } qbs-src-1.4.5/share/qbs/modules/cpp/genericunix-gcc.qbs000066400000000000000000000033121266132464200230020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs 1.0 UnixGCC { condition: !qbs.targetOS.contains('darwin') && !qbs.targetOS.contains('linux') && qbs.toolchain && qbs.toolchain.contains('gcc') && !qbs.toolchain.contains('mingw') } qbs-src-1.4.5/share/qbs/modules/cpp/ios-gcc.qbs000066400000000000000000000114201266132464200212530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs 1.0 import qbs.DarwinTools import qbs.File import qbs.ModUtils DarwinGCC { condition: qbs.hostOS.contains('osx') && qbs.targetOS.contains('ios') && qbs.toolchain && qbs.toolchain.contains('gcc') // Setting a minimum is especially important for Simulator or CC/LD thinks the target is OS X minimumIosVersion: xcodeSdkVersion || (cxxStandardLibrary === "libc++" ? "5.0" : undefined) platformObjcFlags: base.concat(simulatorObjcFlags) platformObjcxxFlags: base.concat(simulatorObjcFlags) // Private properties readonly property stringList simulatorObjcFlags: { // default in Xcode and also required for building 32-bit Simulator binaries with ARC // since the default ABI version is 0 for 32-bit targets return qbs.targetOS.contains("ios-simulator") ? ["-fobjc-abi-version=2", "-fobjc-legacy-dispatch"] : []; } Rule { condition: !product.moduleProperty("qbs", "targetOS").contains("ios-simulator") multiplex: true inputs: ["qbs"] Artifact { filePath: product.destinationDirectory + "/" + product.moduleProperty("bundle", "contentsFolderPath") + "/ResourceRules.plist" fileTags: ["resourcerules"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating ResourceRules"; cmd.highlight = "codegen"; cmd.sysroot = product.moduleProperty("qbs","sysroot"); cmd.sourceCode = function() { File.copy(sysroot + "/ResourceRules.plist", outputs.resourcerules[0].filePath); } return cmd; } } Rule { condition: product.moduleProperty("cpp", "buildIpa") multiplex: true inputs: ["application", "infoplist", "pkginfo", "resourcerules", "compiled_nib"] Artifact { filePath: product.destinationDirectory + "/" + product.targetName + ".ipa" fileTags: ["ipa"] } prepare: { var signingIdentity = product.moduleProperty("cpp", "signingIdentity"); if (!signingIdentity) throw "The name of a valid signing identity must be set using " + "cpp.signingIdentity in order to build an IPA package."; var provisioningProfile = product.moduleProperty("cpp", "provisioningProfile"); if (!provisioningProfile) throw "The path to a provisioning profile must be set using " + "cpp.provisioningProfile in order to build an IPA package."; var args = ["-sdk", product.moduleProperty("cpp", "xcodeSdkName"), "PackageApplication", "-v", product.buildDirectory + "/" + product.moduleProperty("bundle", "bundleName"), "-o", outputs.ipa[0].filePath, "--sign", signingIdentity, "--embed", provisioningProfile]; var command = "/usr/bin/xcrun"; var cmd = new Command(command, args) cmd.description = "creating ipa, signing with " + signingIdentity; cmd.highlight = "codegen"; cmd.workingDirectory = product.buildDirectory; return cmd; } } } qbs-src-1.4.5/share/qbs/modules/cpp/linux-gcc.qbs000066400000000000000000000032321266132464200216220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs 1.0 UnixGCC { condition: qbs.targetOS.contains('linux') && qbs.toolchain && qbs.toolchain.contains('gcc') rpaths: ['$ORIGIN'] } qbs-src-1.4.5/share/qbs/modules/cpp/msvc.js000066400000000000000000000300241266132464200205270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var FileInfo = loadExtension("qbs.FileInfo"); var ModUtils = loadExtension("qbs.ModUtils"); var WindowsUtils = loadExtension("qbs.WindowsUtils"); function prepareCompiler(project, product, inputs, outputs, input, output) { var i; var optimization = ModUtils.moduleProperty(input, "optimization") var debugInformation = ModUtils.moduleProperty(input, "debugInformation") var args = ['/nologo', '/c'] // Determine which C-language we're compiling var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(Object.keys(outputs))); if (!["c", "cpp"].contains(tag)) throw ("unsupported source language"); // Whether we're compiling a precompiled header or normal source file var pchOutput = outputs[tag + "_pch"] ? outputs[tag + "_pch"][0] : undefined; // enable unwind semantics args.push("/EHsc") // optimization: if (optimization === 'small') args.push('/Os') else if (optimization === 'fast') args.push('/O2') if (debugInformation) { if (ModUtils.moduleProperty(product, "separateDebugInformation")) args.push('/Zi'); else args.push('/Z7'); } var rtl = ModUtils.moduleProperty(product, "runtimeLibrary"); if (rtl) { rtl = (rtl === "static" ? "/MT" : "/MD"); if (product.moduleProperty("qbs", "enableDebugCode")) rtl += "d"; args.push(rtl); } // warnings: var warningLevel = ModUtils.moduleProperty(input, "warningLevel") if (warningLevel === 'none') args.push('/w') if (warningLevel === 'all') args.push('/Wall') if (ModUtils.moduleProperty(input, "treatWarningsAsErrors")) args.push('/WX') var includePaths = ModUtils.moduleProperties(input, 'includePaths'); for (i in includePaths) args.push('/I' + FileInfo.toWindowsSeparators(includePaths[i])) var systemIncludePaths = ModUtils.moduleProperties(input, 'systemIncludePaths'); for (i in systemIncludePaths) args.push('/I' + FileInfo.toWindowsSeparators(systemIncludePaths[i])) var platformDefines = ModUtils.moduleProperty(input, 'platformDefines'); for (i in platformDefines) args.push('/D' + platformDefines[i]) var defines = ModUtils.moduleProperties(input, 'defines'); for (i in defines) args.push('/D' + defines[i]) var minimumWindowsVersion = ModUtils.moduleProperty(product, "minimumWindowsVersion"); if (minimumWindowsVersion) { var hexVersion = WindowsUtils.getWindowsVersionInFormat(minimumWindowsVersion, 'hex'); if (hexVersion) { var versionDefs = [ 'WINVER', '_WIN32_WINNT', '_WIN32_WINDOWS' ]; for (i in versionDefs) { args.push('/D' + versionDefs[i] + '=' + hexVersion); } } else { print('WARNING: Unknown Windows version "' + minimumWindowsVersion + '"'); } } var objOutput = outputs.obj ? outputs.obj[0] : undefined args.push('/Fo' + FileInfo.toWindowsSeparators(objOutput.filePath)) args.push(FileInfo.toWindowsSeparators(input.filePath)) var prefixHeaders = ModUtils.moduleProperty(product, "prefixHeaders"); for (i in prefixHeaders) args.push("/FI" + FileInfo.toWindowsSeparators(prefixHeaders[i])); // Language if (tag === "cpp") args.push("/TP"); else if (tag === "c") args.push("/TC"); // precompiled header file var pch = ModUtils.moduleProperty(product, "precompiledHeader", tag); if (pch) { if (pchOutput) { // create PCH args.push("/Yc"); args.push("/Fp" + FileInfo.toWindowsSeparators(pchOutput.filePath)); args.push("/Fo" + FileInfo.toWindowsSeparators(objOutput.filePath)); args.push(FileInfo.toWindowsSeparators(input.filePath)); } else { // use PCH var pchHeaderName = FileInfo.toWindowsSeparators(pch); var pchName = FileInfo.toWindowsSeparators(ModUtils.moduleProperty(product, "precompiledHeaderDir") + "\\.obj\\" + product.name + "_" + tag + ".pch"); args.push("/FI" + pchHeaderName); args.push("/Yu" + pchHeaderName); args.push("/Fp" + pchName); } } args = args.concat(ModUtils.moduleProperties(input, 'platformFlags'), ModUtils.moduleProperties(input, 'flags'), ModUtils.moduleProperties(input, 'platformFlags', tag), ModUtils.moduleProperties(input, 'flags', tag)); var compilerPath = ModUtils.moduleProperty(product, "compilerPath"); var wrapperArgs = ModUtils.moduleProperty(product, "compilerWrapper"); if (wrapperArgs && wrapperArgs.length > 0) { args.unshift(compilerPath); compilerPath = wrapperArgs.shift(); args = wrapperArgs.concat(args); } var cmd = new Command(compilerPath, args) cmd.description = (pchOutput ? 'pre' : '') + 'compiling ' + input.fileName; if (pchOutput) cmd.description += ' (' + tag + ')'; cmd.highlight = "compiler"; cmd.workingDirectory = product.buildDirectory + "/.obj"; cmd.responseFileUsagePrefix = '@'; // cl.exe outputs the cpp file name. We filter that out. cmd.inputFileName = input.fileName; cmd.stdoutFilterFunction = function(output) { return output.split(inputFileName + "\r\n").join(""); }; return cmd; } function prepareLinker(project, product, inputs, outputs, input, output) { var i; var linkDLL = (outputs.dynamiclibrary ? true : false) var primaryOutput = (linkDLL ? outputs.dynamiclibrary[0] : outputs.application[0]) var debugInformation = ModUtils.moduleProperty(product, "debugInformation") var generateManifestFiles = !linkDLL && ModUtils.moduleProperty(product, "generateManifestFiles") var args = ['/nologo'] if (linkDLL) { args.push('/DLL'); args.push('/IMPLIB:' + FileInfo.toWindowsSeparators(outputs.dynamiclibrary_import[0].filePath)); } if (debugInformation) { args.push("/DEBUG"); if (outputs.debuginfo) args.push("/PDB:" + outputs.debuginfo[0].fileName); } else { args.push('/INCREMENTAL:NO') } var minimumWindowsVersion = ModUtils.moduleProperty(product, "minimumWindowsVersion"); var subsystemSwitch = undefined; if (minimumWindowsVersion || product.consoleApplication !== undefined) { // Ensure that we default to console if product.consoleApplication is undefined // since that could still be the case if only minimumWindowsVersion had been defined subsystemSwitch = product.consoleApplication === false ? '/SUBSYSTEM:WINDOWS' : '/SUBSYSTEM:CONSOLE'; } if (minimumWindowsVersion) { var subsystemVersion = WindowsUtils.getWindowsVersionInFormat(minimumWindowsVersion, 'subsystem'); if (subsystemVersion) { subsystemSwitch += ',' + subsystemVersion; args.push('/OSVERSION:' + subsystemVersion); } else { print('WARNING: Unknown Windows version "' + minimumWindowsVersion + '"'); } } if (subsystemSwitch) args.push(subsystemSwitch); var linkerOutputNativeFilePath; var manifestFileName; if (generateManifestFiles) { linkerOutputNativeFilePath = FileInfo.toWindowsSeparators( FileInfo.path(primaryOutput.filePath) + "/intermediate." + primaryOutput.fileName); manifestFileName = linkerOutputNativeFilePath + ".manifest"; args.push('/MANIFEST', '/MANIFESTFILE:' + manifestFileName) } else { linkerOutputNativeFilePath = FileInfo.toWindowsSeparators(primaryOutput.filePath); } var allInputs = (inputs.obj || []).concat(inputs.staticlibrary || []) if (inputs.dynamiclibrary_import) allInputs = allInputs.concat(inputs.dynamiclibrary_import); for (i in allInputs) { var fileName = FileInfo.toWindowsSeparators(allInputs[i].filePath) args.push(fileName) } function pushLibs(libs) { if (!libs) return; var s = {}; var c = libs.length; for (var i = 0; i < c; ++i) { var lib = FileInfo.toWindowsSeparators(libs[i]); if (!lib.match(/\.lib$/i)) lib += ".lib"; if (s[lib]) continue; s[lib] = true; args.push(lib); } } pushLibs(ModUtils.modulePropertiesFromArtifacts(product, inputs.staticlibrary, "cpp", "staticLibraries")); pushLibs(ModUtils.moduleProperties(product, "dynamicLibraries")); if (product.moduleProperty("cpp", "entryPoint")) args.push("/ENTRY:" + product.moduleProperty("cpp", "entryPoint")); args.push('/OUT:' + linkerOutputNativeFilePath) var libraryPaths = ModUtils.moduleProperties(product, 'libraryPaths'); for (i in libraryPaths) { args.push('/LIBPATH:' + FileInfo.toWindowsSeparators(libraryPaths[i])) } var linkerFlags = ModUtils.moduleProperties(product, 'platformLinkerFlags').concat( ModUtils.moduleProperties(product, 'linkerFlags')); args = args.concat(linkerFlags); if (ModUtils.moduleProperty(product, "allowUnresolvedSymbols")) args.push("/FORCE:UNRESOLVED"); var commands = []; var cmd = new Command(product.moduleProperty("cpp", "linkerPath"), args) cmd.description = 'linking ' + primaryOutput.fileName; cmd.highlight = 'linker'; cmd.workingDirectory = FileInfo.path(primaryOutput.filePath) cmd.responseFileUsagePrefix = '@'; cmd.stdoutFilterFunction = function(output) { return output.replace(/^ +Creating library.*\r\n$/, ""); }; commands.push(cmd); if (generateManifestFiles) { var outputNativeFilePath = FileInfo.toWindowsSeparators(primaryOutput.filePath); cmd = new JavaScriptCommand(); cmd.src = linkerOutputNativeFilePath; cmd.dst = outputNativeFilePath; cmd.sourceCode = function() { File.copy(src, dst); } cmd.silent = true commands.push(cmd); args = [ '/nologo', '/manifest', manifestFileName, "/outputresource:" + outputNativeFilePath + ";#" + (linkDLL ? "2" : "1") ] cmd = new Command("mt.exe", args) cmd.description = 'embedding manifest into ' + primaryOutput.fileName; cmd.highlight = 'linker'; cmd.workingDirectory = FileInfo.path(primaryOutput.filePath) commands.push(cmd); } return commands; } qbs-src-1.4.5/share/qbs/modules/cpp/osx-gcc.qbs000066400000000000000000000034441266132464200213010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs 1.0 import qbs.ModUtils DarwinGCC { condition: qbs.hostOS.contains('osx') && qbs.targetOS.contains('osx') && qbs.toolchain && qbs.toolchain.contains('gcc') minimumOsxVersion: xcodeSdkVersion || (cxxStandardLibrary === "libc++" ? "10.7" : undefined) } qbs-src-1.4.5/share/qbs/modules/cpp/windows-mingw.qbs000066400000000000000000000077301266132464200225510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs 1.0 import qbs.ModUtils import qbs.WindowsUtils GenericGCC { condition: qbs.targetOS.contains("windows") && qbs.toolchain && qbs.toolchain.contains("mingw") staticLibraryPrefix: "lib" dynamicLibraryPrefix: "" executablePrefix: "" staticLibrarySuffix: ".a" dynamicLibrarySuffix: ".dll" executableSuffix: ".exe" windowsApiCharacterSet: "unicode" platformDefines: base.concat(WindowsUtils.characterSetDefines(windowsApiCharacterSet)) compilerDefines: ['__GNUC__', 'WIN32', '_WIN32'] property string windresName: 'windres' property path windresPath: { return toolchainPathPrefix + windresName } setupBuildEnvironment: { var v = new ModUtils.EnvironmentVariable("PATH", ";", true); v.prepend(toolchainInstallPath); v.set(); } setupRunEnvironment: { var v = new ModUtils.EnvironmentVariable("PATH", ";", true); v.prepend(toolchainInstallPath); v.set(); } FileTagger { patterns: ["*.rc"] fileTags: ["rc"] } Rule { inputs: ["rc"] auxiliaryInputs: ["hpp"] Artifact { filePath: ".obj/" + qbs.getHash(input.baseDir) + "/" + input.completeBaseName + "_res.o" fileTags: ["obj"] } prepare: { var platformDefines = ModUtils.moduleProperty(input, 'platformDefines'); var defines = ModUtils.moduleProperties(input, 'defines'); var includePaths = ModUtils.moduleProperties(input, 'includePaths'); var systemIncludePaths = ModUtils.moduleProperties(input, 'systemIncludePaths'); var args = []; var i; for (i in platformDefines) { args.push('-D'); args.push(platformDefines[i]); } for (i in defines) { args.push('-D'); args.push(defines[i]); } for (i in includePaths) { args.push('-I'); args.push(includePaths[i]); } for (i in systemIncludePaths) { args.push('-I'); args.push(systemIncludePaths[i]); } args = args.concat(['-i', input.filePath, '-o', output.filePath]); var cmd = new Command(ModUtils.moduleProperty(product, "windresPath"), args); cmd.description = 'compiling ' + input.fileName; cmd.highlight = 'compiler'; return cmd; } } } qbs-src-1.4.5/share/qbs/modules/cpp/windows-msvc.qbs000066400000000000000000000272721266132464200224030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs 1.0 import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.PathTools import qbs.WindowsUtils import 'msvc.js' as MSVC CppModule { condition: qbs.hostOS.contains('windows') && qbs.targetOS.contains('windows') && qbs.toolchain && qbs.toolchain.contains('msvc') id: module windowsApiCharacterSet: "unicode" platformDefines: base.concat(WindowsUtils.characterSetDefines(windowsApiCharacterSet)) platformCommonCompilerFlags: { var flags = base; if (compilerVersionMajor >= 18) // 2013 flags.push("/FS"); return flags; } compilerDefines: ['_WIN32'] warningLevel: "default" compilerName: "cl.exe" property string assemblerName: { switch (qbs.architecture) { case "armv7": return "armasm.exe"; case "ia64": return "ias.exe"; case "x86": return "ml.exe"; case "x86_64": return "ml64.exe"; } } linkerName: "link.exe" runtimeLibrary: "dynamic" separateDebugInformation: true property bool generateManifestFiles: true property path toolchainInstallPath architecture: qbs.architecture staticLibraryPrefix: "" dynamicLibraryPrefix: "" executablePrefix: "" staticLibrarySuffix: ".lib" dynamicLibrarySuffix: ".dll" executableSuffix: ".exe" debugInfoSuffix: ".pdb" property string dynamicLibraryImportSuffix: ".lib" validate: { var validator = new ModUtils.PropertyValidator("cpp"); validator.setRequiredProperty("architecture", architecture, "you might want to re-run 'qbs-setup-toolchains'"); validator.validate(); } Transformer { condition: cPrecompiledHeader !== undefined inputs: cPrecompiledHeader Artifact { fileTags: ['obj'] filePath: { var completeBaseName = FileInfo.completeBaseName(product.moduleProperty("cpp", "cPrecompiledHeader")); return ".obj/" + qbs.getHash(completeBaseName) + '_c.obj' } } Artifact { fileTags: ['c_pch'] filePath: ".obj/" + product.name + '_c.pch' } prepare: { return MSVC.prepareCompiler.apply(this, arguments); } } Transformer { condition: cxxPrecompiledHeader !== undefined inputs: cxxPrecompiledHeader explicitlyDependsOn: ["c_pch"] // to prevent vc--0.pdb conflict Artifact { fileTags: ['obj'] filePath: { var completeBaseName = FileInfo.completeBaseName(product.moduleProperty("cpp", "cxxPrecompiledHeader")); return ".obj/" + qbs.getHash(completeBaseName) + '_cpp.obj' } } Artifact { fileTags: ['cpp_pch'] filePath: ".obj/" + product.name + '_cpp.pch' } prepare: { return MSVC.prepareCompiler.apply(this, arguments); } } Rule { id: compiler inputs: ["cpp", "c"] auxiliaryInputs: ["hpp"] explicitlyDependsOn: ["c_pch", "cpp_pch"] Artifact { fileTags: ['obj'] filePath: ".obj/" + qbs.getHash(input.baseDir) + "/" + input.fileName + ".obj" } prepare: { return MSVC.prepareCompiler.apply(this, arguments); } } Rule { id: applicationLinker multiplex: true inputs: ['obj'] inputsFromDependencies: ['staticlibrary', 'dynamiclibrary_import', "debuginfo"] outputFileTags: ["application", "debuginfo"] outputArtifacts: { var app = { fileTags: ["application"], filePath: FileInfo.joinPaths( product.destinationDirectory, PathTools.applicationFilePath(product)) }; var artifacts = [app]; if (ModUtils.moduleProperty(product, "debugInformation") && ModUtils.moduleProperty(product, "separateDebugInformation")) { artifacts.push({ fileTags: ["debuginfo"], filePath: app.filePath.substr(0, app.filePath.length - 4) + ModUtils.moduleProperty(product, "debugInfoSuffix") }); } return artifacts; } prepare: { return MSVC.prepareLinker.apply(this, arguments); } } Rule { id: dynamicLibraryLinker multiplex: true inputs: ['obj'] inputsFromDependencies: ['staticlibrary', 'dynamiclibrary_import', "debuginfo"] outputFileTags: ["dynamiclibrary", "dynamiclibrary_import", "debuginfo"] outputArtifacts: { var artifacts = [ { fileTags: ["dynamiclibrary"], filePath: product.destinationDirectory + "/" + PathTools.dynamicLibraryFilePath(product) }, { fileTags: ["dynamiclibrary_import"], filePath: product.destinationDirectory + "/" + PathTools.importLibraryFilePath(product), alwaysUpdated: false } ]; if (ModUtils.moduleProperty(product, "debugInformation") && ModUtils.moduleProperty(product, "separateDebugInformation")) { var lib = artifacts[0]; artifacts.push({ fileTags: ["debuginfo"], filePath: lib.filePath.substr(0, lib.filePath.length - 4) + ModUtils.moduleProperty(product, "debugInfoSuffix") }); } return artifacts; } prepare: { return MSVC.prepareLinker.apply(this, arguments); } } Rule { id: libtool multiplex: true inputs: ["obj"] inputsFromDependencies: ["staticlibrary"] Artifact { fileTags: ["staticlibrary"] filePath: product.destinationDirectory + "/" + PathTools.staticLibraryFilePath(product) cpp.staticLibraries: { var result = ModUtils.moduleProperties(product, 'staticLibraries'); for (var i in inputs.staticlibrary) { var lib = inputs.staticlibrary[i] result.push(lib.filePath) var impliedLibs = ModUtils.moduleProperties(lib, 'staticLibraries') result = result.uniqueConcat(impliedLibs); } return result } } prepare: { var args = ['/nologo'] var nativeOutputFileName = FileInfo.toWindowsSeparators(output.filePath) args.push('/OUT:' + nativeOutputFileName) for (var i in inputs.obj) { var fileName = FileInfo.toWindowsSeparators(inputs.obj[i].filePath) args.push(fileName) } var cmd = new Command("lib.exe", args); cmd.description = 'creating ' + output.fileName; cmd.highlight = 'linker'; cmd.workingDirectory = FileInfo.path(output.filePath) cmd.responseFileUsagePrefix = '@'; return cmd; } } FileTagger { patterns: ["*.rc"] fileTags: ["rc"] } Rule { inputs: ["rc"] auxiliaryInputs: ["hpp"] Artifact { filePath: ".obj/" + qbs.getHash(input.baseDir) + "/" + input.completeBaseName + ".res" fileTags: ["obj"] } prepare: { var platformDefines = ModUtils.moduleProperty(input, 'platformDefines'); var defines = ModUtils.moduleProperties(input, 'defines'); var includePaths = ModUtils.moduleProperties(input, 'includePaths'); var systemIncludePaths = ModUtils.moduleProperties(input, 'systemIncludePaths'); var args = []; var i; for (i in platformDefines) { args.push('/d'); args.push(platformDefines[i]); } for (i in defines) { args.push('/d'); args.push(defines[i]); } for (i in includePaths) { args.push('/i'); args.push(includePaths[i]); } for (i in systemIncludePaths) { args.push('/i'); args.push(systemIncludePaths[i]); } args = args.concat(['/fo', output.filePath, input.filePath]); var cmd = new Command('rc', args); cmd.description = 'compiling ' + input.fileName; cmd.highlight = 'compiler'; // Remove the first two lines of stdout. That's the logo. // Unfortunately there's no command line switch to turn that off. cmd.stdoutFilterFunction = function(output) { var idx = 0; for (var i = 0; i < 3; ++i) idx = output.indexOf('\n', idx + 1); return output.substr(idx + 1); } return cmd; } } FileTagger { patterns: "*.asm" fileTags: ["asm"] } Rule { inputs: ["asm"] Artifact { filePath: ".obj/" + qbs.getHash(input.baseDir) + "/" + input.completeBaseName + ".obj" fileTags: ["obj"] } prepare: { var args = ["/nologo", "/c", "/Fo" + FileInfo.toWindowsSeparators(output.filePath), FileInfo.toWindowsSeparators(input.filePath)]; if (ModUtils.moduleProperty(product, "debugInformation")) args.push("/Zi"); var cmd = new Command(ModUtils.moduleProperty(product, "assemblerName"), args); cmd.description = "assembling " + input.fileName; cmd.inputFileName = input.fileName; cmd.stdoutFilterFunction = function(output) { var lines = output.split("\r\n").filter(function (s) { return !s.endsWith(inputFileName); }); return lines.join("\r\n"); }; return cmd; } } } qbs-src-1.4.5/share/qbs/modules/ib/000077500000000000000000000000001266132464200170325ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/modules/ib/IBModule.qbs000066400000000000000000000204231266132464200212020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.BundleTools import qbs.DarwinTools import qbs.FileInfo import qbs.ModUtils import qbs.Process import 'ib.js' as Ib Module { Depends { name: "cpp" } // to put toolchainInstallPath in the PATH for actool condition: qbs.hostOS.contains("darwin") && qbs.targetOS.contains("darwin") property bool warnings: true property bool errors: true property bool notices: true property stringList flags // iconutil specific property string iconutilName: "iconutil" property string iconutilPath: iconutilName // XIB/NIB specific property string ibtoolName: "ibtool" property string ibtoolPath: ibtoolName property bool flatten: true property string module property bool autoActivateCustomFonts: true // Asset catalog specific property string actoolName: "ictool" property string actoolPath: actoolName property string appIconName property string launchImageName property bool compressPngs: true // private properties property string outputFormat: "human-readable-text" property string appleIconSuffix: ".icns" property string compiledAssetCatalogSuffix: ".car" property string compiledNibSuffix: ".nib" property string compiledStoryboardSuffix: ".storyboardc" property string ibtoolVersion: { return Ib.ibtoolVersion(ibtoolPath); } property var ibtoolVersionParts: ibtoolVersion ? ibtoolVersion.split('.').map(function(item) { return parseInt(item, 10); }) : [] property int ibtoolVersionMajor: ibtoolVersionParts[0] property int ibtoolVersionMinor: ibtoolVersionParts[1] property int ibtoolVersionPatch: ibtoolVersionParts[2] validate: { var validator = new ModUtils.PropertyValidator("ib"); validator.setRequiredProperty("ibtoolVersion", ibtoolVersion); validator.setRequiredProperty("ibtoolVersionMajor", ibtoolVersionMajor); validator.setRequiredProperty("ibtoolVersionMinor", ibtoolVersionMinor); validator.addVersionValidator("ibtoolVersion", ibtoolVersion, 2, 3); validator.addRangeValidator("ibtoolVersionMajor", ibtoolVersionMajor, 1); validator.addRangeValidator("ibtoolVersionMinor", ibtoolVersionMinor, 0); if (ibtoolVersionPatch !== undefined) validator.addRangeValidator("ibtoolVersionPatch", ibtoolVersionPatch, 0); validator.validate(); } FileTagger { patterns: ["*.iconset"] // bundle fileTags: ["iconset"] } FileTagger { patterns: ["*.nib", "*.xib"] fileTags: ["nib"] } FileTagger { patterns: ["*.storyboard"] fileTags: ["storyboard"] } FileTagger { patterns: ["*.xcassets"] // bundle fileTags: ["assetcatalog"] } Rule { inputs: ["iconset"] Artifact { filePath: FileInfo.joinPaths(BundleTools.destinationDirectoryForResource(product, input), input.completeBaseName + ModUtils.moduleProperty(product, "appleIconSuffix")) fileTags: ["icns"] } prepare: { var args = ["--convert", "icns", "--output", output.filePath, input.filePath]; var cmd = new Command(ModUtils.moduleProperty(product, "iconutilPath"), args); cmd.description = ModUtils.moduleProperty(product, "iconutilName") + ' ' + input.fileName; return cmd; } } Rule { inputs: ["nib", "storyboard"] outputFileTags: [ "compiled_ibdoc", "compiled_nib", "compiled_storyboard", "partial_infoplist" ] outputArtifacts: { // When the flatten property is true, this artifact will be a FILE, otherwise it will be a DIRECTORY var path = BundleTools.destinationDirectoryForResource(product, input); var suffix = ""; if (input.fileTags.contains("nib")) suffix = ModUtils.moduleProperty(product, "compiledNibSuffix"); else if (input.fileTags.contains("storyboard")) suffix = ModUtils.moduleProperty(product, "compiledStoryboardSuffix"); path += '/' + input.completeBaseName + suffix; var tags = ["compiled_ibdoc"]; if (inputs["nib"]) tags.push("compiled_nib"); if (inputs["storyboard"]) tags.push("compiled_storyboard"); var artifacts = [{ filePath: path, fileTags: tags }]; if (product.moduleProperty("ib", "ibtoolVersionMajor") >= 6) { var prefix = input.fileTags.contains("storyboard") ? "SB" : ""; path = FileInfo.joinPaths(product.destinationDirectory, input.completeBaseName + "-" + prefix + "PartialInfo.plist"); artifacts.push({ filePath: path, fileTags: "partial_infoplist" }); } return artifacts; } prepare: { var cmd = new Command(ModUtils.moduleProperty(product, "ibtoolPath"), Ib.ibtooldArguments(product, inputs, outputs)); cmd.description = ModUtils.moduleProperty(input, "ibtoolName") + ' ' + input.fileName; // Also display the language name of the nib/storyboard being compiled if it has one var localizationKey = DarwinTools.localizationKey(input.filePath); if (localizationKey) cmd.description += ' (' + localizationKey + ')'; cmd.highlight = 'compiler'; // May not be strictly needed, but is set by some versions of Xcode if (input.fileTags.contains("storyboard")) { var targetOS = product.moduleProperty("qbs", "targetOS"); if (targetOS.contains("ios")) cmd.environment.push("IBSC_MINIMUM_COMPATIBILITY_VERSION=" + product.moduleProperty("cpp", "minimumIosVersion")); if (targetOS.contains("osx")) cmd.environment.push("IBSC_MINIMUM_COMPATIBILITY_VERSION=" + product.moduleProperty("cpp", "minimumOsxVersion")); } return cmd; } } Rule { inputs: ["assetcatalog"] multiplex: true outputArtifacts: Ib.actoolOutputArtifacts(product, inputs) outputFileTags: ["compiled_assetcatalog", "partial_infoplist"] prepare: { var cmd = new Command(ModUtils.moduleProperty(product, "actoolPath"), Ib.ibtooldArguments(product, inputs, outputs)); cmd.description = inputs["assetcatalog"].map(function (input) { return "compiling " + input.fileName; }).join('\n'); cmd.highlight = "compiler"; cmd.stdoutFilterFunction = function(output) { return output; }; return cmd; } } } qbs-src-1.4.5/share/qbs/modules/ib/ib.js000066400000000000000000000230631266132464200177660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var BundleTools = loadExtension("qbs.BundleTools"); var DarwinTools = loadExtension("qbs.DarwinTools"); var File = loadExtension("qbs.File"); var FileInfo = loadExtension("qbs.FileInfo"); var ModUtils = loadExtension("qbs.ModUtils"); var Process = loadExtension("qbs.Process"); var PropertyList = loadExtension("qbs.PropertyList"); function artifactsFromInputs(inputs) { var artifacts = []; for (var tag in inputs) { artifacts = artifacts.concat(inputs[tag]); } return artifacts; } function ibtooldArguments(product, inputs, outputs, overrideOutput) { var i; var args = []; var allInputs = artifactsFromInputs(inputs); var outputFormat = ModUtils.moduleProperty(product, "outputFormat"); if (outputFormat) { if (!["binary1", "xml1", "human-readable-text"].contains(outputFormat)) throw("Invalid ibtoold output format: " + outputFormat + ". " + "Must be in [binary1, xml1, human-readable-text]."); args.push("--output-format", outputFormat); } var debugFlags = ["warnings", "errors", "notices"]; for (var j in debugFlags) { var flag = debugFlags[j]; if (ModUtils.modulePropertyFromArtifacts(product, allInputs, product.moduleName, flag)) { args.push("--" + flag); } } if (inputs.assetcatalog) { args.push("--platform", DarwinTools.applePlatformName(product.moduleProperty("qbs", "targetOS"))); var appIconName = ModUtils.modulePropertyFromArtifacts(product, inputs.assetcatalog, product.moduleName, "appIconName"); if (appIconName) args.push("--app-icon", appIconName); var launchImageName = ModUtils.modulePropertyFromArtifacts(product, inputs.assetcatalog, product.moduleName, "launchImageName"); if (launchImageName) args.push("--launch-image", launchImageName); // Undocumented but used by Xcode (only for iOS?), probably runs pngcrush or equivalent if (ModUtils.modulePropertyFromArtifacts(product, inputs.assetcatalog, product.moduleName, "compressPngs")) args.push("--compress-pngs"); } else { var sysroot = product.moduleProperty("qbs", "sysroot"); if (sysroot) args.push("--sdk", sysroot); args.push("--flatten", ModUtils.modulePropertyFromArtifacts(product, allInputs, product.moduleName, "flatten") ? 'YES' : 'NO'); // --module and --auto-activate-custom-fonts were introduced in Xcode 6.0 if (ModUtils.moduleProperty(product, "ibtoolVersionMajor") >= 6) { var module = ModUtils.moduleProperty(product, "module"); if (module) args.push("--module", module); if (ModUtils.modulePropertyFromArtifacts(product, allInputs, product.moduleName, "autoActivateCustomFonts")) args.push("--auto-activate-custom-fonts"); } } // --minimum-deployment-target was introduced in Xcode 5.0 if (ModUtils.moduleProperty(product, "ibtoolVersionMajor") >= 5) { if (product.moduleProperty("cpp", "minimumOsxVersion")) { args.push("--minimum-deployment-target"); args.push(product.moduleProperty("cpp", "minimumOsxVersion")); } if (product.moduleProperty("cpp", "minimumIosVersion")) { args.push("--minimum-deployment-target"); args.push(product.moduleProperty("cpp", "minimumIosVersion")); } } // --target-device and -output-partial-info-plist were introduced in Xcode 6.0 for ibtool if (ModUtils.moduleProperty(product, "ibtoolVersionMajor") >= 6 || compilingAssetCatalogs) { args.push("--output-partial-info-plist", (outputs && outputs.partial_infoplist) ? outputs.partial_infoplist[0].filePath : "/dev/null"); if (product.moduleProperty("qbs", "targetOS").contains("osx")) args.push("--target-device", "mac"); if (product.moduleProperty("qbs", "targetOS").contains("ios")) { // TODO: Only output the devices specified in TARGET_DEVICE_FAMILY // We can't get this info from Info.plist keys due to dependency order args.push("--target-device", "iphone"); args.push("--target-device", "ipad"); } } args = args.concat(ModUtils.modulePropertiesFromArtifacts(product, allInputs, product.moduleName, "flags")); if (overrideOutput) { args.push("--compile", overrideOutput); } else { if (outputs.compiled_ibdoc) args.push("--compile", outputs.compiled_ibdoc[0].filePath); if (outputs.compiled_assetcatalog) args.push("--compile", BundleTools.destinationDirectoryForResource(product, inputs.assetcatalog[0])); } for (i in allInputs) args.push(allInputs[i].filePath); return args; } function createTemporaryDirectory() { var process; try { process = new Process(); process.exec("mktemp", ["-d", "/tmp/io.qt.qbs." + new Array(32).join("X")], true); return process.readStdOut().trim(); } finally { process.close(); } } function actoolOutputArtifacts(product, inputs) { var process; try { // actool has no --dry-run option (rdar://21786925), // so compile to a fake temporary directory in order to extract the list of output files var outputDirectory = BundleTools.destinationDirectoryForResource(product, inputs.assetcatalog[0]); var fakeOutputDirectory = createTemporaryDirectory(); // Last --output-format argument overrides any previous ones process = new Process(); process.exec(ModUtils.moduleProperty(product, "actoolPath"), Ib.ibtooldArguments(product, inputs, undefined, fakeOutputDirectory) .concat(["--output-format", "xml1"]), true); var artifacts = parseActoolOutput(process.readStdOut()); // Fix the paths since we faked them for (var i in artifacts) artifacts[i].filePath = outputDirectory + artifacts[i].filePath.substr(fakeOutputDirectory.length); // Newer versions of actool don't generate *anything* if there's no input; // in that case a partial Info.plist would not have been generated either if (artifacts && artifacts.length > 0) artifacts.push({filePath: FileInfo.joinPaths(product.destinationDirectory, "assetcatalog_generated_info.plist"), fileTags: ["partial_infoplist"]}); return artifacts; } finally { process.close(); } } function parseActoolOutput(output) { var propertyList = new PropertyList(); try { propertyList.readFromString(output); var plist = propertyList.toObject(); if (plist) plist = plist["com.apple.actool.compilation-results"]; if (plist) { var artifacts = []; files = plist["output-files"]; for (var i in files) { var tags = files[i].endsWith(".plist") ? ["partial_infoplist"] : ["compiled_assetcatalog"]; artifacts.push({ filePath: files[i], fileTags: tags }); } return artifacts; } } finally { propertyList.clear(); } } function ibtoolVersion(ibtool) { var process; var version; try { process = new Process(); if (process.exec(ibtool, ["--version", "--output-format", "xml1"], true) !== 0) print(process.readStdErr()); var propertyList = new PropertyList(); try { propertyList.readFromString(process.readStdOut()); var plist = propertyList.toObject(); if (plist) plist = plist["com.apple.ibtool.version"]; if (plist) version = plist["short-bundle-version"]; } finally { propertyList.clear(); } } finally { process.close(); } return version; } qbs-src-1.4.5/share/qbs/modules/java/000077500000000000000000000000001266132464200173615ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/modules/java/JavaModule.qbs000066400000000000000000000260201266132464200221170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.FileInfo import qbs.ModUtils import qbs.Probes import qbs.Process import qbs.TextFile import "utils.js" as JavaUtils Module { Probes.JdkProbe { id: jdk environmentPaths: [jdkPath].concat(base) } property stringList additionalClassPaths property stringList additionalCompilerFlags property stringList additionalJarFlags property stringList bootClassPaths property string compilerFilePath: FileInfo.joinPaths(jdkPath, "bin", compilerName) property string compilerName: "javac" property bool enableWarnings: true property string interpreterFilePath : FileInfo.joinPaths(jdkPath, "bin", interpreterName) property string interpreterName: "java" property string jarFilePath: FileInfo.joinPaths(jdkPath, "bin", jarName) property string jarName: "jar" property path jdkPath: jdk.path property string compilerVersion: jdk.version ? jdk.version[1] : undefined property var compilerVersionParts: compilerVersion ? compilerVersion.split(/[\._]/).map(function(item) { return parseInt(item, 10); }) : [] property int compilerVersionMajor: compilerVersionParts[0] property int compilerVersionMinor: compilerVersionParts[1] property int compilerVersionPatch: compilerVersionParts[2] property int compilerVersionUpdate: compilerVersionParts[3] property string languageVersion PropertyOptions { name: "languageVersion" description: "Java language version to interpret source code as" } property string runtimeVersion PropertyOptions { name: "runtimeVersion" description: "version of the Java runtime to generate compatible bytecode for" } property var manifest: { return { "Manifest-Version": "1.0", "Class-Path": manifestClassPath ? manifestClassPath.join(" ") : undefined }; } PropertyOptions { name: "manifest" description: "properties to add to the manifest file when building a JAR" } property path manifestFile PropertyOptions { name: "manifestFile" description: "manifest file to embed when building a JAR" } property stringList manifestClassPath PropertyOptions { name: "manifestClassPath" description: "entries to add to the manifest's Class-Path when building a JAR" } property bool warningsAsErrors: false property pathList jdkIncludePaths: { var paths = []; if (qbs.hostOS.contains("darwin") && compilerVersionMinor <= 6) { paths.push("/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers"); } else { paths.push(FileInfo.joinPaths(jdkPath, "include")); var hostOS = qbs.hostOS.contains("windows") ? qbs.hostOS.concat(["win32"]) : qbs.hostOS; var platforms = ["win32", "darwin", "linux", "bsd", "solaris"]; for (var i = 0; i < platforms.length; ++i) { if (hostOS.contains(platforms[i])) { // Corresponds to JDK_INCLUDE_SUBDIR in the JDK Makefiles paths.push(FileInfo.joinPaths(jdkPath, "include", platforms[i])); break; } } } return paths; } // Internal properties property path classFilesDir: FileInfo.joinPaths(product.buildDirectory, "classes") property path internalClassFilesDir: FileInfo.joinPaths(product.buildDirectory, ".classes") property path runtimeJarPath: { if (qbs.hostOS.contains("osx") && compilerVersionMajor === 1 && compilerVersionMinor < 7) return FileInfo.joinPaths(jdkPath, "bundle", "Classes", "classes.jar"); return FileInfo.joinPaths(jdkPath, "jre", "lib", "rt.jar"); } validate: { var validator = new ModUtils.PropertyValidator("java"); validator.setRequiredProperty("jdkPath", jdkPath); validator.setRequiredProperty("compilerVersion", compilerVersion); validator.setRequiredProperty("compilerVersionParts", compilerVersionParts); validator.setRequiredProperty("compilerVersionMajor", compilerVersionMajor); validator.setRequiredProperty("compilerVersionMinor", compilerVersionMinor); validator.setRequiredProperty("compilerVersionUpdate", compilerVersionUpdate); validator.addVersionValidator("compilerVersion", compilerVersion ? compilerVersion.replace("_", ".") : undefined, 4, 4); validator.addRangeValidator("compilerVersionMajor", compilerVersionMajor, 1); validator.addRangeValidator("compilerVersionMinor", compilerVersionMinor, 0); validator.addRangeValidator("compilerVersionPatch", compilerVersionPatch, 0); validator.addRangeValidator("compilerVersionUpdate", compilerVersionUpdate, 0); validator.validate(); } FileTagger { patterns: "*.java" fileTags: ["java.java"] } Group { name: "io.qt.qbs.internal.java-helper" files: { return JavaUtils.helperFullyQualifiedNames("java").map(function(name) { return FileInfo.joinPaths(path, name + ".java"); }); } fileTags: ["java.java-internal"] } Rule { multiplex: true inputs: ["java.java-internal"] outputFileTags: ["java.class-internal"] outputArtifacts: { return JavaUtils.helperOutputArtifacts(product); } prepare: { var cmd = new Command(ModUtils.moduleProperty(product, "compilerFilePath"), JavaUtils.javacArguments(product, inputs, JavaUtils.helperOverrideArgs(product, "javac"))); cmd.silent = true; return [cmd]; } } Rule { multiplex: true inputs: ["java.java"] inputsFromDependencies: ["java.jar"] explicitlyDependsOn: ["java.class-internal"] outputFileTags: ["java.class", "hpp"] // Annotations can produce additional java source files. Ignored for now. outputArtifacts: { return JavaUtils.outputArtifacts(product, inputs); } prepare: { var cmd = new Command(ModUtils.moduleProperty(product, "compilerFilePath"), JavaUtils.javacArguments(product, inputs)); cmd.description = "Compiling Java sources"; cmd.highlight = "compiler"; return [cmd]; } } Rule { inputs: ["java.class"] multiplex: true Artifact { fileTags: ["java.jar"] filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ".jar") } prepare: { var i, key; var flags = "cf"; var args = [output.filePath]; var manifestFile = ModUtils.moduleProperty(product, "manifestFile"); var manifest = ModUtils.moduleProperty(product, "manifest"); var aggregateManifest = JavaUtils.manifestContents(manifestFile) || {}; // Add local key-value pairs (overrides equivalent keys specified in the file if // one was given) for (key in manifest) { if (manifest.hasOwnProperty(key)) aggregateManifest[key] = manifest[key]; } for (key in aggregateManifest) { if (aggregateManifest.hasOwnProperty(key) && aggregateManifest[key] === undefined) delete aggregateManifest[key]; } // Use default manifest unless we actually have properties to set var needsManifestFile = manifestFile !== undefined || aggregateManifest !== {"Manifest-Version": "1.0"}; manifestFile = FileInfo.joinPaths(product.buildDirectory, "manifest.mf"); var mf; try { mf = new TextFile(manifestFile, TextFile.WriteOnly); // Ensure that manifest version comes first mf.write("Manifest-Version: " + (aggregateManifest["Manifest-Version"] || "1.0") + "\n"); delete aggregateManifest["Manifest-Version"]; for (key in aggregateManifest) mf.write(key + ": " + aggregateManifest[key] + "\n"); mf.write("\n"); } finally { if (mf) { mf.close(); } } if (needsManifestFile) { flags += "m"; args.push(manifestFile); } var entryPoint = ModUtils.moduleProperty(product, "entryPoint"); var entryPoint = product.entryPoint; if (entryPoint) { flags += "e"; args.push(entryPoint); } args.unshift(flags); var otherFlags = ModUtils.moduleProperty(product, "additionalJarFlags"); if (otherFlags) args = args.concat(otherFlags); for (i in inputs["java.class"]) args.push(FileInfo.relativePath(ModUtils.moduleProperty(product, "classFilesDir"), inputs["java.class"][i].filePath)); var cmd = new Command(ModUtils.moduleProperty(product, "jarFilePath"), args); cmd.workingDirectory = ModUtils.moduleProperty(product, "classFilesDir"); cmd.description = "building " + FileInfo.fileName(output.fileName); cmd.highlight = "linker"; return cmd; } } } qbs-src-1.4.5/share/qbs/modules/java/io/000077500000000000000000000000001266132464200177705ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/modules/java/io/qt/000077500000000000000000000000001266132464200204145ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/modules/java/io/qt/qbs/000077500000000000000000000000001266132464200212015ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/modules/java/io/qt/qbs/Artifact.java000066400000000000000000000047121266132464200236050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs; import java.util.ArrayList; import java.util.List; public class Artifact { private String filePath; private List fileTags; public Artifact(String filePath) { if (filePath == null) throw new IllegalArgumentException("filePath"); this.filePath = filePath; this.fileTags = new ArrayList(); } public String getFilePath() { return filePath; } public void setFilePath(String filePath) { this.filePath = filePath; } public List getFileTags() { return fileTags; } public void setFileTags(List fileTags) { this.fileTags = fileTags; } public void addFileTag(String fileTag) { this.fileTags.add(fileTag); } public void removeFileTag(String fileTag) { this.fileTags.remove(fileTag); } public void clearFileTags() { this.fileTags.clear(); } } qbs-src-1.4.5/share/qbs/modules/java/io/qt/qbs/ArtifactListJsonWriter.java000066400000000000000000000130461266132464200264700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.util.List; /** * This uses a custom JSON implementation because the Java Standard Library does * not yet have native support for JSON, and only minimal support is required * here. */ public class ArtifactListJsonWriter implements ArtifactListWriter { private static final int TAB_WIDTH = 4; // based on escapeString from qtbase/qjsonwriter.cpp private static String escapeString(String s) { String out = ""; for (int i = 0; i < s.length();) { int u = s.codePointAt(i); // unpaired surrogate if (u >= Character.MIN_SURROGATE && u <= Character.MAX_SURROGATE) { out += "\ufffd"; i += Character.charCount(u); continue; } if (u < 0x80) { if (u < 0x20 || u == 0x22 || u == 0x5c) { out += "\\"; switch (u) { case 0x22: out += "\""; break; case 0x5c: out += "\\"; break; case 0x8: out += "b"; break; case 0xc: out += "f"; break; case 0xa: out += "n"; break; case 0xd: out += "r"; break; case 0x9: out += "t"; break; default: out += "u"; out += "0"; out += "0"; String hex = Integer.toHexString(u); if (hex.length() == 1) out += "0"; out += hex; break; } } else { out += s.substring(i, i + Character.charCount(u)); } } else { out += s.substring(i, i + Character.charCount(u)); } i += Character.charCount(u); } return out; } private static void writeString(PrintStream printWriter, String s) { printWriter.print("\""); printWriter.print(escapeString(s)); printWriter.print("\""); } private static void writeIndent(PrintStream printWriter, int level) { for (int i = 0; i < level * TAB_WIDTH; ++i) { printWriter.print(" "); } } private static void writeArtifact(Artifact artifact, PrintStream printWriter, int indentLevel, Boolean comma) { writeIndent(printWriter, indentLevel++); printWriter.print("{\n"); writeIndent(printWriter, indentLevel); writeString(printWriter, "filePath"); printWriter.print(": "); writeString(printWriter, artifact.getFilePath()); printWriter.println(","); writeIndent(printWriter, indentLevel); writeString(printWriter, "fileTags"); printWriter.print(": ["); for (int i = 0; i < artifact.getFileTags().size(); ++i) { writeString(printWriter, artifact.getFileTags().get(i)); if (i != artifact.getFileTags().size() - 1) printWriter.print(", "); } printWriter.println("]"); writeIndent(printWriter, --indentLevel); printWriter.println("}" + (comma ? "," : "")); } @Override public void write(List artifacts, OutputStream outputStream) throws IOException { PrintStream printWriter = new PrintStream(outputStream); printWriter.print("[\n"); for (int i = 0; i < artifacts.size(); ++i) { writeArtifact(artifacts.get(i), printWriter, 1, i != artifacts.size() - 1); } printWriter.println("]"); } } qbs-src-1.4.5/share/qbs/modules/java/io/qt/qbs/ArtifactListTextWriter.java000066400000000000000000000045651266132464200265110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.util.List; public class ArtifactListTextWriter implements ArtifactListWriter { private String join(List list, String separator) { String string = ""; if (!list.isEmpty()) { string += list.get(0); for (int i = 1; i < list.size(); ++i) { string += separator + list; } } return string; } @Override public void write(List artifacts, OutputStream outputStream) throws IOException { PrintStream stream = new PrintStream(outputStream); for (Artifact artifact : artifacts) { stream.format("%s [%s]\n", artifact.getFilePath(), join(artifact.getFileTags(), ", ")); } } } qbs-src-1.4.5/share/qbs/modules/java/io/qt/qbs/ArtifactListWriter.java000066400000000000000000000034171266132464200256370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs; import java.io.IOException; import java.io.OutputStream; import java.util.List; public interface ArtifactListWriter { public abstract void write(List artifacts, OutputStream outputStream) throws IOException; } qbs-src-1.4.5/share/qbs/modules/java/io/qt/qbs/ArtifactListXmlWriter.java000066400000000000000000000102611266132464200263130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; import org.w3c.dom.Element; public class ArtifactListXmlWriter implements ArtifactListWriter { @Override public void write(List artifacts, OutputStream outputStream) throws IOException { try { DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory .newInstance(); DocumentBuilder documentBuilder = documentBuilderFactory .newDocumentBuilder(); Document document = documentBuilder.newDocument(); Element rootElement = document.createElement("artifacts"); document.appendChild(rootElement); for (Artifact artifact : artifacts) { Element artifactElement = document.createElement("artifact"); rootElement.appendChild(artifactElement); Element filePathElement = document.createElement("filePath"); artifactElement.appendChild(filePathElement); filePathElement.appendChild(document.createTextNode(artifact .getFilePath())); Element fileTagsElement = document.createElement("fileTags"); artifactElement.appendChild(fileTagsElement); for (String fileTag : artifact.getFileTags()) { Element fileTagElement = document.createElement("fileTag"); fileTagsElement.appendChild(fileTagElement); fileTagElement .appendChild(document.createTextNode(fileTag)); } } TransformerFactory transformerFactory = TransformerFactory .newInstance(); Transformer transformer = transformerFactory.newTransformer(); DOMSource source = new DOMSource(document); StreamResult result = new StreamResult(outputStream); transformer.transform(source, result); new PrintStream(outputStream).println(); } catch (ParserConfigurationException pce) { throw new IOException(pce); } catch (TransformerException tfe) { throw new IOException(tfe); } } } qbs-src-1.4.5/share/qbs/modules/java/io/qt/qbs/tools/000077500000000000000000000000001266132464200223415ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/modules/java/io/qt/qbs/tools/JavaCompilerScannerTool.java000066400000000000000000000050671266132464200277400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs.tools; import io.qt.qbs.tools.utils.JavaCompilerScanner; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class JavaCompilerScannerTool { public static void main(String[] args) { JavaCompilerScanner scanner = new JavaCompilerScanner(); List compilerArguments = new ArrayList( Arrays.asList(args)); if (args.length >= 1 && args[0].equals("--output-format")) { compilerArguments.remove(0); if (args.length < 2) { throw new IllegalArgumentException( "--output-format requires an argument"); } scanner.setOutputFormat(args[1]); compilerArguments.remove(0); } try { int result = scanner.run(compilerArguments); scanner.write(System.out); System.exit(result); } catch (IOException e) { e.printStackTrace(); System.exit(1); } } } qbs-src-1.4.5/share/qbs/modules/java/io/qt/qbs/tools/utils/000077500000000000000000000000001266132464200235015ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/modules/java/io/qt/qbs/tools/utils/JavaCompilerOptions.java000066400000000000000000000075101266132464200302770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs.tools.utils; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.lang.model.SourceVersion; import javax.tools.JavaCompiler; import javax.tools.StandardJavaFileManager; public class JavaCompilerOptions { private final List recognizedOptions; private final List classNames; private final List files; private JavaCompilerOptions(List recognizedOptions, List classNames, List files) { this.recognizedOptions = recognizedOptions; this.classNames = classNames; this.files = files; } public static JavaCompilerOptions parse(JavaCompiler compiler, StandardJavaFileManager fileManager, String... arguments) { List recognizedOptions = new ArrayList(); List classNames = new ArrayList(); List files = new ArrayList(); for (int i = 0; i < arguments.length; ++i) { int argumentCount = compiler.isSupportedOption(arguments[i]); if (argumentCount < 0) argumentCount = fileManager.isSupportedOption(arguments[i]); if (argumentCount >= 0) { for (int j = 0; j < argumentCount + 1; ++j) { if (i + j >= arguments.length) { throw new IllegalArgumentException(arguments[i]); } recognizedOptions.add(arguments[i + j]); } i += argumentCount; } else { File file = new File(arguments[i]); if (file.exists()) files.add(file); else if (SourceVersion.isName(arguments[i])) classNames.add(arguments[i]); else throw new IllegalArgumentException(arguments[i]); } } return new JavaCompilerOptions(recognizedOptions, classNames, files); } public List getRecognizedOptions() { return Collections.unmodifiableList(recognizedOptions); } public List getFiles() { return Collections.unmodifiableList(files); } public List getClassNames() { return Collections.unmodifiableList(classNames); } } qbs-src-1.4.5/share/qbs/modules/java/io/qt/qbs/tools/utils/JavaCompilerScanner.java000066400000000000000000000134371266132464200302420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs.tools.utils; import io.qt.qbs.Artifact; import io.qt.qbs.ArtifactListJsonWriter; import io.qt.qbs.ArtifactListTextWriter; import io.qt.qbs.ArtifactListWriter; import io.qt.qbs.ArtifactListXmlWriter; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.tools.FileObject; import javax.tools.ForwardingJavaFileManager; import javax.tools.JavaCompiler; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; public class JavaCompilerScanner { private static final String humanReadableTextFormat = "human-readable-text"; private static final String jsonFormat = "json"; private static final String xmlFormat = "xml1"; private List artifacts = new ArrayList(); private String outputFormat = humanReadableTextFormat; private static Map getOutputFormatters() { Map outputFormatters = new HashMap(); outputFormatters.put(humanReadableTextFormat, new ArtifactListTextWriter()); outputFormatters.put(jsonFormat, new ArtifactListJsonWriter()); outputFormatters.put(xmlFormat, new ArtifactListXmlWriter()); return outputFormatters; } public String getOutputFormat() { return this.outputFormat; } public void setOutputFormat(String outputFormat) { this.outputFormat = outputFormat; } public List getArtifacts() { return this.artifacts; } public int run(List compilerArguments) { artifacts.clear(); JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager standardFileManager = compiler .getStandardFileManager(null, null, null); JavaFileManager fileManager = new ForwardingJavaFileManager( standardFileManager) { public JavaFileObject getJavaFileForOutput( JavaFileManager.Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException { JavaFileObject o = super.getJavaFileForOutput(location, className, kind, sibling); Artifact artifact = new Artifact(new File(o.toUri() .getSchemeSpecificPart()).toString()); if (kind.equals(JavaFileObject.Kind.CLASS)) { artifact.addFileTag("java.class"); } else if (kind.equals(JavaFileObject.Kind.SOURCE)) { artifact.addFileTag("java.java"); } artifacts.add(artifact); return new NullFileObject(o); } public FileObject getFileForOutput( JavaFileManager.Location location, String packageName, String relativeName, FileObject sibling) throws IOException { FileObject o = super.getFileForOutput(location, packageName, relativeName, sibling); Artifact artifact = new Artifact(new File(o.toUri() .getSchemeSpecificPart()).toString()); if (o.getName().endsWith(".h")) { artifact.addFileTag("hpp"); } artifacts.add(artifact); return new NullFileObject(o); } }; final JavaCompilerOptions options = JavaCompilerOptions .parse(compiler, standardFileManager, compilerArguments .toArray(new String[compilerArguments.size()])); return compiler.getTask( null, fileManager, null, options.getRecognizedOptions(), options.getClassNames(), standardFileManager.getJavaFileObjectsFromFiles(options .getFiles())).call() ? 0 : 1; } public void write(OutputStream outputStream) throws IOException { getOutputFormatters().get(outputFormat).write(artifacts, outputStream); } } qbs-src-1.4.5/share/qbs/modules/java/io/qt/qbs/tools/utils/NullFileObject.java000066400000000000000000000113421266132464200272060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ package io.qt.qbs.tools.utils; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; import java.net.URI; import javax.lang.model.element.Modifier; import javax.lang.model.element.NestingKind; import javax.tools.FileObject; import javax.tools.JavaFileObject; /** * Represents a FileObject that discards its output when written. */ public class NullFileObject implements FileObject, JavaFileObject { FileObject obj; public NullFileObject(FileObject obj) { this.obj = obj; } @Override public URI toUri() { return obj.toUri(); } @Override public String getName() { return obj.getName(); } @Override public InputStream openInputStream() throws IOException { return new InputStream() { @Override public int read() throws IOException { return -1; } }; } @Override public OutputStream openOutputStream() throws IOException { return new OutputStream() { @Override public void write(int b) throws IOException { } }; } @Override public Reader openReader(boolean ignoreEncodingErrors) throws IOException { return new Reader() { @Override public int read(char[] cbuf, int off, int len) throws IOException { return -1; } @Override public void close() throws IOException { } }; } @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { return obj.getCharContent(ignoreEncodingErrors); } @Override public Writer openWriter() throws IOException { return new Writer() { @Override public void write(char[] cbuf, int off, int len) throws IOException { } @Override public void flush() throws IOException { } @Override public void close() throws IOException { } }; } @Override public long getLastModified() { return obj.getLastModified(); } @Override public boolean delete() { return obj.delete(); } @Override public Kind getKind() { if (obj instanceof JavaFileObject) { return ((JavaFileObject) obj).getKind(); } throw new UnsupportedOperationException(); } @Override public boolean isNameCompatible(String simpleName, Kind kind) { if (obj instanceof JavaFileObject) { return ((JavaFileObject) obj).isNameCompatible(simpleName, kind); } throw new UnsupportedOperationException(); } @Override public NestingKind getNestingKind() { if (obj instanceof JavaFileObject) { return ((JavaFileObject) obj).getNestingKind(); } throw new UnsupportedOperationException(); } @Override public Modifier getAccessLevel() { if (obj instanceof JavaFileObject) { return ((JavaFileObject) obj).getAccessLevel(); } throw new UnsupportedOperationException(); } } qbs-src-1.4.5/share/qbs/modules/java/utils.js000066400000000000000000000257071266132464200210720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var File = loadExtension("qbs.File"); var FileInfo = loadExtension("qbs.FileInfo"); var ModUtils = loadExtension("qbs.ModUtils"); var Process = loadExtension("qbs.Process"); function findJdkPath(hostOS, arch, environmentPaths, searchPaths) { var i; for (var key in environmentPaths) { if (environmentPaths[key]) { return environmentPaths[key]; } } if (hostOS.contains("windows")) { var keys = [ "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\JavaSoft\\Java Development Kit" ]; for (i in keys) { var current = qbs.getNativeSetting(keys[i], "CurrentVersion"); // 1.8 etc. if (current) { var home = qbs.getNativeSetting([keys[i], current].join("\\"), "JavaHome"); if (home) { return home; } } } return undefined; } if (hostOS.contains("osx")) { var p = new Process(); try { // We filter by architecture here so that we'll get a compatible JVM for JNI use. var args = []; if (arch) { args.push("--arch", arch === "x86" ? "i386" : arch); } // --failfast doesn't print the default JVM if nothing matches the filter(s). var status = p.exec("/usr/libexec/java_home", args.concat(["--failfast"])); return status === 0 ? p.readStdOut().trim() : undefined; } finally { p.close(); } } if (hostOS.contains("unix")) { var requiredTools = ["javac", "java", "jar"]; for (i = 0; i < searchPaths.length; ++i) { function fullToolPath(tool) { return FileInfo.joinPaths(searchPaths[i], "bin", tool); } if (requiredTools.map(fullToolPath).every(File.exists)) { return searchPaths[i]; } } return undefined; } } function findJdkVersion(compilerFilePath) { var p = new Process(); try { p.exec(compilerFilePath, ["-version"]); var re = /^javac (([0-9]+(?:\.[0-9]+){2,2})_([0-9]+))$/m; var match = p.readStdErr().trim().match(re); if (match !== null) return match; } finally { p.close(); } } function supportsGeneratedNativeHeaderFiles(product) { var compilerVersionMajor = ModUtils.moduleProperty(product, "compilerVersionMajor"); if (compilerVersionMajor === 1) { if (ModUtils.moduleProperty(product, "compilerVersionMinor") >= 8) { return true; } } return compilerVersionMajor > 1; } function javacArguments(product, inputs, overrides) { function getModuleProperty(product, propertyName, overrides) { if (overrides && overrides[propertyName]) return overrides[propertyName]; return ModUtils.moduleProperty(product, propertyName); } function getModuleProperties(product, propertyName, overrides) { if (overrides && overrides[propertyName]) return overrides[propertyName]; return ModUtils.moduleProperties(product, propertyName); } var i; var outputDir = getModuleProperty(product, "classFilesDir", overrides); var classPaths = [outputDir]; var additionalClassPaths = getModuleProperty(product, "additionalClassPaths", overrides); if (additionalClassPaths) classPaths = classPaths.concat(additionalClassPaths); for (i in inputs["java.jar"]) classPaths.push(inputs["java.jar"][i].filePath); var debugArg = product.moduleProperty("qbs", "buildVariant") === "debug" ? "-g" : "-g:none"; var pathListSeparator = product.moduleProperty("qbs", "pathListSeparator"); var args = [ "-classpath", classPaths.join(pathListSeparator), "-s", product.buildDirectory, debugArg, "-d", outputDir ]; if (supportsGeneratedNativeHeaderFiles(product)) args.push("-h", product.buildDirectory); var runtimeVersion = getModuleProperty(product, "runtimeVersion", overrides); if (runtimeVersion) args.push("-target", runtimeVersion); var languageVersion = getModuleProperty(product, "languageVersion", overrides); if (languageVersion) args.push("-source", languageVersion); var bootClassPaths = getModuleProperties(product, "bootClassPaths", overrides); if (bootClassPaths && bootClassPaths.length > 0) args.push("-bootclasspath", bootClassPaths.join(pathListSeparator)); if (!getModuleProperty(product, "enableWarnings", overrides)) args.push("-nowarn"); if (getModuleProperty(product, "warningsAsErrors", overrides)) args.push("-Werror"); var otherFlags = getModuleProperty(product, "additionalCompilerFlags", overrides); if (otherFlags) args = args.concat(otherFlags); for (i in inputs["java.java"]) args.push(inputs["java.java"][i].filePath); for (i in inputs["java.java-internal"]) args.push(inputs["java.java-internal"][i].filePath); return args; } /** * Returns a list of fully qualified Java class names for the compiler helper tool. * * @param type @c java to return names of sources, @c to return names of compiled classes */ function helperFullyQualifiedNames(type) { var names = [ "io/qt/qbs/Artifact", "io/qt/qbs/ArtifactListJsonWriter", "io/qt/qbs/ArtifactListTextWriter", "io/qt/qbs/ArtifactListWriter", "io/qt/qbs/ArtifactListXmlWriter", "io/qt/qbs/tools/JavaCompilerScannerTool", "io/qt/qbs/tools/utils/JavaCompilerOptions", "io/qt/qbs/tools/utils/JavaCompilerScanner", "io/qt/qbs/tools/utils/JavaCompilerScanner$1", "io/qt/qbs/tools/utils/NullFileObject", "io/qt/qbs/tools/utils/NullFileObject$1", "io/qt/qbs/tools/utils/NullFileObject$2", "io/qt/qbs/tools/utils/NullFileObject$3", "io/qt/qbs/tools/utils/NullFileObject$4" ]; if (type === "java") { return names.filter(function (name) { return !name.contains("$"); }); } else if (type === "class") { return names; } } function helperOutputArtifacts(product) { return helperFullyQualifiedNames("class").map(function (name) { return { filePath: FileInfo.joinPaths(ModUtils.moduleProperty(product, "internalClassFilesDir"), name + ".class"), fileTags: ["java.class-internal"] }; }); } function helperOverrideArgs(product, tool) { var overrides = {}; if (tool === "javac") { // Build the helper tool with the same source and target version as the JDK it's being // compiled with. Both are irrelevant here since the resulting tool will only be run // with the same JDK as it was built with, and we know in advance the source is // compatible with all Java language versions from 1.6 and above. var jdkVersion = [ModUtils.moduleProperty(product, "compilerVersionMajor"), ModUtils.moduleProperty(product, "compilerVersionMinor")].join("."); overrides["languageVersion"] = jdkVersion; overrides["runtimeVersion"] = jdkVersion; // Build the helper tool's class files separately from the actual product's class files overrides["classFilesDir"] = ModUtils.moduleProperty(product, "internalClassFilesDir"); } // Inject the current JDK's runtime classes into the boot class path when building/running the // dependency scanner. This is normally not necessary but is important for Android platforms // where android.jar is the only JAR on the boot classpath and JSR 199 is unavailable. overrides["bootClassPaths"] = [ModUtils.moduleProperty(product, "runtimeJarPath")].concat( ModUtils.moduleProperties(product, "bootClassPaths")); return overrides; } function outputArtifacts(product, inputs) { // Handle the case where a product depends on Java but has no Java sources if (!inputs["java.java"] || inputs["java.java"].length === 0) return []; // We need to ensure that the output directory is created first, because the Java compiler // internally checks that it is present before performing any actions File.makePath(ModUtils.moduleProperty(product, "classFilesDir")); var process; try { process = new Process(); process.setWorkingDirectory( FileInfo.joinPaths(ModUtils.moduleProperty(product, "internalClassFilesDir"))); process.exec(ModUtils.moduleProperty(product, "interpreterFilePath"), ["io/qt/qbs/tools/JavaCompilerScannerTool", "--output-format", "json"] .concat(javacArguments(product, inputs, helperOverrideArgs(product))), true); return JSON.parse(process.readStdOut()); } finally { if (process) process.close(); } } function manifestContents(filePath) { if (filePath === undefined) return undefined; var contents, file; try { file = new TextFile(filePath); contents = file.readAll(); } finally { if (file) { file.close(); } } if (contents) { var dict = {}; var lines = contents.split(/[\r\n]/g); for (var i in lines) { var kv = lines[i].split(":"); if (kv.length !== 2) return undefined; dict[kv[0]] = kv[1]; } return dict; } } qbs-src-1.4.5/share/qbs/modules/nodejs/000077500000000000000000000000001266132464200177225ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/modules/nodejs/NodeJS.qbs000066400000000000000000000114661266132464200215630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Probes Module { // JavaScript files which have been "processed" - currently this simply means "copied to output // directory" but might later include minification and obfuscation processing additionalProductTypes: ["nodejs_processed_js"].concat(applicationFile ? ["application"] : []) Probes.NodeJsProbe { id: nodejs pathPrefixes: [toolchainInstallPath] } property path applicationFile PropertyOptions { name: "applicationFile" description: "file whose corresponding output will be executed when running the Node.js app" } property path toolchainInstallPath: nodejs.path property path interpreterFileName: nodejs.fileName property path interpreterFilePath: nodejs.filePath // private properties readonly property path compiledIntermediateDir: FileInfo.joinPaths(product.buildDirectory, "tmp", "nodejs.intermediate") setupBuildEnvironment: { var v = new ModUtils.EnvironmentVariable("PATH", qbs.pathListSeparator, qbs.hostOS.contains("windows")); v.prepend(toolchainInstallPath); v.set(); } setupRunEnvironment: { var v = new ModUtils.EnvironmentVariable("NODE_PATH", qbs.pathListSeparator, qbs.hostOS.contains("windows")); v.prepend(FileInfo.path(getEnv("QBS_RUN_FILE_PATH"))); v.set(); } FileTagger { patterns: ["*.js"] fileTags: ["js"] } validate: { var validator = new ModUtils.PropertyValidator("nodejs"); validator.setRequiredProperty("toolchainInstallPath", toolchainInstallPath); validator.setRequiredProperty("interpreterFileName", interpreterFileName); validator.setRequiredProperty("interpreterFilePath", interpreterFilePath); validator.validate(); } Rule { inputs: ["js"] outputArtifacts: { var tags = ["nodejs_processed_js"]; if (input.fileTags.contains("application_js") || product.moduleProperty("nodejs", "applicationFile") === input.filePath) tags.push("application"); // Preserve directory structure of input files var intermediatePath = product.sourceDirectory; // Handle nodejs.compiledIntermediateDir (QBS-5 workaround) var compiled = product.moduleProperty("nodejs", "compiledIntermediateDir"); if (input.filePath.startsWith(compiled)) { intermediatePath = compiled; } intermediatePath = FileInfo.path(FileInfo.relativePath(intermediatePath, input.filePath)); return [{ filePath: FileInfo.joinPaths(product.destinationDirectory, intermediatePath, input.fileName), fileTags: tags }]; } outputFileTags: ["nodejs_processed_js", "application"] prepare: { var cmd = new JavaScriptCommand(); cmd.description = "copying " + input.fileName; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; return cmd; } } } qbs-src-1.4.5/share/qbs/modules/nsis/000077500000000000000000000000001266132464200174145ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/modules/nsis/NSISModule.qbs000066400000000000000000000221611266132464200220470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs 1.0 import qbs.File import qbs.FileInfo import qbs.ModUtils Module { condition: qbs.targetOS.contains("windows") property path toolchainInstallPath: qbs.getNativeSetting(registryKey) property string version: (versionMajor !== undefined && versionMinor !== undefined) ? (versionMajor + "." + versionMinor) : undefined property var versionParts: [ versionMajor, versionMinor, versionPatch, versionBuild ] property int versionMajor: qbs.getNativeSetting(registryKey, "VersionMajor") property int versionMinor: qbs.getNativeSetting(registryKey, "VersionMinor") property int versionPatch: qbs.getNativeSetting(registryKey, "VersionBuild") property int versionBuild: qbs.getNativeSetting(registryKey, "VersionRevision") property string compilerName: "makensis" property string compilerPath: compilerName property string warningLevel: "normal" PropertyOptions { name: "warningLevel" allowedValues: ["none", "normal", "errors", "warnings", "info", "all"] } property bool disableConfig: false PropertyOptions { name: "disableConfig" description: "disable inclusion of nsisconf.nsh" } property bool enableQbsDefines: true PropertyOptions { name: "enableQbsDefines" description: "built-in variables that are defined when using the NSIS compiler" } property stringList defines PropertyOptions { name: "defines" description: "variables that are defined when using the NSIS compiler" } property stringList compilerFlags PropertyOptions { name: "compilerFlags" description: "additional flags for the NSIS compiler" } property string compressor: "default" PropertyOptions { name: "compressor" description: "the compression algorithm used to compress files/data in the installer" allowedValues: ["default", "zlib", "zlib-solid", "bzip2", "bzip2-solid", "lzma", "lzma-solid"] } property string executableSuffix: ".exe" // Private properties property string registryKey: { if (!qbs.hostOS.contains("windows")) return undefined; var keys = [ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS" ]; for (var i in keys) { if (qbs.getNativeSetting(keys[i])) return keys[i]; } } validate: { var validator = new ModUtils.PropertyValidator("nsis"); // Only *require* the toolchain install path on Windows // On other (Unix-like) operating systems it'll probably be in the PATH if (qbs.targetOS.contains("windows")) validator.setRequiredProperty("toolchainInstallPath", toolchainInstallPath); validator.setRequiredProperty("versionMajor", versionMajor); validator.setRequiredProperty("versionMinor", versionMinor); validator.setRequiredProperty("versionPatch", versionPatch); validator.setRequiredProperty("versionBuild", versionBuild); validator.addVersionValidator("version", version, 2, 4); validator.addRangeValidator("versionMajor", versionMajor, 1); validator.addRangeValidator("versionMinor", versionMinor, 0); validator.addRangeValidator("versionPatch", versionPatch, 0); validator.addRangeValidator("versionBuild", versionBuild, 0); validator.validate(); } setupBuildEnvironment: { if (toolchainInstallPath) { var v = new ModUtils.EnvironmentVariable("PATH", ";", true); v.prepend(toolchainInstallPath); v.prepend(FileInfo.joinPaths(toolchainInstallPath, "bin")); v.set(); } } // NSIS Script File FileTagger { patterns: ["*.nsi"] fileTags: ["nsi"] } // NSIS Header File FileTagger { patterns: ["*.nsh"] fileTags: ["nsh"] } Rule { id: nsisCompiler multiplex: true inputs: ["nsi"] Artifact { fileTags: ["nsissetup", "application"] filePath: product.destinationDirectory + "/" + product.targetName + ModUtils.moduleProperty(product, "executableSuffix") } prepare: { var i; var args = []; // Prefix character for makensis options var opt = product.moduleProperty("qbs", "hostOS").contains("windows") ? "/" : "-"; if (ModUtils.moduleProperty(product, "disableConfig")) { args.push(opt + "NOCONFIG"); } var warningLevel = ModUtils.moduleProperty(product, "warningLevel"); var warningLevels = ["none", "errors", "warnings", "info", "all"]; if (warningLevel !== "normal") { var level = warningLevels.indexOf(warningLevel); if (level < 0) { throw("Unexpected warning level '" + warningLevel + "'."); } else { args.push(opt + "V" + level); } } var enableQbsDefines = ModUtils.moduleProperty(product, "enableQbsDefines") if (enableQbsDefines) { var map = { "project.": project, "product.": product }; for (var prefix in map) { var obj = map[prefix]; for (var prop in obj) { var val = obj[prop]; if (typeof val !== 'function' && typeof val !== 'object' && !prop.startsWith("_")) { args.push(opt + "D" + prefix + prop + "=" + val); } } } // Users are likely to need this var arch = product.moduleProperty("qbs", "architecture"); args.push(opt + "Dqbs.architecture=" + arch); // Helper define for alternating between 32-bit and 64-bit logic if (arch === "x86_64" || arch === "ia64") { args.push(opt + "DWin64"); } } // User-supplied defines var defines = ModUtils.moduleProperty(product, "defines"); for (i in defines) { args.push(opt + "D" + defines[i]); } // User-supplied flags var flags = ModUtils.moduleProperty(product, "compilerFlags"); for (i in flags) { args.push(flags[i]); } // Override the compression algorithm if needed var compressor = ModUtils.moduleProperty(product, "compressor"); if (compressor !== "default") { var compressorFlag = opt + "XSetCompressor /FINAL "; if (compressor.endsWith("-solid")) { compressorFlag += "/SOLID "; } args.push(compressorFlag + compressor.split('-')[0]); } var inputFileNames = []; for (i in inputs.nsi) { inputFileNames.push(inputs.nsi[i].fileName); args.push(FileInfo.toNativeSeparators(inputs.nsi[i].filePath, product.moduleProperty("qbs", "hostOS"))); } // Output file name - this goes last to override any OutFile command in the script args.push(opt + "XOutFile " + output.filePath); var cmd = new Command(ModUtils.moduleProperty(product, "compilerPath"), args); cmd.description = "compiling " + inputFileNames.join(", "); cmd.highlight = "compiler"; cmd.workingDirectory = FileInfo.path(output.filePath); return cmd; } } } qbs-src-1.4.5/share/qbs/modules/qbs/000077500000000000000000000000001266132464200172255ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/modules/qbs/common.qbs000066400000000000000000000172351266132464200212340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs 1.0 import qbs.FileInfo import qbs.ModUtils import qbs.PathTools Module { property string buildVariant: "debug" property bool enableDebugCode: buildVariant == "debug" property bool debugInformation: (buildVariant == "debug") property string optimization: (buildVariant == "debug" ? "none" : "fast") readonly property stringList hostOS: undefined // set internally property string hostOSVersion: { if (hostOS && hostOS.contains("osx")) { return getNativeSetting("/System/Library/CoreServices/ServerVersion.plist", "ProductVersion") || getNativeSetting("/System/Library/CoreServices/SystemVersion.plist", "ProductVersion"); } else if (hostOS && hostOS.contains("windows")) { var version = getNativeSetting("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion", "CurrentVersion"); return version + "." + hostOSBuildVersion; } } property string hostOSBuildVersion: { if (hostOS.contains("osx")) { return getNativeSetting("/System/Library/CoreServices/ServerVersion.plist", "ProductBuildVersion") || getNativeSetting("/System/Library/CoreServices/SystemVersion.plist", "ProductBuildVersion"); } else if (hostOS.contains("windows")) { return getNativeSetting("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion", "CurrentBuildNumber"); } } readonly property var hostOSVersionParts: hostOSVersion ? hostOSVersion.split('.').map(function(item) { return parseInt(item, 10); }) : [] readonly property int hostOSVersionMajor: hostOSVersionParts[0] || 0 readonly property int hostOSVersionMinor: hostOSVersionParts[1] || 0 readonly property int hostOSVersionPatch: hostOSVersionParts[2] || 0 property stringList targetOS: hostOS property string pathListSeparator: hostOS.contains("windows") ? ";" : ":" property string pathSeparator: hostOS.contains("windows") ? "\\" : "/" property string nullDevice: hostOS.contains("windows") ? "NUL" : "/dev/null" property string profile property stringList toolchain property string architecture property bool install: false property string installSourceBase readonly property string installRoot: undefined property string installDir property string installPrefix: "" property path sysroot PropertyOptions { name: "buildVariant" allowedValues: ['debug', 'release'] description: "name of the build variant" } PropertyOptions { name: "optimization" allowedValues: ['none', 'fast', 'small'] description: "optimization level" } validate: { var validator = new ModUtils.PropertyValidator("qbs"); validator.setRequiredProperty("hostOS", hostOS); validator.setRequiredProperty("targetOS", targetOS); if (hostOS && (hostOS.contains("windows") || hostOS.contains("osx"))) { validator.setRequiredProperty("hostOSVersion", hostOSVersion, "could not detect host operating system version; " + "verify that system files and registry keys have not " + "been modified."); if (hostOSVersion) validator.addVersionValidator("hostOSVersion", hostOSVersion, 2, 4); validator.setRequiredProperty("hostOSBuildVersion", hostOSBuildVersion, "could not detect host operating system build version; " + "verify that system files or registry have not been " + "tampered with."); } validator.addCustomValidator("architecture", architecture, function (value) { return !architecture || architecture === canonicalArchitecture(architecture); }, "'" + architecture + "' is invalid. You must use the canonical name '" + canonicalArchitecture(architecture) + "'"); validator.validate(); } // private properties property var commonRunEnvironment: { var env = qbs.currentEnv(); if (targetOS.contains("windows")) { var newEntry = FileInfo.toWindowsSeparators(FileInfo.joinPaths(installRoot, installPrefix)); env["PATH"] = PathTools.prependOrSetPath(newEntry, env["PATH"], qbs.pathListSeparator); } else if (hostOS.contains("darwin") && targetOS.contains("darwin")) { env["DYLD_FRAMEWORK_PATH"] = PathTools.prependOrSetPath([ FileInfo.joinPaths(installRoot, installPrefix, "Library", "Frameworks"), FileInfo.joinPaths(installRoot, installPrefix, "lib"), FileInfo.joinPaths(installRoot, installPrefix) ].join(pathListSeparator), env["DYLD_FRAMEWORK_PATH"], qbs.pathListSeparator); env["DYLD_LIBRARY_PATH"] = PathTools.prependOrSetPath([ FileInfo.joinPaths(installRoot, installPrefix, "lib"), FileInfo.joinPaths(installRoot, installPrefix, "Library", "Frameworks"), FileInfo.joinPaths(installRoot, installPrefix) ].join(pathListSeparator), env["DYLD_LIBRARY_PATH"], qbs.pathListSeparator); if (targetOS.contains("ios-simulator") && sysroot) env["DYLD_ROOT_PATH"] = PathTools.prependOrSetPath(sysroot, env["DYLD_ROOT_PATH"], qbs.pathListSeparator); } else if (hostOS.contains("unix") && targetOS.contains("unix")) { env["LD_LIBRARY_PATH"] = PathTools.prependOrSetPath( FileInfo.joinPaths(installRoot, installPrefix, "lib"), env["LD_LIBRARY_PATH"], qbs.pathListSeparator); } return env; } // internal properties readonly property string version: [versionMajor, versionMinor, versionPatch].join(".") readonly property int versionMajor: undefined // set internally readonly property int versionMinor: undefined // set internally readonly property int versionPatch: undefined // set internally } qbs-src-1.4.5/share/qbs/modules/typescript/000077500000000000000000000000001266132464200206465ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/modules/typescript/TypeScriptModule.qbs000066400000000000000000000223041266132464200246320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.File import qbs.FileInfo import qbs.ModUtils import qbs.Probes import qbs.Process import "typescript.js" as TypeScript Module { Depends { name: "nodejs" } additionalProductTypes: ["compiled_typescript"] // QBS-833 workaround Probes.NodeJsProbe { id: nodejsProbe; pathPrefixes: [nodejsProbe.toolchainInstallPath] } nodejs.toolchainInstallPath: nodejsProbe.path nodejs.interpreterFileName: nodejsProbe.fileName nodejs.interpreterFilePath: nodejsProbe.filePath Probes.TypeScriptProbe { id: tsc pathPrefixes: [toolchainInstallPath] nodejsToolchainInstallPath: nodejs.toolchainInstallPath } property path toolchainInstallPath: tsc.path property string version: tsc.version ? tsc.version[2] : undefined property var versionParts: version ? version.split('.').map(function(item) { return parseInt(item, 10); }) : [] property int versionMajor: versionParts[0] property int versionMinor: versionParts[1] property int versionPatch: versionParts[2] property int versionBuild: versionParts[3] property string versionSuffix: tsc.version ? tsc.version[3] : undefined property string compilerName: tsc.fileName property string compilerPath: tsc.filePath property string warningLevel: "normal" PropertyOptions { name: "warningLevel" description: "pedantic to warn on expressions and declarations with an implied 'any' type" allowedValues: ["normal", "pedantic"] } property string targetVersion PropertyOptions { name: "targetVersion" description: "ECMAScript target version" allowedValues: ["ES3", "ES5"] } property string moduleLoader PropertyOptions { name: "moduleLoader" allowedValues: ["commonjs", "amd"] } property bool stripComments: !qbs.debugInformation PropertyOptions { name: "stripComments" description: "whether to remove comments from the generated output" } property bool generateDeclarations: false PropertyOptions { name: "generateDeclarations" description: "whether to generate corresponding .d.ts files during compilation" } // In release mode, nodejs can/should default-enable minification and obfuscation, // making the source maps useless, so these default settings work out fine property bool generateSourceMaps: qbs.debugInformation PropertyOptions { name: "generateSourceMaps" description: "whether to generate corresponding .map files during compilation" } property stringList compilerFlags PropertyOptions { name: "compilerFlags" description: "additional flags for the TypeScript compiler" } property bool singleFile: false PropertyOptions { name: "singleFile" description: "whether to compile all source files to a single output file" } validate: { var validator = new ModUtils.PropertyValidator("typescript"); validator.setRequiredProperty("toolchainInstallPath", toolchainInstallPath); validator.setRequiredProperty("compilerName", compilerName); validator.setRequiredProperty("compilerPath", compilerPath); validator.setRequiredProperty("version", version); validator.setRequiredProperty("versionParts", versionParts); validator.setRequiredProperty("versionMajor", versionMajor); validator.setRequiredProperty("versionMinor", versionMinor); validator.setRequiredProperty("versionPatch", versionPatch); validator.addVersionValidator("version", version, 3, 4); validator.addRangeValidator("versionMajor", versionMajor, 1); validator.addRangeValidator("versionMinor", versionMinor, 0); validator.addRangeValidator("versionPatch", versionPatch, 0); if (versionParts && versionParts.length >= 4) { validator.setRequiredProperty("versionBuild", versionBuild); validator.addRangeValidator("versionBuild", versionBuild, 0); } validator.validate(); } // TypeScript declaration files FileTagger { patterns: ["*.d.ts"] fileTags: ["typescript_declaration"] } // TypeScript source files FileTagger { patterns: ["*.ts"] fileTags: ["typescript"] } Group { name: "io.qt.qbs.internal.typescript-helper" files: [ FileInfo.joinPaths(path, "qbs-tsc-scan", "qbs-tsc-scan.ts"), FileInfo.joinPaths(typescript.toolchainInstallPath, "typescript.d.ts") ] fileTags: ["typescript.typescript-internal"] } Rule { multiplex: true inputs: ["typescript.typescript-internal"] outputFileTags: ["typescript.compiled_typescript-internal"] outputArtifacts: { if (!TypeScript.supportsModernFeatures(product)) return []; return [{ filePath: FileInfo.joinPaths(product.buildDirectory, ".io.qt.qbs.internal.typescript", "qbs-tsc-scan.js"), fileTags: ["typescript.compiled_typescript-internal"] }]; } prepare: { var inputPaths = inputs["typescript.typescript-internal"].map(function (input) { return input.filePath; }); var args = ["--module", "commonjs", "--outDir", FileInfo.path(output.filePath)].concat(inputPaths); var cmd = new Command(ModUtils.moduleProperty(product, "compilerPath"), args); cmd.silent = true; return [cmd]; } } Rule { id: typescriptCompiler multiplex: true inputs: ["typescript"] inputsFromDependencies: ["typescript_declaration"] explicitlyDependsOn: ["typescript.compiled_typescript-internal"] outputArtifacts: TypeScript.outputArtifacts(product, inputs) outputFileTags: ["application_js", "compiled_typescript", "js", "source_map", "typescript_declaration"] prepare: { var cmd, cmds = []; cmd = new Command(ModUtils.moduleProperty(product, "compilerPath"), TypeScript.tscArguments(product, inputs)); cmd.description = "compiling " + (ModUtils.moduleProperty(product, "singleFile") ? outputs.compiled_typescript[0].fileName : inputs.typescript.map(function(obj) { return obj.fileName; }).join(", ")); cmd.highlight = "compiler"; cmds.push(cmd); // QBS-5 // Move the compiled JavaScript files compiled by TypeScript to an intermediate // directory so that the nodejs module can perform any necessary postprocessing // on the result. The nodejs module will move the files back to their original // locations after postprocessing. cmd = new JavaScriptCommand(); cmd.silent = true; cmd.outDir = product.buildDirectory; cmd.sourceCode = function() { for (var i = 0; i < outputs.compiled_typescript.length; ++i) { var output = outputs.compiled_typescript[i]; var intermediatePath = FileInfo.path(FileInfo.relativePath(product.moduleProperty("nodejs", "compiledIntermediateDir"), output.filePath)); var originalFilePath = FileInfo.joinPaths(outDir, intermediatePath, output.fileName); File.copy(originalFilePath, output.filePath); File.remove(originalFilePath); } }; cmds.push(cmd); return cmds; } } } qbs-src-1.4.5/share/qbs/modules/typescript/qbs-tsc-scan/000077500000000000000000000000001266132464200231445ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/modules/typescript/qbs-tsc-scan/.gitignore000066400000000000000000000001611266132464200251320ustar00rootroot00000000000000# Visual Studio Code IDE tsconfig.json qbs-tsc-scan.js typings/node/node.d.ts typings/typescript/typescript.d.ts qbs-src-1.4.5/share/qbs/modules/typescript/qbs-tsc-scan/qbs-tsc-scan.ts000066400000000000000000000051671266132464200260230ustar00rootroot00000000000000import ts = require("typescript"); declare var process: any; export namespace io.qt.qbs { export class Artifact { filePath: string; fileTags: string[]; } export namespace tools { export namespace utils { function stringEndsWith(s: string, e: string) { return s.slice(-e.length) === e; } export function artifactFromFilePath(filePath: string): Artifact { var fileTags: string[] = []; if (stringEndsWith(filePath, ".js.map")) { fileTags.push("source_map"); } else if (stringEndsWith(filePath, ".js")) { fileTags.push("js", "compiled_typescript"); } else if (stringEndsWith(filePath, ".d.ts")) { fileTags.push("typescript_declaration"); } return { filePath: filePath, fileTags: fileTags }; } } function compileInternal(fileNames: string[], options: ts.CompilerOptions): qbs.Artifact[] { var outputArtifacts: qbs.Artifact[] = []; var program = ts.createProgram(fileNames, options); var emitResult = program.emit(undefined, filePath => { outputArtifacts.push(utils.artifactFromFilePath(filePath)); }); var allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); allDiagnostics.forEach(diagnostic => { var message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); if (diagnostic.file) { var { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); console.error(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); } else { console.error(message); } }); return emitResult.emitSkipped ? undefined : outputArtifacts; } export function compile(commandLineArguments: string[]): qbs.Artifact[] { var parsedCommandLine = ts.parseCommandLine(commandLineArguments); return compileInternal(parsedCommandLine.fileNames, parsedCommandLine.options); } export function TypeScriptCompilerScannerToolMain(): void { var outputArtifacts = compile(process.argv.slice(2)); if (outputArtifacts !== undefined) { console.log(JSON.stringify(outputArtifacts)); } else { process.exit(1); } } } } io.qt.qbs.tools.TypeScriptCompilerScannerToolMain(); qbs-src-1.4.5/share/qbs/modules/typescript/typescript.js000066400000000000000000000237311266132464200234200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ var ModUtils = loadExtension("qbs.ModUtils"); var Process = loadExtension("qbs.Process"); function findTscVersion(compilerFilePath, nodejsPath) { var p = new Process(); try { if (nodejsPath) p.setEnv("PATH", nodejsPath); p.exec(compilerFilePath, ["--version"]); var re = /^(?:message TS6029: )?Version (([0-9]+(?:\.[0-9]+){1,3})(?:-(.+?))?)$/m; var match = p.readStdOut().trim().match(re); if (match !== null) return match; } finally { p.close(); } } function tscArguments(product, inputs) { var i; var args = []; if (ModUtils.moduleProperty(product, "warningLevel") === "pedantic") { args.push("--noImplicitAny"); } var targetVersion = ModUtils.moduleProperty(product, "targetVersion"); if (targetVersion) { args.push("--target"); args.push(targetVersion); } var moduleLoader = ModUtils.moduleProperty(product, "moduleLoader"); if (moduleLoader) { args.push("--module"); args.push(moduleLoader); } if (ModUtils.moduleProperty(product, "stripComments")) { args.push("--removeComments"); } if (ModUtils.moduleProperty(product, "generateDeclarations")) { args.push("--declaration"); } if (ModUtils.moduleProperty(product, "generateSourceMaps")) { args.push("--sourcemap"); } // User-supplied flags var flags = ModUtils.moduleProperty(product, "compilerFlags"); for (i in flags) { args.push(flags[i]); } if (supportsModernFeatures(product)) { args.push("--rootDir", product.sourceDirectory); } args.push("--outDir", product.buildDirectory); if (ModUtils.moduleProperty(product, "singleFile")) { args.push("--out", FileInfo.joinPaths(product.destinationDirectory, product.targetName) + ".js"); } if (inputs.typescript_declaration) { for (i = 0; i < inputs.typescript_declaration.length; ++i) { args.push(inputs.typescript_declaration[i].filePath); } } if (inputs.typescript) { for (i = 0; i < inputs.typescript.length; ++i) { args.push(inputs.typescript[i].filePath); } } if (inputs["typescript.typescript-internal"]) { for (i = 0; i < inputs["typescript.typescript-internal"].length; ++i) { args.push(inputs["typescript.typescript-internal"][i].filePath); } } return args; } function outputArtifacts(product, inputs) { if (!supportsModernFeatures(product)) { print("WARNING: Qbs does not properly support TypeScript versions prior to 1.5 due to " + "severe limitations in dependency tracking. This is TypeScript version " + ModUtils.moduleProperty(product, "version") + ". It is strongly recommended that " + "you upgrade TypeScript, or continue at your own risk."); return legacyOutputArtifacts(product, inputs); } var process; try { process = new Process(); process.setEnv("NODE_PATH", ModUtils.moduleProperty(product, "toolchainInstallPath")); process.exec(product.moduleProperty("nodejs", "interpreterFilePath"), [FileInfo.joinPaths(product.buildDirectory, ".io.qt.qbs.internal.typescript", "qbs-tsc-scan.js")] .concat(tscArguments(product, inputs)), true); var artifacts = JSON.parse(process.readStdOut()); // Find and tag the "main" output file var applicationFile = product.moduleProperty("nodejs", "applicationFile"); if (applicationFile) { var i, appIndex = -1; if (product.moduleProperty("typescript", "singleFile")) { for (i = 0; i < artifacts.length; ++i) { if (artifacts[i].fileTags.contains("compiled_typescript")) { appIndex = i; break; } } } else { var expected = FileInfo.relativePath(product.sourceDirectory, applicationFile); if (!expected.endsWith(".ts")) // tsc doesn't allow this anyways, so it's a perfectly reasonable restriction throw "TypeScript source file name '" + applicationFile + "' does not end with .ts"; expected = expected.slice(0, -2) + "js"; for (i = 0; i < artifacts.length; ++i) { if (expected === FileInfo.relativePath(product.buildDirectory, artifacts[i].filePath)) { appIndex = i; break; } } } if (appIndex === -1 || !artifacts[appIndex].fileTags.contains("compiled_typescript")) throw "nodejs.applicationFile was set, but Qbs couldn't find the compiled " + "JavaScript file corresponding to '" + applicationFile + "'"; artifacts[appIndex].fileTags = artifacts[appIndex].fileTags.concat(["application_js"]); } return artifacts; } finally { if (process) process.close(); } } function legacyOutputArtifacts(product, inputs) { var artifacts = []; if (!inputs.typescript) { return artifacts; } var jsTags = ["js", "compiled_typescript"]; var filePath = FileInfo.joinPaths(product.destinationDirectory, product.targetName); if (product.moduleProperty("typescript", "singleFile")) { // We could check // if (product.moduleProperty("nodejs", "applicationFile") === inputs.typescript[i].filePath) // but since we're compiling to a single file there's no need to state it explicitly jsTags.push("application_js"); artifacts.push({fileTags: jsTags, filePath: FileInfo.joinPaths( product.moduleProperty("nodejs", "compiledIntermediateDir"), product.targetName + ".js")}); if (product.moduleProperty("typescript", "generateDeclarations")) { artifacts.push({fileTags: ["typescript_declaration"], filePath: filePath + ".d.ts"}); } if (product.moduleProperty("typescript", "generateSourceMaps")) { artifacts.push({fileTags: ["source_map"], filePath: filePath + ".js.map"}); } } else { for (var i = 0; i < inputs.typescript.length; ++i) { jsTags = ["js", "compiled_typescript"]; if (product.moduleProperty("nodejs", "applicationFile") === inputs.typescript[i].filePath) jsTags.push("application_js"); var intermediatePath = FileInfo.path(FileInfo.relativePath( product.sourceDirectory, inputs.typescript[i].filePath)); var baseName = FileInfo.baseName(inputs.typescript[i].fileName); filePath = FileInfo.joinPaths(product.destinationDirectory, intermediatePath, baseName); artifacts.push({fileTags: jsTags, filePath: FileInfo.joinPaths( product.moduleProperty("nodejs", "compiledIntermediateDir"), intermediatePath, baseName + ".js")}); if (product.moduleProperty("typescript", "generateDeclarations")) { artifacts.push({fileTags: ["typescript_declaration"], filePath: filePath + ".d.ts"}); } if (product.moduleProperty("typescript", "generateSourceMaps")) { artifacts.push({fileTags: ["source_map"], filePath: filePath + ".js.map"}); } } } return artifacts; } function supportsModernFeatures(product) { var compilerVersionMajor = ModUtils.moduleProperty(product, "versionMajor"); if (compilerVersionMajor === 1) { if (ModUtils.moduleProperty(product, "versionMinor") >= 5) { return true; } } return compilerVersionMajor > 1; } qbs-src-1.4.5/share/qbs/modules/wix/000077500000000000000000000000001266132464200172475ustar00rootroot00000000000000qbs-src-1.4.5/share/qbs/modules/wix/WiXModule.qbs000066400000000000000000000423671266132464200216470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ import qbs import qbs.File import qbs.FileInfo import qbs.ModUtils Module { condition: qbs.targetOS.contains("windows") property path toolchainInstallPath: qbs.getNativeSetting(registryKey, "InstallFolder") property path toolchainInstallRoot: qbs.getNativeSetting(registryKey, "InstallRoot") property string version: qbs.getNativeSetting(registryKey, "ProductVersion") property var versionParts: version ? version.split('.').map(function(item) { return parseInt(item, 10); }) : [] property int versionMajor: versionParts[0] property int versionMinor: versionParts[1] property int versionPatch: versionParts[2] property int versionBuild: versionParts[3] property string compilerName: "candle.exe" property string compilerPath: FileInfo.joinPaths(toolchainInstallRoot, compilerName) property string linkerName: "light.exe" property string linkerPath: FileInfo.joinPaths(toolchainInstallRoot, linkerName) property string warningLevel: "normal" PropertyOptions { name: "warningLevel" allowedValues: ["none", "normal", "pedantic"] } property bool debugInformation: qbs.debugInformation property bool treatWarningsAsErrors: false property bool verboseOutput: false PropertyOptions { name: "verboseOutput" description: "display verbose output from the compiler and linker" } property bool visualStudioCompatibility: true PropertyOptions { name: "visualStudioCompatibility" description: "whether to define most of the same variables as " + "Visual Studio when using the Candle compiler" } property bool enableQbsDefines: true PropertyOptions { name: "enableQbsDefines" description: "built-in variables that are defined when using the Candle compiler" } property pathList includePaths PropertyOptions { name: "includePaths" description: "directories to add to the include search path" } property stringList defines PropertyOptions { name: "defines" description: "variables that are defined when using the Candle compiler" } property stringList compilerFlags PropertyOptions { name: "compilerFlags" description: "additional flags for the Candle compiler" } property stringList linkerFlags PropertyOptions { name: "linkerFlags" description: "additional flags for the Light linker" } property stringList cultures PropertyOptions { name: "cultures" description: "the list of localizations to build the MSI for; leave undefined to build all localizations" } property stringList extensions: product.type.contains("wixsetup") ? ["WixBalExtension"] : [] // default to WiX Standard Bootstrapper extension // private properties property string targetSuffix: { if (product.type.contains("msi")) { return windowsInstallerSuffix; } else if (product.type.contains("wixsetup")) { return executableSuffix; } } // MSI/MSM package validation only works natively on Windows property bool enablePackageValidation: qbs.hostOS.contains("windows") property string executableSuffix: ".exe" property string windowsInstallerSuffix: ".msi" property string registryKey: { var knownVersions = [ "4.0", "3.10", "3.9", "3.8", "3.7", "3.6", "3.5", "3.0", "2.0" ]; var keyNative = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Installer XML\\"; var keyWoW64 = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows Installer XML\\"; for (i in knownVersions) { if (qbs.getNativeSetting(keyNative + knownVersions[i], "ProductVersion")) return keyNative + knownVersions[i]; if (qbs.getNativeSetting(keyWoW64 + knownVersions[i], "ProductVersion")) return keyWoW64 + knownVersions[i]; } } validate: { var validator = new ModUtils.PropertyValidator("wix"); validator.setRequiredProperty("toolchainInstallPath", toolchainInstallPath); validator.setRequiredProperty("toolchainInstallRoot", toolchainInstallRoot); validator.setRequiredProperty("version", version); validator.setRequiredProperty("versionMajor", versionMajor); validator.setRequiredProperty("versionMinor", versionMinor); validator.setRequiredProperty("versionPatch", versionPatch); validator.addVersionValidator("version", version, 3, 4); validator.addRangeValidator("versionMajor", versionMajor, 1); validator.addRangeValidator("versionMinor", versionMinor, 0); validator.addRangeValidator("versionPatch", versionPatch, 0); if (versionParts && versionParts.length >= 4) { validator.setRequiredProperty("versionBuild", versionBuild); validator.addRangeValidator("versionBuild", versionBuild, 0); } validator.validate(); } setupBuildEnvironment: { var v = new ModUtils.EnvironmentVariable("PATH", qbs.pathListSeparator, true); v.prepend(toolchainInstallPath); v.prepend(toolchainInstallRoot); v.set(); } // WiX Include Files FileTagger { patterns: ["*.wxi"] fileTags: ["wxi"] } // WiX Localization Files FileTagger { patterns: ["*.wxl"] fileTags: ["wxl"] } // WiX Source Files FileTagger { patterns: ["*.wxs"] fileTags: ["wxs"] } Rule { id: candleCompiler inputs: ["wxs"] auxiliaryInputs: ['wxi'] Artifact { fileTags: ["wixobj"] filePath: FileInfo.joinPaths(".obj", qbs.getHash(input.baseDir), FileInfo.baseName(input.fileName) + ".wixobj") } prepare: { var i; var args = ["-nologo"]; if (ModUtils.moduleProperty(input, "warningLevel") === "none") { args.push("-sw"); } else { if (ModUtils.moduleProperty(input, "warningLevel") === "pedantic") { args.push("-pedantic"); } if (ModUtils.moduleProperty(input, "treatWarningsAsErrors")) { args.push("-wx"); } } if (ModUtils.moduleProperty(input, "verboseOutput")) { args.push("-v"); } var arch = product.moduleProperty("qbs", "architecture"); if (!["x86", "x86_64", "ia64", "arm"].contains(arch)) { // http://wixtoolset.org/documentation/manual/v3/xsd/wix/package.html throw("WiX: unsupported architecture '" + arch + "'"); } // QBS uses "x86_64", Microsoft uses "x64" if (arch === "x86_64") { arch = "x64"; } // Visual Studio defines these variables along with various solution and project names and paths; // we'll pass most of them to ease compatibility between QBS and WiX projects originally created // using Visual Studio. The only definitions we don't pass are the ones which make no sense at all // in QBS, like the solution and project directories since they do not exist. if (ModUtils.moduleProperty(input, "visualStudioCompatibility")) { var toolchain = product.moduleProperties("qbs", "toolchain"); var toolchainInstallPath = product.moduleProperty("cpp", "toolchainInstallPath"); if (toolchain && toolchain.contains("msvc") && toolchainInstallPath) { var vcDir = toolchainInstallPath.replace(/[\\/]bin$/i, ""); var vcRootDir = vcDir.replace(/[\\/]VC$/i, ""); args.push("-dDevEnvDir=" + FileInfo.toWindowsSeparators(FileInfo.joinPaths(vcRootDir, 'Common7', 'IDE'))); } var buildVariant = product.moduleProperty("qbs", "buildVariant"); if (buildVariant === "debug") { args.push("-dDebug"); args.push("-dConfiguration=Debug"); } else if (buildVariant === "release") { // VS doesn't define "Release" args.push("-dConfiguration=Release"); } var productTargetExt = ModUtils.moduleProperty(input, "targetSuffix"); if (!productTargetExt) { throw("WiX: Unsupported product type '" + product.type + "'"); } var builtBinaryFilePath = FileInfo.joinPaths(product.buildDirectory, product.destinationDirectory, product.targetName + productTargetExt); args.push("-dOutDir=" + FileInfo.toWindowsSeparators(FileInfo.path(builtBinaryFilePath))); // in VS, relative to the project file by default args.push("-dPlatform=" + arch); args.push("-dProjectName=" + project.name); args.push("-dTargetDir=" + FileInfo.toWindowsSeparators(FileInfo.path(builtBinaryFilePath))); // in VS, an absolute path args.push("-dTargetExt=" + productTargetExt); args.push("-dTargetFileName=" + product.targetName + productTargetExt); args.push("-dTargetName=" + product.targetName); args.push("-dTargetPath=" + FileInfo.toWindowsSeparators(builtBinaryFilePath)); } var includePaths = ModUtils.moduleProperties(input, "includePaths"); for (i in includePaths) { args.push("-I" + includePaths[i]); } var enableQbsDefines = ModUtils.moduleProperty(input, "enableQbsDefines") if (enableQbsDefines) { var map = { "project.": project, "product.": product }; for (var prefix in map) { var obj = map[prefix]; for (var prop in obj) { var val = obj[prop]; if (typeof val !== 'function' && typeof val !== 'object' && !prop.startsWith("_")) { args.push("-d" + prefix + prop + "=" + val); } } } // Helper define for alternating between 32-bit and 64-bit logic if (arch === "x64" || arch === "ia64") { args.push("-dWin64"); } } // User-supplied defines var defines = ModUtils.moduleProperties(input, "defines"); for (i in defines) { args.push("-d" + defines[i]); } // User-supplied flags var flags = ModUtils.moduleProperties(input, "compilerFlags"); for (i in flags) { args.push(flags[i]); } args.push("-out"); args.push(FileInfo.toWindowsSeparators(output.filePath)); args.push("-arch"); args.push(arch); var extensions = ModUtils.moduleProperties(input, "extensions"); for (i in extensions) { args.push("-ext"); args.push(extensions[i]); } args.push(FileInfo.toWindowsSeparators(input.filePath)); var cmd = new Command(ModUtils.moduleProperty(product, "compilerPath"), args); cmd.description = "compiling " + input.fileName; cmd.highlight = "compiler"; cmd.workingDirectory = FileInfo.path(output.filePath); return cmd; } } Rule { id: lightLinker multiplex: true inputs: ["wixobj", "wxl"] outputArtifacts: { var artifacts = []; if (product.type.contains("wixsetup")) { artifacts.push({ fileTags: ["wixsetup", "application"], filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ModUtils.moduleProperty(product, "executableSuffix")) }); } if (product.type.contains("msi")) { artifacts.push({ fileTags: ["msi"], filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ModUtils.moduleProperty(product, "windowsInstallerSuffix")) }); } if (ModUtils.moduleProperty(product, "debugInformation")) { artifacts.push({ fileTags: ["wixpdb"], filePath: FileInfo.joinPaths(product.destinationDirectory, product.targetName + ".wixpdb") }); } return artifacts; } outputFileTags: ["application", "msi", "wixpdb", "wixsetup"] prepare: { var i; var primaryOutput; if (product.type.contains("wixsetup")) { primaryOutput = outputs.wixsetup[0]; } else if (product.type.contains("msi")) { primaryOutput = outputs.msi[0]; } else { throw("WiX: Unsupported product type '" + product.type + "'"); } var args = ["-nologo"]; if (!ModUtils.moduleProperty(product, "enablePackageValidation")) { args.push("-sval"); } if (ModUtils.moduleProperty(product, "warningLevel") === "none") { args.push("-sw"); } else { if (ModUtils.moduleProperty(product, "warningLevel") === "pedantic") { args.push("-pedantic"); } if (ModUtils.moduleProperty(product, "treatWarningsAsErrors")) { args.push("-wx"); } } if (ModUtils.moduleProperty(product, "verboseOutput")) { args.push("-v"); } args.push("-out"); args.push(FileInfo.toWindowsSeparators(primaryOutput.filePath)); if (ModUtils.moduleProperty(product, "debugInformation")) { args.push("-pdbout"); args.push(FileInfo.toWindowsSeparators(outputs.wixpdb[0].filePath)); } else { args.push("-spdb"); } var extensions = ModUtils.moduleProperties(product, "extensions"); for (i in extensions) { args.push("-ext"); args.push(extensions[i]); } for (i in inputs.wxl) { args.push("-loc"); args.push(FileInfo.toWindowsSeparators(inputs.wxl[i].filePath)); } if (product.type.contains("msi")) { var cultures = ModUtils.moduleProperties(product, "cultures"); args.push("-cultures:" + (cultures && cultures.length > 0 ? cultures.join(";") : "null")); } // User-supplied flags var flags = ModUtils.moduleProperties(product, "linkerFlags"); for (i in flags) { args.push(flags[i]); } for (i in inputs.wixobj) { args.push(FileInfo.toWindowsSeparators(inputs.wixobj[i].filePath)); } var cmd = new Command(ModUtils.moduleProperty(product, "linkerPath"), args); cmd.description = "linking " + primaryOutput.fileName; cmd.highlight = "linker"; cmd.workingDirectory = FileInfo.path(primaryOutput.filePath); return cmd; } } } qbs-src-1.4.5/share/share.qbs000066400000000000000000000023311266132464200160130ustar00rootroot00000000000000import qbs import qbs.File import qbs.FileInfo Product { name: "qbs resources" type: ["copied qbs resources"] Group { name: "Modules and imports" files: ["qbs/**/*"] fileTags: ["qbs resources"] qbs.install: true qbs.installDir: project.resourcesInstallDir + "/share" qbs.installSourceBase: "." } Group { name: "Examples as resources" files: ["../examples/**/*"] fileTags: [] qbs.install: true qbs.installDir: project.resourcesInstallDir + "/share/qbs" qbs.installSourceBase: ".." } Rule { inputs: ["qbs resources"] Artifact { filePath: FileInfo.joinPaths(project.buildDirectory, project.resourcesInstallDir, "share", FileInfo.relativePath(product.sourceDirectory, input.filePath)) fileTags: ["copied qbs resources"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Copying resource " + input.fileName + " to build directory."; cmd.highlight = "codegen"; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } } } qbs-src-1.4.5/src/000077500000000000000000000000001266132464200136705ustar00rootroot00000000000000qbs-src-1.4.5/src/app/000077500000000000000000000000001266132464200144505ustar00rootroot00000000000000qbs-src-1.4.5/src/app/app.pri000066400000000000000000000011311266132464200157400ustar00rootroot00000000000000include(../install_prefix.pri) QT = core TEMPLATE = app !isEmpty(QBS_APPS_DESTDIR):DESTDIR = $${QBS_APPS_DESTDIR} else:DESTDIR = ../../../bin !isEmpty(QBS_APPS_RPATH_DIR) { linux-*:QMAKE_LFLAGS += -Wl,-z,origin \'-Wl,-rpath,$${QBS_APPS_RPATH_DIR}\' macx:QMAKE_LFLAGS += -Wl,-rpath,$${QBS_APPS_RPATH_DIR} } CONFIG += console CONFIG -= app_bundle CONFIG += c++11 include($${PWD}/../lib/corelib/use_corelib.pri) include($${PWD}/shared/logging/logging.pri) !isEmpty(QBS_APPS_INSTALL_DIR):target.path = $${QBS_APPS_INSTALL_DIR} else:target.path = $${QBS_INSTALL_PREFIX}/bin INSTALLS += target qbs-src-1.4.5/src/app/app.pro000066400000000000000000000002731266132464200157540ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS =\ qbs\ qbs-setup-android \ qbs-setup-toolchains \ qbs-setup-qt \ config \ qbs-qmltypes !isEmpty(QT.widgets.name):SUBDIRS += config-ui qbs-src-1.4.5/src/app/apps.qbs000066400000000000000000000005051266132464200161220ustar00rootroot00000000000000import qbs Project { references: [ "config/config.qbs", "config-ui/config-ui.qbs", "qbs/qbs.qbs", "qbs-qmltypes/qbs-qmltypes.qbs", "qbs-setup-android/qbs-setup-android.qbs", "qbs-setup-qt/qbs-setup-qt.qbs", "qbs-setup-toolchains/qbs-setup-toolchains.qbs", ] } qbs-src-1.4.5/src/app/config-ui/000077500000000000000000000000001266132464200163305ustar00rootroot00000000000000qbs-src-1.4.5/src/app/config-ui/Info.plist000066400000000000000000000006241266132464200203020ustar00rootroot00000000000000 CFBundleIdentifier org.qt-project.qbs-config-ui CFBundleInfoDictionaryVersion 6.0 CFBundleName Qbs Settings qbs-src-1.4.5/src/app/config-ui/commandlineparser.cpp000066400000000000000000000073371266132464200225510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "commandlineparser.h" #include #include #include using qbs::Internal::Tr; static QString helpOptionShort() { return QLatin1String("-h"); } static QString helpOptionLong() { return QLatin1String("--help"); } static QString settingsDirOption() { return QLatin1String("--settings-dir"); } void CommandLineParser::parse(const QStringList &commandLine) { m_commandLine = commandLine; Q_ASSERT(!m_commandLine.isEmpty()); m_command = QFileInfo(m_commandLine.takeFirst()).fileName(); m_helpRequested = false; m_settingsDir.clear(); if (m_commandLine.isEmpty()) return; const QString &arg = m_commandLine.first(); if (arg == helpOptionShort() || arg == helpOptionLong()) { m_commandLine.removeFirst(); m_helpRequested = true; } else if (arg == settingsDirOption()) { m_commandLine.removeFirst(); assignOptionArgument(settingsDirOption(), m_settingsDir); } if (!m_commandLine.isEmpty()) complainAboutExtraArguments(); } void CommandLineParser::throwError(const QString &message) { qbs::ErrorInfo error(Tr::tr("Syntax error: %1").arg(message)); error.append(usageString()); throw error; } QString CommandLineParser::usageString() const { QString s = Tr::tr("This tool displays qbs settings in a GUI.\n" "If you have more than a few settings, this might be preferable to " "plain \"qbs config\", as it presents a hierarchical view.\n"); s += Tr::tr("Usage:\n"); s += Tr::tr(" %1 [%2 ] [%3|%4]\n") .arg(m_command, settingsDirOption(), helpOptionShort(), helpOptionLong()); return s; } void CommandLineParser::assignOptionArgument(const QString &option, QString &argument) { if (m_commandLine.isEmpty()) throwError(Tr::tr("Option '%1' needs an argument.").arg(option)); argument = m_commandLine.takeFirst(); if (argument.isEmpty()) throwError(Tr::tr("Argument for option '%1' must not be empty.").arg(option)); } void CommandLineParser::complainAboutExtraArguments() { throwError(Tr::tr("Extraneous command-line arguments '%1'.") .arg(m_commandLine.join(QLatin1Char(' ')))); } qbs-src-1.4.5/src/app/config-ui/commandlineparser.h000066400000000000000000000041721266132464200222100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_CONFIGUI_COMMANDLINEPARSER_H #define QBS_CONFIGUI_COMMANDLINEPARSER_H #include class CommandLineParser { public: void parse(const QStringList &commandLine); bool helpRequested() const { return m_helpRequested; } QString settingsDir() const { return m_settingsDir; } QString usageString() const; private: void throwError(const QString &message); void assignOptionArgument(const QString &option, QString &argument); void complainAboutExtraArguments(); bool m_helpRequested; QString m_settingsDir; QStringList m_commandLine; QString m_command; }; #endif // Include guard qbs-src-1.4.5/src/app/config-ui/config-ui.pro000066400000000000000000000005451266132464200207360ustar00rootroot00000000000000include(../app.pri) CONFIG -= console QT += gui widgets TARGET = qbs-config-ui HEADERS += \ commandlineparser.h \ mainwindow.h SOURCES += \ commandlineparser.cpp \ main.cpp \ mainwindow.cpp OTHER_FILES += \ Info.plist mac: QMAKE_LFLAGS += -sectcreate __TEXT __info_plist $$shell_quote($$PWD/Info.plist) FORMS += mainwindow.ui qbs-src-1.4.5/src/app/config-ui/config-ui.qbs000066400000000000000000000006121266132464200207160ustar00rootroot00000000000000import qbs 1.0 QbsApp { Depends { name: "Qt.widgets" } name: "qbs-config-ui" consoleApplication: false files: [ "commandlineparser.cpp", "commandlineparser.h", "main.cpp", "mainwindow.cpp", "mainwindow.h", "mainwindow.ui", ] Depends { name: "bundle" } bundle.isBundle: false bundle.infoPlistFile: "Info.plist" } qbs-src-1.4.5/src/app/config-ui/main.cpp000066400000000000000000000043011266132464200177560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mainwindow.h" #include "commandlineparser.h" #include #include #include #include #include using qbs::Internal::Tr; int main(int argc, char *argv[]) { QApplication app(argc, argv); CommandLineParser clParser; try { clParser.parse(app.arguments()); if (clParser.helpRequested()) { std::cout << qPrintable(clParser.usageString()); return EXIT_SUCCESS; } } catch (const qbs::ErrorInfo &error) { std::cerr << qPrintable(error.toString()); return EXIT_FAILURE; } MainWindow mw(clParser.settingsDir()); mw.show(); return app.exec(); } qbs-src-1.4.5/src/app/config-ui/mainwindow.cpp000066400000000000000000000146431266132464200212200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "mainwindow.h" #include "ui_mainwindow.h" #include #include #include #include #include #include #include #include #include #include MainWindow::MainWindow(const QString &settingsDir, QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); m_model = new qbs::SettingsModel(settingsDir, this); ui->treeView->setModel(m_model); ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->treeView, SIGNAL(expanded(QModelIndex)), SLOT(adjustColumns())); connect(ui->treeView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(provideContextMenu(QPoint))); adjustColumns(); QMenu * const fileMenu = menuBar()->addMenu(tr("&File")); QMenu * const viewMenu = menuBar()->addMenu(tr("&View")); QAction * const reloadAction = new QAction(tr("&Reload"), this); reloadAction->setShortcut(QKeySequence::Refresh); connect(reloadAction, SIGNAL(triggered()), SLOT(reloadSettings())); QAction * const saveAction = new QAction(tr("&Save"), this); saveAction->setShortcut(QKeySequence::Save); connect(saveAction, SIGNAL(triggered()), SLOT(saveSettings())); QAction * const expandAllAction = new QAction(tr("&Expand All"), this); expandAllAction->setShortcut(Qt::CTRL | Qt::Key_E); connect(expandAllAction, SIGNAL(triggered()), SLOT(expandAll())); QAction * const collapseAllAction = new QAction(tr("C&ollapse All"), this); collapseAllAction->setShortcut(Qt::CTRL | Qt::Key_O); connect(collapseAllAction, SIGNAL(triggered()), SLOT(collapseAll())); QAction * const exitAction = new QAction(tr("E&xit"), this); exitAction->setShortcut(QKeySequence::Quit); exitAction->setMenuRole(QAction::QuitRole); connect(exitAction, SIGNAL(triggered()), SLOT(exit())); fileMenu->addAction(reloadAction); fileMenu->addAction(saveAction); fileMenu->addSeparator(); fileMenu->addAction(exitAction); viewMenu->addAction(expandAllAction); viewMenu->addAction(collapseAllAction); ui->treeView->installEventFilter(this); } MainWindow::~MainWindow() { delete ui; } void MainWindow::adjustColumns() { for (int column = 0; column < m_model->columnCount(); ++column) ui->treeView->resizeColumnToContents(column); } void MainWindow::expandAll() { ui->treeView->expandAll(); adjustColumns(); } void MainWindow::collapseAll() { ui->treeView->collapseAll(); adjustColumns(); } void MainWindow::reloadSettings() { if (m_model->hasUnsavedChanges()) { const QMessageBox::StandardButton answer = QMessageBox::question(this, tr("Unsaved Changes"), tr("You have unsaved changes. Do you want to discard them?")); if (answer != QMessageBox::Yes) return; } m_model->reload(); } void MainWindow::saveSettings() { m_model->save(); } void MainWindow::exit() { if (m_model->hasUnsavedChanges()) { const QMessageBox::StandardButton answer = QMessageBox::question(this, tr("Unsaved Changes"), tr("You have unsaved changes. Do you want to save them now?")); if (answer == QMessageBox::Yes) m_model->save(); } qApp->quit(); } void MainWindow::provideContextMenu(const QPoint &pos) { const QModelIndex index = ui->treeView->indexAt(pos); if (index.isValid() && index.column() != m_model->keyColumn()) return; const QString settingsKey = m_model->data(index).toString(); QMenu contextMenu; QAction addKeyAction(this); QAction removeKeyAction(this); if (index.isValid()) { addKeyAction.setText(tr("Add new key below '%1'").arg(settingsKey)); removeKeyAction.setText(tr("Remove key '%1' and all its sub-keys").arg(settingsKey)); contextMenu.addAction(&addKeyAction); contextMenu.addAction(&removeKeyAction); } else { addKeyAction.setText(tr("Add new top-level key")); contextMenu.addAction(&addKeyAction); } const QAction *action = contextMenu.exec(ui->treeView->mapToGlobal(pos)); if (action == &addKeyAction) m_model->addNewKey(index); else if (action == &removeKeyAction) m_model->removeKey(index); } bool MainWindow::eventFilter(QObject *watched, QEvent *event) { if (ui->treeView->hasFocus() && event->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast(event); if (keyEvent->matches(QKeySequence::Delete)) { const QModelIndexList indexes = ui->treeView->selectionModel()->selectedRows(); if (indexes.count() == 1) { const QModelIndex index = indexes.first(); if (index.isValid()) { m_model->removeKey(index); return true; } } } } return QMainWindow::eventFilter(watched, event); } qbs-src-1.4.5/src/app/config-ui/mainwindow.h000066400000000000000000000042641266132464200206630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include namespace qbs { class SettingsModel; } QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } class QPoint; QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(const QString &settingsDir, QWidget *parent = 0); ~MainWindow(); bool eventFilter(QObject *watched, QEvent *event); private slots: void adjustColumns(); void expandAll(); void collapseAll(); void reloadSettings(); void saveSettings(); void exit(); void provideContextMenu(const QPoint &pos); private: Ui::MainWindow *ui; qbs::SettingsModel *m_model; }; #endif // MAINWINDOW_H qbs-src-1.4.5/src/app/config-ui/mainwindow.ui000066400000000000000000000015141266132464200210440ustar00rootroot00000000000000 MainWindow 0 0 800 600 Qbs Settings 0 0 800 27 qbs-src-1.4.5/src/app/config/000077500000000000000000000000001266132464200157155ustar00rootroot00000000000000qbs-src-1.4.5/src/app/config/config.pro000066400000000000000000000003541266132464200177060ustar00rootroot00000000000000include(../app.pri) TARGET = qbs-config SOURCES += \ configcommandexecutor.cpp \ configcommandlineparser.cpp \ configmain.cpp HEADERS += \ configcommand.h \ configcommandexecutor.h \ configcommandlineparser.h qbs-src-1.4.5/src/app/config/config.qbs000066400000000000000000000004161266132464200176720ustar00rootroot00000000000000import qbs 1.0 QbsApp { name: "qbs-config" files: [ "configcommand.h", "configcommandexecutor.cpp", "configcommandexecutor.h", "configcommandlineparser.cpp", "configcommandlineparser.h", "configmain.cpp" ] } qbs-src-1.4.5/src/app/config/configcommand.h000066400000000000000000000036001266132464200206710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef CONFIGCOMMAND_H #define CONFIGCOMMAND_H #include #include #include class ConfigCommand { public: enum Command { CfgSet, CfgUnset, CfgList, CfgExport, CfgImport, CfgNone }; ConfigCommand() : command(CfgNone) {} Command command; QStringList varNames; QString varValue; QString fileName; }; #endif // CONFIGCOMMAND_H qbs-src-1.4.5/src/app/config/configcommandexecutor.cpp000066400000000000000000000123331266132464200230060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "configcommandexecutor.h" #include "configcommand.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include using namespace qbs; ConfigCommandExecutor::ConfigCommandExecutor(Settings *settings) : m_settings(settings) { } void ConfigCommandExecutor::execute(const ConfigCommand &command) { switch (command.command) { case ConfigCommand::CfgList: printSettings(command); break; case ConfigCommand::CfgSet: setValue(command.varNames.first(), command.varValue); break; case ConfigCommand::CfgUnset: foreach (const QString &varName, command.varNames) m_settings->remove(varName); break; case ConfigCommand::CfgExport: exportSettings(command.fileName); break; case ConfigCommand::CfgImport: // Display old and new settings, in case import fails or user accidentally nukes everything printf("old "); // Will end up as "old settings:" printSettings(command); importSettings(command.fileName); printf("\nnew "); printSettings(command); break; case ConfigCommand::CfgNone: qFatal("%s: Impossible command value.", Q_FUNC_INFO); break; } } void ConfigCommandExecutor::setValue(const QString &key, const QString &rawInput) { m_settings->setValue(key, representationToSettingsValue(rawInput)); } void ConfigCommandExecutor::printSettings(const ConfigCommand &command) { if (command.varNames.isEmpty()) { foreach (const QString &key, m_settings->allKeys()) printOneSetting(key); } else { foreach (const QString &parentKey, command.varNames) { if (m_settings->value(parentKey).isValid()) { // Key is a leaf. printOneSetting(parentKey); } else { // Key is a node. foreach (const QString &key, m_settings->allKeysWithPrefix(parentKey)) printOneSetting(parentKey + QLatin1Char('.') + key); } } } } void ConfigCommandExecutor::printOneSetting(const QString &key) { printf("%s: %s\n", qPrintable(key), qPrintable(qbs::settingsValueToRepresentation(m_settings->value(key)))); } void ConfigCommandExecutor::exportSettings(const QString &filename) { QFile file(filename); if (!file.open(QFile::Truncate | QFile::WriteOnly | QFile::Text)) { throw ErrorInfo(tr("Could not open file '%1' for writing: %2") .arg(QDir::toNativeSeparators(filename), file.errorString())); } QTextStream stream(&file); stream.setCodec("UTF-8"); foreach (const QString &key, m_settings->allKeys()) stream << key << ": " << qbs::settingsValueToRepresentation(m_settings->value(key)) << endl; } void ConfigCommandExecutor::importSettings(const QString &filename) { QFile file(filename); if (!file.open(QFile::ReadOnly | QFile::Text)) { throw ErrorInfo(tr("Could not open file '%1' for reading: %2") .arg(QDir::toNativeSeparators(filename), file.errorString())); } // Remove all current settings foreach (const QString &key, m_settings->allKeys()) m_settings->remove(key); QTextStream stream(&file); stream.setCodec("UTF-8"); while (!stream.atEnd()) { QString line = stream.readLine(); int colon = line.indexOf(QLatin1Char(':')); if (colon >= 0 && !line.startsWith(QLatin1Char('#'))) { const QString key = line.left(colon).trimmed(); const QString value = line.mid(colon + 1).trimmed(); m_settings->setValue(key, representationToSettingsValue(value)); } } } qbs-src-1.4.5/src/app/config/configcommandexecutor.h000066400000000000000000000042411266132464200224520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef CONFIGCOMMANDEXECUTOR_H #define CONFIGCOMMANDEXECUTOR_H #include namespace qbs { class Settings; } class ConfigCommand; class ConfigCommandExecutor { Q_DECLARE_TR_FUNCTIONS(ConfigCommandExecutor) public: ConfigCommandExecutor(qbs::Settings *settings); void execute(const ConfigCommand &command); private: void setValue(const QString &key, const QString &rawInput); void printSettings(const ConfigCommand &command); void printOneSetting(const QString &key); void exportSettings(const QString &filename); void importSettings(const QString &filename); qbs::Settings *m_settings; }; #endif // CONFIGCOMMANDEXECUTOR_H qbs-src-1.4.5/src/app/config/configcommandlineparser.cpp000066400000000000000000000125631266132464200233210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "configcommandlineparser.h" #include #include #include using namespace qbs; using namespace Internal; void ConfigCommandLineParser::parse(const QStringList &commandLine) { m_command = ConfigCommand(); m_helpRequested = false; m_settingsDir.clear(); m_commandLine = commandLine; if (m_commandLine.isEmpty()) throw ErrorInfo(Tr::tr("No parameters supplied.")); if (m_commandLine.count() == 1 && (m_commandLine.first() == QLatin1String("--help") || m_commandLine.first() == QLatin1String("-h"))) { m_helpRequested = true; return; } while (!m_commandLine.isEmpty() && m_commandLine.first().startsWith(QLatin1String("--"))) { const QString arg = m_commandLine.takeFirst().mid(2); if (arg == QLatin1String("list")) setCommand(ConfigCommand::CfgList); else if (arg == QLatin1String("unset")) setCommand(ConfigCommand::CfgUnset); else if (arg == QLatin1String("export")) setCommand(ConfigCommand::CfgExport); else if (arg == QLatin1String("import")) setCommand(ConfigCommand::CfgImport); else if (arg == QLatin1String("settings-dir")) assignOptionArgument(arg, m_settingsDir); else throw ErrorInfo(Tr::tr("Unknown option for config command.")); } switch (command().command) { case ConfigCommand::CfgNone: if (m_commandLine.isEmpty()) throw ErrorInfo(Tr::tr("No parameters supplied.")); if (m_commandLine.count() > 2) throw ErrorInfo(Tr::tr("Too many arguments.")); m_command.varNames << m_commandLine.first(); if (m_commandLine.count() == 1) { setCommand(ConfigCommand::CfgList); } else { m_command.varValue = m_commandLine.at(1); setCommand(ConfigCommand::CfgSet); } break; case ConfigCommand::CfgUnset: if (m_commandLine.isEmpty()) throw ErrorInfo(Tr::tr("Need name of variable to unset.")); m_command.varNames = m_commandLine; break; case ConfigCommand::CfgExport: if (m_commandLine.count() != 1) throw ErrorInfo(Tr::tr("Need name of file to which to export.")); m_command.fileName = m_commandLine.first(); break; case ConfigCommand::CfgImport: if (m_commandLine.count() != 1) throw ErrorInfo(Tr::tr("Need name of file from which to import.")); m_command.fileName = m_commandLine.first(); break; case ConfigCommand::CfgList: m_command.varNames = m_commandLine; break; default: break; } } void ConfigCommandLineParser::setCommand(ConfigCommand::Command command) { if (m_command.command != ConfigCommand::CfgNone) throw ErrorInfo(Tr::tr("You cannot specify more than one command.")); m_command.command = command; } void ConfigCommandLineParser::printUsage() const { puts("Usage:\n" " qbs config [--settings-dir \n" " qbs config [--settings-dir \n" " qbs config [--settings-dir " "\n" "Options:\n" " --list [ ...] list keys under key or all keys\n" " --unset remove key with given name\n" " --import import settings from given file\n" " --export export settings to given file\n"); } void ConfigCommandLineParser::assignOptionArgument(const QString &option, QString &argument) { if (m_commandLine.isEmpty()) throw ErrorInfo(Tr::tr("Option '%1' needs an argument.").arg(option)); argument = m_commandLine.takeFirst(); if (argument.isEmpty()) throw ErrorInfo(Tr::tr("Argument for option '%1' must not be empty.").arg(option)); } qbs-src-1.4.5/src/app/config/configcommandlineparser.h000066400000000000000000000042421266132464200227610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef COMMANDLINEPARSER_H #define COMMANDLINEPARSER_H #include "configcommand.h" #include class ConfigCommandLineParser { public: void parse(const QStringList &commandLine); ConfigCommand command() const { return m_command; } QString settingsDir() const { return m_settingsDir; } bool helpRequested() const { return m_helpRequested; } void printUsage() const; private: void assignOptionArgument(const QString &option, QString &argument); void setCommand(ConfigCommand::Command command); ConfigCommand m_command; bool m_helpRequested; QString m_settingsDir; QStringList m_commandLine; }; #endif // COMMANDLINEPARSER_H qbs-src-1.4.5/src/app/config/configmain.cpp000066400000000000000000000046301266132464200205360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "configcommandlineparser.h" #include "configcommandexecutor.h" #include #include #include #include #include #include using qbs::Internal::Tr; using qbs::Settings; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); ConfigCommandLineParser parser; try { parser.parse(app.arguments().mid(1)); if (parser.helpRequested()) { std::cout << qPrintable(Tr::tr("This tool manages qbs settings.")) << std::endl; parser.printUsage(); return EXIT_SUCCESS; } Settings settings(parser.settingsDir()); ConfigCommandExecutor(&settings).execute(parser.command()); } catch (const qbs::ErrorInfo &e) { std::cerr << qPrintable(e.toString()) << std::endl; parser.printUsage(); return EXIT_FAILURE; } } qbs-src-1.4.5/src/app/qbs-qmltypes/000077500000000000000000000000001266132464200171115ustar00rootroot00000000000000qbs-src-1.4.5/src/app/qbs-qmltypes/main.cpp000066400000000000000000000052521266132464200205450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include using qbs::Internal::Tr; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); ConsoleLogger::instance(); const QStringList args = app.arguments().mid(1); if (args.count() == 1 && (args.first() == QLatin1String("--help") || args.first() == QLatin1String("-h"))) { qbsInfo() << Tr::tr("This tool dumps information about the QML types supported by qbs.\n" "It takes no command-line parameters.\n" "The output is intended to be processed by other tools and has " "little value for humans."); return EXIT_SUCCESS; } if (!args.isEmpty()) { qbsWarning() << Tr::tr("You supplied command-line parameters, " "but this tool does not use any."); } qbs::LanguageInfo languageInfo; const QByteArray typeData = languageInfo.qmlTypeInfo(); std::cout << typeData.constData(); return 0; } qbs-src-1.4.5/src/app/qbs-qmltypes/qbs-qmltypes.pro000066400000000000000000000001101266132464200222640ustar00rootroot00000000000000include(../app.pri) TARGET = qbs-qmltypes SOURCES += \ main.cpp \ qbs-src-1.4.5/src/app/qbs-qmltypes/qbs-qmltypes.qbs000066400000000000000000000001331266132464200222560ustar00rootroot00000000000000import qbs 1.0 QbsApp { name: "qbs-qmltypes" files: [ "main.cpp" ] } qbs-src-1.4.5/src/app/qbs-setup-android/000077500000000000000000000000001266132464200200115ustar00rootroot00000000000000qbs-src-1.4.5/src/app/qbs-setup-android/android-setup.cpp000066400000000000000000000144261266132464200233020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "android-setup.h" #include #include #include #include #include #include #include #include #include #include using namespace qbs; using qbs::Internal::Tr; static QString qls(const char *s) { return QLatin1String(s); } static QStringList allPlatforms(const QString &baseDir) { QDir platformsDir(baseDir + qls("/platforms")); if (!platformsDir.exists()) { throw ErrorInfo(Tr::tr("Expected directory '%1' to be present, but it is not.") .arg(QDir::toNativeSeparators(platformsDir.path()))); } const QStringList platforms = platformsDir.entryList( QStringList() << qls("android-*"), QDir::Dirs | QDir::NoDotAndDotDot); if (platforms.isEmpty()) { throw ErrorInfo(Tr::tr("No platforms found in '%1'.") .arg(QDir::toNativeSeparators(platformsDir.path()))); } return platforms; } static bool compareBuildToolVersions(const QString &v1, const QString &v2) { return Internal::Version::fromString(v1) < Internal::Version::fromString(v2); } static QString detectBuildToolsVersion(const QString &sdkDir) { QDir baseDir(sdkDir + qls("/build-tools")); if (!baseDir.exists()) { throw ErrorInfo(Tr::tr("Expected directory '%1' to be present, but it is not.") .arg(QDir::toNativeSeparators(baseDir.path()))); } QStringList versions = baseDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); if (versions.isEmpty()) { throw ErrorInfo(Tr::tr("No build tools found in '%1'.") .arg(QDir::toNativeSeparators(baseDir.path()))); } std::sort(versions.begin(), versions.end(), compareBuildToolVersions); return versions.last(); } static QString detectPlatform(const QString &sdkDir) { const QStringList sdkPlatforms = allPlatforms(sdkDir); QString newestPlatform; int max = 0; foreach (const QString &platform, sdkPlatforms) { static const QString prefix = qls("android-"); if (!platform.startsWith(prefix)) continue; bool ok; const int nr = platform.mid(prefix.count()).toInt(&ok); if (!ok) continue; if (nr > max) { max = nr; newestPlatform = platform; } } if (newestPlatform.isEmpty()) throw ErrorInfo(Tr::tr("No platforms found in SDK.")); return newestPlatform; } static QStringList expectedArchs() { return QStringList() << QStringLiteral("arm64") << QStringLiteral("armv5") << QStringLiteral("armv7") << QStringLiteral("mipsel") << QStringLiteral("mips64el") << QStringLiteral("x86") << QStringLiteral("x86_64"); } static QString subProfileName(const QString &mainProfileName, const QString &arch) { return mainProfileName + QLatin1Char('-') + arch; } void setupSdk(qbs::Settings *settings, const QString &profileName, const QString &sdkDirPath) { if (!QDir(sdkDirPath).exists()) { throw ErrorInfo(Tr::tr("SDK directory '%1' does not exist.") .arg(QDir::toNativeSeparators(sdkDirPath))); } Profile profile(profileName, settings); profile.removeProfile(); profile.setValue(qls("Android.sdk.sdkDir"), QDir::cleanPath(sdkDirPath)); profile.setValue(qls("Android.sdk.buildToolsVersion"), detectBuildToolsVersion(sdkDirPath)); profile.setValue(qls("Android.sdk.platform"), detectPlatform(sdkDirPath)); profile.setValue(qls("qbs.targetOS"), QStringList() << qls("android") << qls("linux") << qls("unix")); } void setupNdk(qbs::Settings *settings, const QString &profileName, const QString &ndkDirPath) { if (ndkDirPath.isEmpty()) return; if (!QDir(ndkDirPath).exists()) { throw ErrorInfo(Tr::tr("NDK directory '%1' does not exist.") .arg(QDir::toNativeSeparators(ndkDirPath))); } Profile mainProfile(profileName, settings); mainProfile.setValue(qls("Android.ndk.ndkDir"), QDir::cleanPath(ndkDirPath)); mainProfile.setValue(qls("Android.sdk.ndkDir"), QDir::cleanPath(ndkDirPath)); mainProfile.setValue(qls("qbs.toolchain"), QStringList() << qls("gcc")); foreach (const QString &arch, expectedArchs()) { Profile p(subProfileName(profileName, arch), settings); p.removeProfile(); p.setBaseProfile(mainProfile.name()); p.setValue(qls("qbs.architecture"), arch); } } void setupAndroid(Settings *settings, const QString &profileName, const QString &sdkDirPath, const QString &ndkDirPath) { setupSdk(settings, profileName, sdkDirPath); setupNdk(settings, profileName, ndkDirPath); } qbs-src-1.4.5/src/app/qbs-setup-android/android-setup.h000066400000000000000000000035301266132464200227410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_SETUP_ANDROID_SDKSETUP_H #define QBS_SETUP_ANDROID_SDKSETUP_H #include namespace qbs { class Settings; } QT_BEGIN_NAMESPACE class QString; QT_END_NAMESPACE void setupAndroid(qbs::Settings *settings, const QString &profileName, const QString &sdkDirPath, const QString &ndkDirPath); #endif // Include guard. qbs-src-1.4.5/src/app/qbs-setup-android/commandlineparser.cpp000066400000000000000000000115611266132464200242240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "commandlineparser.h" #include #include #include CommandLineParser::CommandLineParser() { } using qbs::Internal::Tr; static QString helpOptionShort() { return QLatin1String("-h"); } static QString helpOptionLong() { return QLatin1String("--help"); } static QString settingsDirOption() { return QLatin1String("--settings-dir"); } static QString sdkDirOption() { return QLatin1String("--sdk-dir"); } static QString ndkDirOption() { return QLatin1String("--ndk-dir"); } void CommandLineParser::parse(const QStringList &commandLine) { m_commandLine = commandLine; Q_ASSERT(!m_commandLine.isEmpty()); m_command = QFileInfo(m_commandLine.takeFirst()).fileName(); m_helpRequested = false; m_sdkDir.clear(); m_ndkDir.clear(); m_profileName.clear(); m_settingsDir.clear(); if (m_commandLine.isEmpty()) throwError(Tr::tr("No command-line arguments provided.")); while (!m_commandLine.isEmpty()) { const QString arg = m_commandLine.first(); if (!arg.startsWith(QLatin1String("--"))) break; m_commandLine.removeFirst(); if (arg == helpOptionShort() || arg == helpOptionLong()) m_helpRequested = true; else if (arg == settingsDirOption()) assignOptionArgument(settingsDirOption(), m_settingsDir); else if (arg == sdkDirOption()) assignOptionArgument(sdkDirOption(), m_sdkDir); else if (arg == ndkDirOption()) assignOptionArgument(ndkDirOption(), m_ndkDir); } if (m_helpRequested) { if (!m_commandLine.isEmpty()) complainAboutExtraArguments(); return; } if (m_sdkDir.isEmpty()) throwError(Tr::tr("No SDK directory supplied.")); switch (m_commandLine.count()) { case 0: throwError(Tr::tr("No profile name supplied.")); case 1: m_profileName = m_commandLine.takeFirst(); break; default: complainAboutExtraArguments(); } } void CommandLineParser::throwError(const QString &message) { qbs::ErrorInfo error(Tr::tr("Syntax error: %1").arg(message)); error.append(usageString()); throw error; } QString CommandLineParser::usageString() const { QString s = Tr::tr("This tool creates qbs profiles from Android SDK and NDK installations.\n"); s += Tr::tr("Usage:\n"); s += Tr::tr(" %1 [%2 ] [%3 ] %4 \n") .arg(m_command, settingsDirOption(), ndkDirOption(), sdkDirOption()); s += Tr::tr(" %1 %2|%3\n").arg(m_command, helpOptionShort(), helpOptionLong()); s += Tr::tr("If an NDK path is given, additional profiles will be created for each " "architecture supported by the NDK.\n" "Their names will be of the form
      _."); return s; } void CommandLineParser::assignOptionArgument(const QString &option, QString &argument) { if (m_commandLine.isEmpty()) throwError(Tr::tr("Option '%1' needs an argument.").arg(option)); argument = m_commandLine.takeFirst(); if (argument.isEmpty()) throwError(Tr::tr("Argument for option '%1' must not be empty.").arg(option)); } void CommandLineParser::complainAboutExtraArguments() { throwError(Tr::tr("Extraneous command-line arguments '%1'.") .arg(m_commandLine.join(QLatin1Char(' ')))); } qbs-src-1.4.5/src/app/qbs-setup-android/commandlineparser.h000066400000000000000000000046271266132464200236760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_SETUP_ANDROID_COMMANDLINEPARSER_H #define QBS_SETUP_ANDROID_COMMANDLINEPARSER_H #include class CommandLineParser { public: CommandLineParser(); void parse(const QStringList &commandLine); bool helpRequested() const { return m_helpRequested; } QString sdkDir() const { return m_sdkDir; } QString ndkDir() const { return m_ndkDir; } QString profileName() const { return m_profileName; } QString settingsDir() const { return m_settingsDir; } QString usageString() const; private: Q_NORETURN void throwError(const QString &message); void assignOptionArgument(const QString &option, QString &argument); Q_NORETURN void complainAboutExtraArguments(); bool m_helpRequested; QString m_sdkDir; QString m_ndkDir; QString m_profileName; QString m_settingsDir; QStringList m_commandLine; QString m_command; }; #endif // Include guard. qbs-src-1.4.5/src/app/qbs-setup-android/main.cpp000066400000000000000000000045151266132464200214460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "commandlineparser.h" #include "android-setup.h" #include #include #include #include #include #include int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); CommandLineParser clParser; try { clParser.parse(app.arguments()); if (clParser.helpRequested()) { std::cout << qPrintable(clParser.usageString()) << std::endl; return EXIT_SUCCESS; } qbs::Settings settings(clParser.settingsDir()); setupAndroid(&settings, clParser.profileName(), clParser.sdkDir(), clParser.ndkDir()); } catch (const qbs::ErrorInfo &e) { std::cerr << qPrintable(qbs::Internal::Tr::tr("Error: %1").arg(e.toString())) << std::endl; return EXIT_FAILURE; } } qbs-src-1.4.5/src/app/qbs-setup-android/qbs-setup-android.pro000066400000000000000000000002731266132464200240760ustar00rootroot00000000000000include(../app.pri) TARGET = qbs-setup-android SOURCES += \ android-setup.cpp \ commandlineparser.cpp \ main.cpp HEADERS += \ android-setup.h \ commandlineparser.h qbs-src-1.4.5/src/app/qbs-setup-android/qbs-setup-android.qbs000066400000000000000000000003241266132464200240600ustar00rootroot00000000000000import qbs QbsApp { name: "qbs-setup-android" files: [ "android-setup.cpp", "android-setup.h", "commandlineparser.cpp", "commandlineparser.h", "main.cpp", ] } qbs-src-1.4.5/src/app/qbs-setup-qt/000077500000000000000000000000001266132464200170155ustar00rootroot00000000000000qbs-src-1.4.5/src/app/qbs-setup-qt/commandlineparser.cpp000066400000000000000000000113231266132464200232240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "commandlineparser.h" #include #include #include using qbs::Internal::Tr; static QString helpOptionShort() { return QLatin1String("-h"); } static QString helpOptionLong() { return QLatin1String("--help"); } static QString detectOption() { return QLatin1String("--detect"); } static QString settingsDirOption() { return QLatin1String("--settings-dir"); } void CommandLineParser::parse(const QStringList &commandLine) { m_commandLine = commandLine; Q_ASSERT(!m_commandLine.isEmpty()); m_command = QFileInfo(m_commandLine.takeFirst()).fileName(); m_helpRequested = false; m_autoDetectionMode = false; m_qmakePath.clear(); m_profileName.clear(); m_settingsDir.clear(); if (m_commandLine.isEmpty()) throwError(Tr::tr("No command-line arguments provided.")); while (!m_commandLine.isEmpty()) { const QString arg = m_commandLine.first(); if (!arg.startsWith(QLatin1String("--"))) break; m_commandLine.removeFirst(); if (arg == helpOptionShort() || arg == helpOptionLong()) m_helpRequested = true; else if (arg == detectOption()) m_autoDetectionMode = true; else if (arg == settingsDirOption()) assignOptionArgument(settingsDirOption(), m_settingsDir); } if (m_helpRequested || m_autoDetectionMode) { if (!m_commandLine.isEmpty()) complainAboutExtraArguments(); return; } switch (m_commandLine.count()) { case 0: case 1: throwError(Tr::tr("Not enough command-line arguments provided.")); case 2: m_qmakePath = m_commandLine.at(0); m_profileName = m_commandLine.at(1); break; default: complainAboutExtraArguments(); } } void CommandLineParser::throwError(const QString &message) { qbs::ErrorInfo error(Tr::tr("Syntax error: %1").arg(message)); error.append(usageString()); throw error; } QString CommandLineParser::usageString() const { QString s = Tr::tr("This tool creates qbs profiles from Qt versions.\n"); s += Tr::tr("Usage:\n"); s += Tr::tr(" %1 [%2 ] %3\n") .arg(m_command, settingsDirOption(), detectOption()); s += Tr::tr(" %1 [%2 ] \n") .arg(m_command, settingsDirOption()); s += Tr::tr(" %1 %2|%3\n").arg(m_command, helpOptionShort(), helpOptionLong()); s += Tr::tr("The first form tries to auto-detect all known Qt versions, looking them up " "via the PATH environment variable.\n"); s += Tr::tr("The second form creates one profile for one Qt version."); return s; } void CommandLineParser::assignOptionArgument(const QString &option, QString &argument) { if (m_commandLine.isEmpty()) throwError(Tr::tr("Option '%1' needs an argument.").arg(option)); argument = m_commandLine.takeFirst(); if (argument.isEmpty()) throwError(Tr::tr("Argument for option '%1' must not be empty.").arg(option)); } void CommandLineParser::complainAboutExtraArguments() { throwError(Tr::tr("Extraneous command-line arguments '%1'.") .arg(m_commandLine.join(QLatin1Char(' ')))); } qbs-src-1.4.5/src/app/qbs-setup-qt/commandlineparser.h000066400000000000000000000046161266132464200227000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_SETUPTOOLCHAINS_COMMANDLINEPARSER_H #define QBS_SETUPTOOLCHAINS_COMMANDLINEPARSER_H #include class CommandLineParser { public: void parse(const QStringList &commandLine); bool helpRequested() const { return m_helpRequested; } bool autoDetectionMode() const { return m_autoDetectionMode; } QString qmakePath() const { return m_qmakePath; } QString profileName() const { return m_profileName; } QString settingsDir() const { return m_settingsDir; } QString usageString() const; private: void throwError(const QString &message); void assignOptionArgument(const QString &option, QString &argument); void complainAboutExtraArguments(); bool m_helpRequested; bool m_autoDetectionMode; QString m_qmakePath; QString m_profileName; QString m_settingsDir; QStringList m_commandLine; QString m_command; }; #endif // Include guard qbs-src-1.4.5/src/app/qbs-setup-qt/main.cpp000066400000000000000000000074061266132464200204540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "setupqt.h" #include "commandlineparser.h" #include #include #include #include #include #include #include #include using namespace qbs; using Internal::Tr; int main(int argc, char *argv[]) { QCoreApplication application(argc, argv); try { CommandLineParser clParser; clParser.parse(application.arguments()); if (clParser.helpRequested()) { std::cout << qPrintable(clParser.usageString()) << std::endl; return EXIT_SUCCESS; } Settings settings(clParser.settingsDir()); if (clParser.autoDetectionMode()) { // search all Qt's in path and dump their settings QList qtEnvironments = SetupQt::fetchEnvironments(); foreach (const QtEnvironment &qtEnvironment, qtEnvironments) { QString profileName = QLatin1String("qt-") + qtEnvironment.qtVersion; if (SetupQt::checkIfMoreThanOneQtWithTheSameVersion(qtEnvironment.qtVersion, qtEnvironments)) { QStringList prefixPathParts = qtEnvironment.installPrefixPath .split(QLatin1Char('/'), QString::SkipEmptyParts); if (!prefixPathParts.isEmpty()) profileName += QLatin1String("-") + prefixPathParts.last(); } SetupQt::saveToQbsSettings(profileName, qtEnvironment, &settings); } return EXIT_SUCCESS; } if (!SetupQt::isQMakePathValid(clParser.qmakePath())) { std::cerr << qPrintable(Tr::tr("'%1' does not seem to be a qmake executable.") .arg(clParser.qmakePath())) << std::endl; return EXIT_FAILURE; } QtEnvironment qtEnvironment = SetupQt::fetchEnvironment(clParser.qmakePath()); QString profileName = clParser.profileName(); profileName.replace(QLatin1Char('.'), QLatin1Char('-')); SetupQt::saveToQbsSettings(profileName, qtEnvironment, &settings); return EXIT_SUCCESS; } catch (const ErrorInfo &e) { std::cerr << qPrintable(e.toString()) << std::endl; return EXIT_FAILURE; } } qbs-src-1.4.5/src/app/qbs-setup-qt/qbs-setup-qt.exe.manifest000066400000000000000000000007261266132464200236770ustar00rootroot00000000000000 qbs-src-1.4.5/src/app/qbs-setup-qt/qbs-setup-qt.pro000066400000000000000000000004241266132464200221040ustar00rootroot00000000000000include(../app.pri) include($${PWD}/../../lib/qtprofilesetup/use_qtprofilesetup.pri) TARGET = qbs-setup-qt SOURCES += \ commandlineparser.cpp \ main.cpp \ setupqt.cpp HEADERS += \ commandlineparser.h \ setupqt.h mingw { RC_FILE = qbs-setup-qt.rc } qbs-src-1.4.5/src/app/qbs-setup-qt/qbs-setup-qt.qbs000066400000000000000000000005761266132464200221010ustar00rootroot00000000000000import qbs 1.0 QbsApp { name: "qbs-setup-qt" Depends { name: "qbsqtprofilesetup" } files: [ "commandlineparser.cpp", "commandlineparser.h", "main.cpp", "setupqt.cpp", "setupqt.h" ] Group { name: "MinGW specific files" condition: qbs.toolchain.contains("mingw") files: ["qbs-setup-qt.rc"] } } qbs-src-1.4.5/src/app/qbs-setup-qt/qbs-setup-qt.rc000066400000000000000000000002201266132464200217020ustar00rootroot00000000000000#define RT_MANIFEST 24 #define CREATEPROCESS_MANIFEST_RESOURCE_ID 1 CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "qbs-setup-qt.exe.manifest" qbs-src-1.4.5/src/app/qbs-setup-qt/setupqt.cpp000066400000000000000000000561051266132464200212350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "setupqt.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { using Internal::HostOsInfo; using Internal::Tr; using Internal::Version; static QStringList qmakeExecutableNames() { const QString baseName = HostOsInfo::appendExecutableSuffix(QStringLiteral("qmake")); QStringList lst(baseName); if (HostOsInfo::isLinuxHost()) { // Some distributions ship binaries called qmake-qt5 or qmake-qt4. lst << baseName + QLatin1String("-qt5") << baseName + QLatin1String("-qt4"); } return lst; } static QStringList collectQmakePaths() { const QStringList qmakeExeNames = qmakeExecutableNames(); QStringList qmakePaths; QByteArray environmentPath = qgetenv("PATH"); QList environmentPaths = environmentPath.split(HostOsInfo::pathListSeparator().toLatin1()); foreach (const QByteArray &path, environmentPaths) { foreach (const QString &qmakeExecutableName, qmakeExeNames) { QFileInfo pathFileInfo(QDir(QLatin1String(path)), qmakeExecutableName); if (pathFileInfo.exists()) { QString qmakePath = pathFileInfo.absoluteFilePath(); if (!qmakePaths.contains(qmakePath)) qmakePaths.append(qmakePath); } } } return qmakePaths; } bool SetupQt::isQMakePathValid(const QString &qmakePath) { QFileInfo qmakeFileInfo(qmakePath); return qmakeFileInfo.exists() && qmakeFileInfo.isFile() && qmakeFileInfo.isExecutable(); } QList SetupQt::fetchEnvironments() { QList qtEnvironments; foreach (const QString &qmakePath, collectQmakePaths()) { const QtEnvironment env = fetchEnvironment(qmakePath); if (std::find_if(qtEnvironments.constBegin(), qtEnvironments.constEnd(), [&env](const QtEnvironment &otherEnv) { return env.includePath == otherEnv.includePath; }) == qtEnvironments.constEnd()) { qtEnvironments.append(env); } } return qtEnvironments; } void SetupQt::addQtBuildVariant(QtEnvironment *env, const QString &buildVariantName) { if (env->qtConfigItems.contains(buildVariantName)) env->buildVariant << buildVariantName; } static QMap qmakeQueryOutput(const QString &qmakePath) { QProcess qmakeProcess; qmakeProcess.start(qmakePath, QStringList() << QLatin1String("-query")); if (!qmakeProcess.waitForStarted()) throw ErrorInfo(SetupQt::tr("%1 cannot be started.").arg(qmakePath)); qmakeProcess.waitForFinished(); const QByteArray output = qmakeProcess.readAllStandardOutput(); QMap ret; foreach (const QByteArray &line, output.split('\n')) { int idx = line.indexOf(':'); if (idx >= 0) ret[line.left(idx)] = line.mid(idx + 1).trimmed(); } return ret; } static QByteArray readFileContent(const QString &filePath) { QFile file(filePath); if (file.open(QFile::ReadOnly)) return file.readAll(); return QByteArray(); } static QString configVariable(const QByteArray &configContent, const QString &key) { QRegExp regexp(QLatin1String("\\s*") + key + QLatin1String("\\s*\\+{0,1}=(.*)"), Qt::CaseSensitive); QList configContentLines = configContent.split('\n'); bool success = false; foreach (const QByteArray &configContentLine, configContentLines) { success = regexp.exactMatch(QString::fromLocal8Bit(configContentLine)); if (success) break; } if (success) return regexp.capturedTexts()[1].simplified(); return QString(); } static QStringList configVariableItems(const QByteArray &configContent, const QString &key) { return configVariable(configContent, key).split(QLatin1Char(' '), QString::SkipEmptyParts); } typedef QMap QueryMap; static QString pathQueryValue(const QueryMap &queryMap, const QByteArray &key) { return QDir::fromNativeSeparators(QString::fromLocal8Bit(queryMap.value(key))); } QtEnvironment SetupQt::fetchEnvironment(const QString &qmakePath) { QtEnvironment qtEnvironment; QueryMap queryOutput = qmakeQueryOutput(qmakePath); qtEnvironment.installPrefixPath = pathQueryValue(queryOutput, "QT_INSTALL_PREFIX"); qtEnvironment.documentationPath = pathQueryValue(queryOutput, "QT_INSTALL_DOCS"); qtEnvironment.includePath = pathQueryValue(queryOutput, "QT_INSTALL_HEADERS"); qtEnvironment.libraryPath = pathQueryValue(queryOutput, "QT_INSTALL_LIBS"); qtEnvironment.binaryPath = pathQueryValue(queryOutput, "QT_HOST_BINS"); if (qtEnvironment.binaryPath.isEmpty()) qtEnvironment.binaryPath = pathQueryValue(queryOutput, "QT_INSTALL_BINS"); qtEnvironment.documentationPath = pathQueryValue(queryOutput, "QT_INSTALL_DOCS"); qtEnvironment.pluginPath = pathQueryValue(queryOutput, "QT_INSTALL_PLUGINS"); qtEnvironment.qmlPath = pathQueryValue(queryOutput, "QT_INSTALL_QML"); qtEnvironment.qmlImportPath = pathQueryValue(queryOutput, "QT_INSTALL_IMPORTS"); qtEnvironment.qtVersion = QString::fromLocal8Bit(queryOutput.value("QT_VERSION")); const Version qtVersion = Version::fromString(qtEnvironment.qtVersion); QString mkspecsBaseSrcPath; if (qtVersion.majorVersion() >= 5) { qtEnvironment.mkspecBasePath = pathQueryValue(queryOutput, "QT_HOST_DATA") + QLatin1String("/mkspecs"); mkspecsBaseSrcPath = pathQueryValue(queryOutput, "QT_HOST_DATA/src") + QLatin1String("/mkspecs"); } else { qtEnvironment.mkspecBasePath = pathQueryValue(queryOutput, "QT_INSTALL_DATA") + QLatin1String("/mkspecs"); } if (!QFile::exists(qtEnvironment.mkspecBasePath)) throw ErrorInfo(tr("Cannot extract the mkspecs directory.")); const QByteArray qconfigContent = readFileContent(qtEnvironment.mkspecBasePath + QLatin1String("/qconfig.pri")); qtEnvironment.qtMajorVersion = configVariable(qconfigContent, QLatin1String("QT_MAJOR_VERSION")).toInt(); qtEnvironment.qtMinorVersion = configVariable(qconfigContent, QLatin1String("QT_MINOR_VERSION")).toInt(); qtEnvironment.qtPatchVersion = configVariable(qconfigContent, QLatin1String("QT_PATCH_VERSION")).toInt(); qtEnvironment.qtNameSpace = configVariable(qconfigContent, QLatin1String("QT_NAMESPACE")); qtEnvironment.qtLibInfix = configVariable(qconfigContent, QLatin1String("QT_LIBINFIX")); qtEnvironment.architecture = configVariable(qconfigContent, QLatin1String("QT_TARGET_ARCH")); if (qtEnvironment.architecture.isEmpty()) qtEnvironment.architecture = configVariable(qconfigContent, QLatin1String("QT_ARCH")); if (qtEnvironment.architecture.isEmpty()) qtEnvironment.architecture = QLatin1String("x86"); qtEnvironment.configItems = configVariableItems(qconfigContent, QLatin1String("CONFIG")); qtEnvironment.qtConfigItems = configVariableItems(qconfigContent, QLatin1String("QT_CONFIG")); // retrieve the mkspec if (qtVersion.majorVersion() >= 5) { const QString mkspecName = QString::fromLocal8Bit(queryOutput.value("QMAKE_XSPEC")); qtEnvironment.mkspecName = mkspecName; qtEnvironment.mkspecPath = qtEnvironment.mkspecBasePath + QLatin1Char('/') + mkspecName; if (!mkspecsBaseSrcPath.isEmpty() && !QFile::exists(qtEnvironment.mkspecPath)) qtEnvironment.mkspecPath = mkspecsBaseSrcPath + QLatin1Char('/') + mkspecName; } else { if (HostOsInfo::isWindowsHost()) { const QString baseDirPath = qtEnvironment.mkspecBasePath + QLatin1String("/default/"); const QByteArray fileContent = readFileContent(baseDirPath + QLatin1String("qmake.conf")); qtEnvironment.mkspecPath = configVariable(fileContent, QLatin1String("QMAKESPEC_ORIGINAL")); if (!QFile::exists(qtEnvironment.mkspecPath)) { // Work around QTBUG-28792. // The value of QMAKESPEC_ORIGINAL is wrong for MinGW packages. Y u h8 me? const QRegExp rex(QLatin1String("\\binclude\\(([^)]+)/qmake\\.conf\\)")); if (rex.indexIn(QString::fromLocal8Bit(fileContent)) != -1) qtEnvironment.mkspecPath = QDir::cleanPath(baseDirPath + rex.cap(1)); } } else { qtEnvironment.mkspecPath = QFileInfo(qtEnvironment.mkspecBasePath + QLatin1String("/default")).symLinkTarget(); } // E.g. in qmake.conf for Qt 4.8/mingw we find this gem: // QMAKESPEC_ORIGINAL=C:\\Qt\\Qt\\4.8\\mingw482\\mkspecs\\win32-g++ qtEnvironment.mkspecPath = QDir::cleanPath(qtEnvironment.mkspecPath); qtEnvironment.mkspecName = qtEnvironment.mkspecPath; int idx = qtEnvironment.mkspecName.lastIndexOf(QLatin1Char('/')); if (idx != -1) qtEnvironment.mkspecName.remove(0, idx + 1); } // determine whether we have a framework build qtEnvironment.frameworkBuild = false; if (qtEnvironment.mkspecPath.contains(QLatin1String("macx"))) { if (qtEnvironment.configItems.contains(QLatin1String("qt_framework"))) qtEnvironment.frameworkBuild = true; else if (!qtEnvironment.configItems.contains(QLatin1String("qt_no_framework"))) throw ErrorInfo(tr("could not determine whether Qt is a frameworks build")); } // determine whether Qt is built with debug, release or both addQtBuildVariant(&qtEnvironment, QLatin1String("debug")); addQtBuildVariant(&qtEnvironment, QLatin1String("release")); if (!QFileInfo(qtEnvironment.mkspecPath).exists()) throw ErrorInfo(tr("mkspec '%1' does not exist").arg(qtEnvironment.mkspecPath)); return qtEnvironment; } static bool isToolchainProfileKey(const QString &key) { // The Qt profile setup itself sets cpp.minimum*Version for some systems. return key.startsWith(QLatin1String("cpp.")) && !key.startsWith(QLatin1String("cpp.minimum")); } template bool areProfilePropertiesIncompatible(const T &set1, const T &set2) { // Two objects are only considered incompatible if they are both non empty and compare inequal // This logic is used for comparing target OS, toolchain lists, and architectures return !set1.isEmpty() && !set2.isEmpty() && set1 != set2; } static QStringList qbsTargetOsFromQtMkspec(const QString &mkspec) { if (mkspec.startsWith(QLatin1String("aix-"))) return QStringList() << QLatin1String("aix") << QLatin1String("unix"); if (mkspec.startsWith(QLatin1String("android-"))) return QStringList() << QLatin1String("android") << QLatin1String("linux") << QLatin1String("unix"); if (mkspec.startsWith(QLatin1String("blackberry"))) return QStringList() << QLatin1String("blackberry") << QLatin1String("qnx") << QLatin1String("unix"); if (mkspec.startsWith(QLatin1String("darwin-"))) return QStringList() << QLatin1String("darwin") << QLatin1String("bsd") << QLatin1String("unix"); if (mkspec.startsWith(QLatin1String("freebsd-"))) return QStringList() << QLatin1String("freebsd") << QLatin1String("bsd") << QLatin1String("unix"); if (mkspec.startsWith(QLatin1String("haiku-"))) return QStringList() << QLatin1String("haiku"); if (mkspec.startsWith(QLatin1String("hpux-")) || mkspec.startsWith(QLatin1String("hpuxi-"))) return QStringList() << QLatin1String("hpux") << QLatin1String("unix"); if (mkspec.startsWith(QLatin1String("hurd-"))) return QStringList() << QLatin1String("hurd") << QLatin1String("unix"); if (mkspec.startsWith(QLatin1String("irix-"))) return QStringList() << QLatin1String("irix") << QLatin1String("unix"); if (mkspec.startsWith(QLatin1String("linux-"))) return QStringList() << QLatin1String("linux") << QLatin1String("unix"); if (mkspec.startsWith(QLatin1String("lynxos-"))) return QStringList() << QLatin1String("lynx") << QLatin1String("unix"); if (mkspec.startsWith(QLatin1String("macx-"))) return QStringList() << (mkspec.startsWith(QLatin1String("macx-ios-")) ? QLatin1String("ios") : QLatin1String("osx")) << QLatin1String("darwin") << QLatin1String("bsd") << QLatin1String("unix"); if (mkspec.startsWith(QLatin1String("nacl-")) || mkspec.startsWith(QLatin1String("nacl64-"))) return QStringList() << QLatin1String("nacl"); if (mkspec.startsWith(QLatin1String("netbsd-"))) return QStringList() << QLatin1String("netbsd") << QLatin1String("bsd") << QLatin1String("unix"); if (mkspec.startsWith(QLatin1String("openbsd-"))) return QStringList() << QLatin1String("openbsd") << QLatin1String("bsd") << QLatin1String("unix"); if (mkspec.startsWith(QLatin1String("qnx-"))) return QStringList() << QLatin1String("qnx") << QLatin1String("unix"); if (mkspec.startsWith(QLatin1String("sco-"))) return QStringList() << QLatin1String("sco") << QLatin1String("unix"); if (mkspec.startsWith(QLatin1String("solaris-"))) return QStringList() << QLatin1String("solaris") << QLatin1String("unix"); if (mkspec.startsWith(QLatin1String("tru64-"))) return QStringList() << QLatin1String("tru64") << QLatin1String("unix"); if (mkspec.startsWith(QLatin1String("unixware-"))) return QStringList() << QLatin1String("unixware") << QLatin1String("unix"); if (mkspec.startsWith(QLatin1String("vxworks-"))) return QStringList() << QLatin1String("vxworks") << QLatin1String("unix"); if (mkspec.startsWith(QLatin1String("win32-"))) return QStringList() << QLatin1String("windows"); if (mkspec.startsWith(QLatin1String("wince"))) return QStringList() << QLatin1String("windowsce") << QLatin1String("windows"); if (mkspec.startsWith(QLatin1String("winphone-"))) return QStringList() << QLatin1String("windowsphone") << QLatin1String("winrt") << QLatin1String("windows"); if (mkspec.startsWith(QLatin1String("winrt-"))) return QStringList() << QLatin1String("winrt") << QLatin1String("windows"); return QStringList(); } static QStringList qbsToolchainFromQtMkspec(const QString &mkspec) { if (mkspec.contains(QLatin1String("-msvc"))) return QStringList() << QLatin1String("msvc"); if (mkspec == QLatin1String("win32-g++")) return QStringList() << QLatin1String("mingw") << QLatin1String("gcc"); if (mkspec.contains(QLatin1String("-clang"))) return QStringList() << QLatin1String("clang") << QLatin1String("llvm") << QLatin1String("gcc"); if (mkspec.contains(QLatin1String("-llvm"))) return QStringList() << QLatin1String("llvm") << QLatin1String("gcc"); if (mkspec.contains(QLatin1String("-g++"))) return QStringList() << QLatin1String("gcc"); // Worry about other, less common toolchains (ICC, QCC, etc.) later... return QStringList(); } static int msvcCompilerMajorVersionForYear(int year) { switch (year) { case 2005: return 14; case 2008: return 15; case 2010: return 16; case 2012: return 17; case 2013: return 18; case 2015: return 19; default: return 0; } } enum Match { MatchFull, MatchPartial, MatchNone }; static Match compatibility(const QtEnvironment &env, const Profile &toolchainProfile) { Match match = MatchFull; const QSet toolchainNames = toolchainProfile.value(QLatin1String("qbs.toolchain")) .toStringList().toSet(); const QSet mkspecToolchainNames = qbsToolchainFromQtMkspec(env.mkspecName).toSet(); if (areProfilePropertiesIncompatible(toolchainNames, mkspecToolchainNames)) { QSet intersection = toolchainNames; intersection.intersect(mkspecToolchainNames); if (!intersection.isEmpty()) match = MatchPartial; else return MatchNone; } const QSet targetOsNames = toolchainProfile.value(QLatin1String("qbs.targetOS")) .toStringList().toSet(); if (areProfilePropertiesIncompatible(qbsTargetOsFromQtMkspec(env.mkspecName).toSet(), targetOsNames)) return MatchNone; const QString toolchainArchitecture = toolchainProfile.value(QLatin1String("qbs.architecture")) .toString(); if (areProfilePropertiesIncompatible(canonicalArchitecture(env.architecture), canonicalArchitecture(toolchainArchitecture))) return MatchNone; const QString msvcPrefix(QLatin1String("win32-msvc")); if (env.mkspecName.startsWith(msvcPrefix)) { const int compilerVersionMajor = msvcCompilerMajorVersionForYear( env.mkspecName.mid(msvcPrefix.size()).toInt()); // We want to know for sure that MSVC compiler versions match, // because it's especially important for this toolchain if (compilerVersionMajor == 0 || compilerVersionMajor != toolchainProfile.value(QLatin1String("cpp.compilerVersionMajor"))) { return MatchNone; } } return match; } void SetupQt::saveToQbsSettings(const QString &qtVersionName, const QtEnvironment &qtEnvironment, Settings *settings) { const QString cleanQtVersionName = Profile::cleanName(qtVersionName); QString msg = QCoreApplication::translate("SetupQt", "Creating profile '%1'.") .arg(cleanQtVersionName); printf("%s\n", qPrintable(msg)); const ErrorInfo errorInfo = setupQtProfile(cleanQtVersionName, settings, qtEnvironment); if (errorInfo.hasError()) throw errorInfo; // If this profile does not specify a toolchain and we find exactly one profile that looks // like it might have been added by qbs-setup-toolchains, let's use that one as our // base profile. Profile profile(cleanQtVersionName, settings); if (!profile.baseProfile().isEmpty()) return; foreach (const QString &key, profile.allKeys(Profile::KeySelectionNonRecursive)) { if (isToolchainProfileKey(key)) return; } QStringList fullMatches; QStringList partialMatches; foreach (const QString &profileName, settings->profiles()) { if (profileName == profile.name()) continue; const Profile otherProfile(profileName, settings); bool hasCppKey = false; bool hasQtKey = false; foreach (const QString &key, otherProfile.allKeys(Profile::KeySelectionNonRecursive)) { if (isToolchainProfileKey(key)) { hasCppKey = true; } else if (key.startsWith(QLatin1String("Qt."))) { hasQtKey = true; break; } } if (hasCppKey && !hasQtKey) switch (compatibility(qtEnvironment, Profile(profileName, settings))) { case MatchFull: fullMatches << profileName; break; case MatchPartial: partialMatches << profileName; break; default: break; } } QString bestMatch; if (fullMatches.count() == 1) bestMatch = fullMatches.first(); else if (fullMatches.isEmpty() && partialMatches.count() == 1) bestMatch = partialMatches.first(); if (bestMatch.isEmpty()) { QString message = Tr::tr("You need to set up toolchain information before you can " "use this Qt version for building. "); if (fullMatches.isEmpty() && partialMatches.isEmpty()) { message += Tr::tr("However, no toolchain profile was found. Either create one " "using qbs-setup-toolchains and set it as this profile's " "base profile or add the toolchain settings manually " "to this profile."); } else { message += Tr::tr("Consider setting one of these profiles as this profile's base " "profile: %1.").arg((fullMatches + partialMatches) .join(QLatin1String(", "))); } qbsWarning() << message; } else { profile.setBaseProfile(bestMatch); qbsInfo() << Tr::tr("Setting profile '%1' as the base profile for this profile.") .arg(bestMatch); } } bool SetupQt::checkIfMoreThanOneQtWithTheSameVersion(const QString &qtVersion, const QList &qtEnvironments) { bool foundOneVersion = false; foreach (const QtEnvironment &qtEnvironment, qtEnvironments) { if (qtEnvironment.qtVersion == qtVersion) { if (foundOneVersion) return true; foundOneVersion = true; } } return false; } } // namespace qbs qbs-src-1.4.5/src/app/qbs-setup-qt/setupqt.h000066400000000000000000000045061266132464200207000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_SETUPQT_H #define QBS_SETUPQT_H #include #include #include namespace qbs { class QtEnvironment; class Settings; class SetupQt { Q_DECLARE_TR_FUNCTIONS(SetupQt) public: static bool isQMakePathValid(const QString &qmakePath); static QList fetchEnvironments(); static void addQtBuildVariant(QtEnvironment *env, const QString &buildVariantName); static QtEnvironment fetchEnvironment(const QString &qmakePath); static void saveToQbsSettings(const QString &qtVersionName, const QtEnvironment & qtEnvironment, Settings *settings); static bool checkIfMoreThanOneQtWithTheSameVersion(const QString &qtVersion, const QList &qtEnvironments); }; } // namespace qbs #endif // QBS_SETUPQT_H qbs-src-1.4.5/src/app/qbs-setup-toolchains/000077500000000000000000000000001266132464200205345ustar00rootroot00000000000000qbs-src-1.4.5/src/app/qbs-setup-toolchains/commandlineparser.cpp000066400000000000000000000122221266132464200247420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "commandlineparser.h" #include #include #include using qbs::Internal::Tr; static QString helpOptionShort() { return QLatin1String("-h"); } static QString helpOptionLong() { return QLatin1String("--help"); } static QString detectOption() { return QLatin1String("--detect"); } static QString typeOption() { return QLatin1String("--type"); } static QString settingsDirOption() { return QLatin1String("--settings-dir"); } void CommandLineParser::parse(const QStringList &commandLine) { m_commandLine = commandLine; Q_ASSERT(!m_commandLine.isEmpty()); m_command = QFileInfo(m_commandLine.takeFirst()).fileName(); m_helpRequested = false; m_autoDetectionMode = false; m_compilerPath.clear(); m_toolchainType.clear(); m_profileName.clear(); m_settingsDir.clear(); if (m_commandLine.isEmpty()) throwError(Tr::tr("No command-line arguments provided.")); while (!m_commandLine.isEmpty()) { const QString arg = m_commandLine.first(); if (!arg.startsWith(QLatin1String("--"))) break; m_commandLine.removeFirst(); if (arg == helpOptionShort() || arg == helpOptionLong()) m_helpRequested = true; else if (arg == detectOption()) m_autoDetectionMode = true; else if (arg == typeOption()) assignOptionArgument(typeOption(), m_toolchainType); else if (arg == settingsDirOption()) assignOptionArgument(settingsDirOption(), m_settingsDir); } if (m_helpRequested || m_autoDetectionMode) { if (!m_commandLine.isEmpty()) complainAboutExtraArguments(); return; } switch (m_commandLine.count()) { case 0: case 1: throwError(Tr::tr("Not enough command-line arguments provided.")); case 2: m_compilerPath = m_commandLine.at(0); m_profileName = m_commandLine.at(1); break; default: complainAboutExtraArguments(); } } void CommandLineParser::throwError(const QString &message) { qbs::ErrorInfo error(Tr::tr("Syntax error: %1").arg(message)); error.append(usageString()); throw error; } QString CommandLineParser::usageString() const { QString s = Tr::tr("This tool creates qbs profiles from toolchains.\n"); s += Tr::tr("Usage:\n"); s += Tr::tr(" %1 [%2 ] %3\n") .arg(m_command, settingsDirOption(), detectOption()); s += Tr::tr(" %1 [%3 ] [%2 ] " " \n") .arg(m_command, typeOption(), settingsDirOption()); s += Tr::tr(" %1 %2|%3\n").arg(m_command, helpOptionShort(), helpOptionLong()); s += Tr::tr("The first form tries to auto-detect all known toolchains, looking them up " "via the PATH environment variable.\n"); s += Tr::tr("The second form creates one profile for one toolchain. It will attempt " "to find out the toolchain type automatically.\nIn case the compiler has " "an unusual file name, you may need to provide the '--type' option."); return s; } void CommandLineParser::assignOptionArgument(const QString &option, QString &argument) { if (m_commandLine.isEmpty()) throwError(Tr::tr("Option '%1' needs an argument.").arg(option)); argument = m_commandLine.takeFirst(); if (argument.isEmpty()) throwError(Tr::tr("Argument for option '%1' must not be empty.").arg(option)); } void CommandLineParser::complainAboutExtraArguments() { throwError(Tr::tr("Extraneous command-line arguments '%1'.") .arg(m_commandLine.join(QLatin1Char(' ')))); } qbs-src-1.4.5/src/app/qbs-setup-toolchains/commandlineparser.h000066400000000000000000000047621266132464200244210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_SETUPTOOLCHAINS_COMMANDLINEPARSER_H #define QBS_SETUPTOOLCHAINS_COMMANDLINEPARSER_H #include class CommandLineParser { public: void parse(const QStringList &commandLine); bool helpRequested() const { return m_helpRequested; } bool autoDetectionMode() const { return m_autoDetectionMode; } QString compilerPath() const { return m_compilerPath; } QString toolchainType() const { return m_toolchainType; } QString profileName() const { return m_profileName; } QString settingsDir() const { return m_settingsDir; } QString usageString() const; private: void throwError(const QString &message); void assignOptionArgument(const QString &option, QString &argument); void complainAboutExtraArguments(); bool m_helpRequested; bool m_autoDetectionMode; QString m_compilerPath; QString m_toolchainType; QString m_profileName; QString m_settingsDir; QStringList m_commandLine; QString m_command; }; #endif // Include guard qbs-src-1.4.5/src/app/qbs-setup-toolchains/compilerversion.cpp000066400000000000000000000231161266132464200244630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "compilerversion.h" #include #include #include #include #include #include #include #include #include using namespace qbs; using namespace qbs::Internal; static QString mkStr(const char *s) { return QString::fromLocal8Bit(s); } static QString mkStr(const QByteArray &ba) { return mkStr(ba.constData()); } class TemporaryEnvChanger { public: TemporaryEnvChanger(const QProcessEnvironment &envChanges) { QProcessEnvironment currentEnv = QProcessEnvironment::systemEnvironment(); foreach (const QString &key, envChanges.keys()) { m_changesToRestore.insert(key, currentEnv.value(key)); qputenv(qPrintable(key), qPrintable(envChanges.value(key))); } } ~TemporaryEnvChanger() { foreach (const QString &key, m_changesToRestore.keys()) qputenv(qPrintable(key), qPrintable(m_changesToRestore.value(key))); } private: QProcessEnvironment m_changesToRestore; }; static QByteArray runProcess(const QString &exeFilePath, const QStringList &args, const QProcessEnvironment &env = QProcessEnvironment()) { TemporaryEnvChanger envChanger(env); QProcess process; process.start(exeFilePath, args); if (!process.waitForStarted() || !process.waitForFinished() || process.exitStatus() != QProcess::NormalExit) { throw ErrorInfo(mkStr("Could not run %1 (%2)").arg(exeFilePath, process.errorString())); } if (process.exitCode() != 0) { ErrorInfo e(mkStr("Process '%1' failed with exit code %2.") .arg(exeFilePath).arg(process.exitCode())); const QByteArray stdErr = process.readAllStandardError(); if (!stdErr.isEmpty()) e.append(mkStr("stderr was: %1").arg(mkStr(stdErr))); const QByteArray stdOut = process.readAllStandardOutput(); if (!stdOut.isEmpty()) e.append(mkStr("stdout was: %1").arg(mkStr(stdOut))); throw e; } return process.readAllStandardOutput().trimmed(); } static Version getGccVersion(const QString &compilerFilePath, const QStringList &qbsToolchain) { QByteArray majorKey; QByteArray minorKey; QByteArray patchKey; if (qbsToolchain.contains(QLatin1String("clang"))) { majorKey = "__clang_major__"; minorKey = "__clang_minor__"; patchKey = "__clang_patchlevel__"; } else { majorKey = "__GNUC__"; minorKey = "__GNUC_MINOR__"; patchKey = "__GNUC_PATCHLEVEL__"; } QTemporaryFile dummyFile; if (!dummyFile.open()) throw ErrorInfo(mkStr("Could not create temporary file (%1)").arg(dummyFile.errorString())); dummyFile.close(); const QStringList compilerArgs = QStringList() << QLatin1String("-E") << QLatin1String("-dM") << QLatin1String("-x") << QLatin1String("c") << QLatin1String("-c") << dummyFile.fileName(); const QByteArray compilerOutput = runProcess(compilerFilePath, compilerArgs); if (compilerOutput.isEmpty()) throw ErrorInfo(mkStr("Could not extract version from compiler output.")); const QList lines = compilerOutput.split('\n'); QList keyParts = QList() << majorKey << minorKey << patchKey; QStringList versionParts = QStringList() << QString() << QString() << QString(); int partsFound = 0; foreach (const QByteArray &line, lines) { for (int i = 0; i < keyParts.count() && partsFound < keyParts.count(); ++i) { QString &versionPart = versionParts[i]; if (!versionPart.isEmpty()) continue; const QByteArray cleanLine = line.simplified(); const QByteArray keyPart = "#define " + keyParts.at(i) + ' '; if (!cleanLine.startsWith(keyPart)) continue; versionPart = QString::fromLatin1(cleanLine.mid(keyPart.count())); ++partsFound; } } if (partsFound < keyParts.count()) throw ErrorInfo(mkStr("Failed to extract version from compiler output.")); const Version version = Version::fromString(versionParts.at(0) + QLatin1Char('.') + versionParts.at(1) + QLatin1Char('.') + versionParts.at(2)); if (!version.isValid()) throw ErrorInfo(mkStr("Failed to extract version from compiler output.")); return version; } class DummyFile { public: DummyFile(const QString &fp) : filePath(fp) { } ~DummyFile() { QFile::remove(filePath); } const QString filePath; }; static Version getMsvcVersion(const QString &compilerFilePath, const QProcessEnvironment &compilerEnv) { const QScopedPointer dummyFile( new QTemporaryFile(QDir::tempPath() + QLatin1String("/qbs_dummy"))); if (!dummyFile->open()) { throw ErrorInfo(mkStr("Could not create temporary file (%1)") .arg(dummyFile->errorString())); } const QByteArray magicPrefix = "int version = "; dummyFile->write(magicPrefix + "_MSC_FULL_VER\r\n"); dummyFile->close(); // We cannot use the temporary file itself, as Qt has a lock on it // even after it was closed, causing a "Permission denied" message from MSVC. const QString actualDummyFilePath = dummyFile->fileName() + QLatin1String(".1"); const QString nativeDummyFilePath = QDir::toNativeSeparators(actualDummyFilePath); if (!QFile::copy(dummyFile->fileName(), actualDummyFilePath)) { throw ErrorInfo(mkStr("Could not create source '%1' file for compiler.") .arg(nativeDummyFilePath)); } DummyFile actualDummyFile(actualDummyFilePath); const QString preprocessedFilePath = nativeDummyFilePath + QLatin1String(".i"); const QStringList compilerArgs = QStringList() << QLatin1String("/nologo") << QLatin1String("/P") << nativeDummyFilePath << (QLatin1String("/Fi") + preprocessedFilePath); runProcess(compilerFilePath, compilerArgs, compilerEnv); QFile preprocessedFile(preprocessedFilePath); if (!preprocessedFile.open(QIODevice::ReadOnly)) { throw ErrorInfo(mkStr("Cannot read preprocessed file '%1' (%2)") .arg(preprocessedFilePath, preprocessedFile.errorString())); } QString versionString; foreach (const QByteArray &line, preprocessedFile.readAll().split('\n')) { const QByteArray cleanLine = line.trimmed(); if (cleanLine.startsWith(magicPrefix)) { versionString = QString::fromLocal8Bit(cleanLine.mid(magicPrefix.count())); break; } } if (versionString.isEmpty()) throw ErrorInfo(mkStr("No version number found in preprocessed file.")); if (versionString.count() < 5) throw ErrorInfo(mkStr("Version number '%1' not understood.").arg(versionString)); versionString.insert(2, QLatin1Char('.')).insert(5, QLatin1Char('.')); const Version version = Version::fromString(versionString); if (!version.isValid()) throw ErrorInfo(mkStr("Invalid version string '%1'.").arg(versionString)); return version; } void setCompilerVersion(const QString &compilerFilePath, const QStringList &qbsToolchain, Profile &profile, const QProcessEnvironment &compilerEnv) { try { Version version; if (qbsToolchain.contains(QLatin1String("gcc"))) version = getGccVersion(compilerFilePath, qbsToolchain); else if (qbsToolchain.contains(QLatin1String("msvc"))) version = getMsvcVersion(compilerFilePath, compilerEnv); if (version.isValid()) { profile.setValue(QLatin1String("cpp.compilerVersionMajor"), version.majorVersion()); profile.setValue(QLatin1String("cpp.compilerVersionMinor"), version.minorVersion()); profile.setValue(QLatin1String("cpp.compilerVersionPatch"), version.patchLevel()); } } catch (const ErrorInfo &e) { qDebug("Warning: Failed to retrieve compiler version: %s", qPrintable(e.toString())); } } qbs-src-1.4.5/src/app/qbs-setup-toolchains/compilerversion.h000066400000000000000000000037121266132464200241300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_COMPILERVERSION_H #define QBS_COMPILERVERSION_H #include #include namespace qbs { class Profile; } QT_BEGIN_NAMESPACE class QString; class QStringList; QT_END_NAMESPACE void setCompilerVersion(const QString &compilerFilePath, const QStringList &qbsToolchain, qbs::Profile &profile, const QProcessEnvironment &compilerEnv = QProcessEnvironment()); #endif // Include guard qbs-src-1.4.5/src/app/qbs-setup-toolchains/main.cpp000066400000000000000000000050651266132464200221720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "commandlineparser.h" #include "probe.h" #include #include #include #include #include #include using qbs::Internal::Tr; using qbs::Settings; static void printUsage(const QString &usageString) { std::cout << qPrintable(usageString) << std::endl; } int main(int argc, char **argv) { QCoreApplication app(argc, argv); CommandLineParser clParser; try { clParser.parse(app.arguments()); if (clParser.helpRequested()) { printUsage(clParser.usageString()); return EXIT_SUCCESS; } Settings settings(clParser.settingsDir()); if (clParser.autoDetectionMode()) { probe(&settings); return EXIT_SUCCESS; } createProfile(clParser.profileName(), clParser.toolchainType(), clParser.compilerPath(), &settings); } catch (const qbs::ErrorInfo &e) { std::cerr << qPrintable(e.toString()) << std::endl; return EXIT_FAILURE; } } qbs-src-1.4.5/src/app/qbs-setup-toolchains/msvcinfo.h000066400000000000000000000044421266132464200225350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_MSVCINFO_H #define QBS_MSVCINFO_H #include #include #include #include class MSVC { public: QString version; QString installPath; QString pathPrefix; QStringList architectures; typedef QHash EnvironmentPerArch; EnvironmentPerArch environments; QString clPath(const QString &arch = QString()) { return QDir::cleanPath( installPath + QLatin1Char('/') + pathPrefix + QLatin1Char('/') + arch + QLatin1Char('/') + QLatin1String("cl.exe")); } }; class WinSDK : public MSVC { public: bool isDefault; WinSDK() { pathPrefix = QLatin1String("bin"); } }; #endif // QBS_MSVCINFO_H qbs-src-1.4.5/src/app/qbs-setup-toolchains/msvcprobe.cpp000066400000000000000000000212531266132464200232430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "msvcprobe.h" #include "compilerversion.h" #include "msvcinfo.h" #include "probe.h" #include "vsenvironmentdetector.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include #include #include using namespace qbs; using Internal::Tr; QT_BEGIN_NAMESPACE Q_DECLARE_TYPEINFO(WinSDK, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(MSVC, Q_MOVABLE_TYPE); QT_END_NAMESPACE static void writeEnvironment(Profile &p, const QProcessEnvironment &env) { foreach (const QString &name, env.keys()) p.setValue(QLatin1String("buildEnvironment.") + name, env.value(name)); } static void addMSVCPlatform(const MSVC &msvc, Settings *settings, QList &profiles, QString name, const QString &installPath, const QString &architecture) { name.append(QLatin1Char('_') + architecture); qbsInfo() << Tr::tr("Setting up profile '%1'.").arg(name); Profile p(name, settings); p.removeProfile(); p.setValue(QLatin1String("qbs.targetOS"), QStringList(QLatin1String("windows"))); p.setValue(QLatin1String("cpp.toolchainInstallPath"), installPath); p.setValue(QLatin1String("qbs.toolchain"), QStringList(QLatin1String("msvc"))); p.setValue(QLatin1String("qbs.architecture"), canonicalArchitecture(architecture)); const QProcessEnvironment compilerEnvironment = msvc.environments.value(architecture); setCompilerVersion(installPath + QLatin1String("/cl.exe"), QStringList(QLatin1String("msvc")), p, compilerEnvironment); writeEnvironment(p, compilerEnvironment); profiles << p; } static void findSupportedArchitectures(MSVC *msvc) { if (QFile::exists(msvc->clPath()) || QFile::exists(msvc->clPath(QLatin1String("amd64_x86")))) msvc->architectures += QLatin1String("x86"); if (QFile::exists(msvc->clPath(QLatin1String("amd64"))) || QFile::exists(msvc->clPath(QLatin1String("x86_amd64")))) msvc->architectures += QLatin1String("x86_64"); if (QFile::exists(msvc->clPath(QLatin1String("ia64"))) || QFile::exists(msvc->clPath(QLatin1String("x86_ia64")))) msvc->architectures += QLatin1String("ia64"); if (QFile::exists(msvc->clPath(QLatin1String("x86_arm"))) || QFile::exists(msvc->clPath(QLatin1String("amd64_arm")))) msvc->architectures += QLatin1String("armv7"); } static QString wow6432Key() { #ifdef Q_OS_WIN64 return QLatin1String("\\Wow6432Node"); #else return QString(); #endif } void msvcProbe(Settings *settings, QList &profiles) { qbsInfo() << Tr::tr("Detecting MSVC toolchains..."); // 1) Installed SDKs preferred over standalone Visual studio QVector winSDKs; WinSDK defaultWinSDK; const QSettings sdkRegistry(QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE") + wow6432Key() + QLatin1String("\\Microsoft\\Microsoft SDKs\\Windows"), QSettings::NativeFormat); const QString defaultSdkPath = sdkRegistry.value(QLatin1String("CurrentInstallFolder")).toString(); if (!defaultSdkPath.isEmpty()) { foreach (const QString &sdkKey, sdkRegistry.childGroups()) { WinSDK sdk; sdk.version = sdkKey; sdk.installPath = sdkRegistry.value(sdkKey + QLatin1String("/InstallationFolder")).toString(); sdk.isDefault = (sdk.installPath == defaultSdkPath); if (sdk.installPath.isEmpty()) continue; if (sdk.installPath.endsWith(QLatin1Char('\\'))) sdk.installPath.chop(1); findSupportedArchitectures(&sdk); if (sdk.isDefault) defaultWinSDK = sdk; winSDKs += sdk; } } foreach (const WinSDK &sdk, winSDKs) { qbsInfo() << Tr::tr(" Windows SDK %1 detected:\n" " installed in %2").arg(sdk.version, sdk.installPath); if (!sdk.architectures.isEmpty()) qbsInfo() << Tr::tr(" This SDK contains C++ compiler(s)."); if (sdk.isDefault) qbsInfo() << Tr::tr(" This is the default SDK on this machine."); } // 2) Installed MSVCs QVector msvcs; const QSettings vsRegistry( QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE") + wow6432Key() + QLatin1String("\\Microsoft\\VisualStudio\\SxS\\VC7"), QSettings::NativeFormat); foreach (const QString &vsName, vsRegistry.allKeys()) { // Scan for version major.minor const int dotPos = vsName.indexOf(QLatin1Char('.')); if (dotPos == -1) continue; MSVC msvc; msvc.installPath = vsRegistry.value(vsName).toString(); if (!msvc.installPath.endsWith(QLatin1Char('\\'))) msvc.installPath += QLatin1Char('\\'); msvc.installPath += QLatin1String("bin"); findSupportedArchitectures(&msvc); int nVersion = vsName.left(dotPos).toInt(); switch (nVersion) { case 8: msvc.version = QLatin1String("2005"); break; case 9: msvc.version = QLatin1String("2008"); break; case 10: msvc.version = QLatin1String("2010"); break; case 11: msvc.version = QLatin1String("2012"); break; case 12: msvc.version = QLatin1String("2013"); break; case 14: msvc.version = QLatin1String("2015"); break; } if (msvc.version.isEmpty()) { qbsWarning() << Tr::tr("Unknown MSVC version %1 found.").arg(nVersion); continue; } // Check existence of various install scripts const QString vcvars32bat = msvc.installPath + QLatin1String("/vcvars32.bat"); if (!QFileInfo(vcvars32bat).isFile()) continue; VsEnvironmentDetector envdetector(&msvc); if (!envdetector.start()) { qbsError() << " " << Tr::tr("Detecting the build environment from '%1' failed.").arg( vcvars32bat); continue; } msvcs += msvc; } foreach (const MSVC &msvc, msvcs) { qbsInfo() << Tr::tr(" MSVC detected:\n" " version %1\n" " installed in %2").arg(msvc.version, msvc.installPath); } if (winSDKs.isEmpty() && msvcs.isEmpty()) { qbsInfo() << Tr::tr("Could not detect an installation of " "the Windows SDK or Visual Studio."); return; } foreach (const WinSDK &sdk, winSDKs) { foreach (const QString &arch, sdk.architectures) { addMSVCPlatform(sdk, settings, profiles, QLatin1String("WinSDK") + sdk.version, sdk.installPath + QLatin1String("\\bin"), arch); } } foreach (const MSVC &msvc, msvcs) { foreach (const QString &arch, msvc.architectures) { addMSVCPlatform(msvc, settings, profiles, QLatin1String("MSVC") + msvc.version, msvc.installPath, arch); } } } qbs-src-1.4.5/src/app/qbs-setup-toolchains/msvcprobe.h000066400000000000000000000033021266132464200227030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef MSVCPROBE_H #define MSVCPROBE_H #include namespace qbs { class Profile; class Settings; } void msvcProbe(qbs::Settings *settings, QList &profiles); #endif // MSVCPROBE_H qbs-src-1.4.5/src/app/qbs-setup-toolchains/probe.cpp000066400000000000000000000316731266132464200223610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "probe.h" #include "compilerversion.h" #include "msvcprobe.h" #include "xcodeprobe.h" #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace qbs; using Internal::HostOsInfo; using Internal::Tr; static QTextStream qStdout(stdout); static QTextStream qStderr(stderr); static QString findExecutable(const QString &fileName) { const QString path = QString::fromLocal8Bit(qgetenv("PATH")); foreach (const QString &ppath, path.split(HostOsInfo::pathListSeparator())) { const QString fullPath = ppath + QLatin1Char('/') + fileName; if (QFileInfo(fullPath).exists()) return QDir::cleanPath(fullPath); } return QString(); } static QString qsystem(const QString &exe, const QStringList &args = QStringList()) { QProcess p; p.setProcessChannelMode(QProcess::MergedChannels); p.start(exe, args); if (!p.waitForStarted()) { throw qbs::ErrorInfo(Tr::tr("Failed to start compiler '%1': %2") .arg(exe, p.errorString())); } if (!p.waitForFinished() || p.exitCode() != 0) throw qbs::ErrorInfo(Tr::tr("Failed to run compiler '%1': %2").arg(exe, p.errorString())); return QString::fromLocal8Bit(p.readAll()); } static QStringList validMinGWMachines() { // List of MinGW machine names (gcc -dumpmachine) recognized by Qbs return QStringList() << QLatin1String("mingw32") << QLatin1String("mingw64") << QLatin1String("i686-w64-mingw32") << QLatin1String("x86_64-w64-mingw32") << QLatin1String("i686-w64-mingw32.shared") << QLatin1String("x86_64-w64-mingw32.shared") << QLatin1String("i686-w64-mingw32.static") << QLatin1String("x86_64-w64-mingw32.static") << QLatin1String("i586-mingw32msvc") << QLatin1String("amd64-mingw32msvc"); } static QStringList completeToolchainList(const QString &toolchainName) { QStringList toolchains(toolchainName); if (toolchainName == QLatin1String("clang")) toolchains << completeToolchainList(QLatin1String("llvm")); else if (toolchainName == QLatin1String("llvm") || toolchainName == QLatin1String("mingw")) { toolchains << completeToolchainList(QLatin1String("gcc")); } return toolchains; } static QStringList toolchainTypeFromCompilerName(const QString &compilerName) { if (compilerName == QLatin1String("cl.exe")) return completeToolchainList(QLatin1String("msvc")); foreach (const QString &type, (QStringList() << QLatin1String("clang") << QLatin1String("llvm") << QLatin1String("mingw") << QLatin1String("gcc"))) if (compilerName.contains(type)) return completeToolchainList(type); return QStringList(); } static QString gccMachineName(const QString &compilerFilePath) { return qsystem(compilerFilePath, QStringList() << QLatin1String("-dumpmachine")).trimmed(); } static QStringList standardCompilerFileNames() { return QStringList() << HostOsInfo::appendExecutableSuffix(QStringLiteral("gcc")) << HostOsInfo::appendExecutableSuffix(QStringLiteral("g++")) << HostOsInfo::appendExecutableSuffix(QStringLiteral("clang")) << HostOsInfo::appendExecutableSuffix(QStringLiteral("clang++")); } static void setCommonProperties(Profile &profile, const QString &compilerFilePath, const QStringList &toolchainTypes, const QString &architecture) { const QFileInfo cfi(compilerFilePath); const QString compilerName = QFileInfo(compilerFilePath).fileName(); if (toolchainTypes.contains(QStringLiteral("mingw"))) profile.setValue(QStringLiteral("qbs.targetOS"), QStringList(QStringLiteral("windows"))); const QString prefix = compilerName.left(compilerName.lastIndexOf(QLatin1Char('-')) + 1); if (!prefix.isEmpty()) profile.setValue(QLatin1String("cpp.toolchainPrefix"), prefix); profile.setValue(QLatin1String("cpp.toolchainInstallPath"), cfi.absolutePath()); profile.setValue(QLatin1String("qbs.toolchain"), toolchainTypes); profile.setValue(QLatin1String("qbs.architecture"), canonicalArchitecture(architecture)); setCompilerVersion(compilerFilePath, toolchainTypes, profile); const QString suffix = compilerName.right(compilerName.size() - prefix.size()); if (!standardCompilerFileNames().contains(suffix)) qWarning("%s", qPrintable( QString::fromLatin1("'%1' is not a standard compiler file name; " "you must set the cpp.cCompilerName and " "cpp.cxxCompilerName properties of this profile " "manually").arg(compilerName))); } class ToolPathSetup { public: ToolPathSetup(Profile *profile, const QString &path, const QString &toolchainPrefix) : m_profile(profile), m_compilerDirPath(path), m_toolchainPrefix(toolchainPrefix) { } void apply(const QString &toolName, const QString &propertyName) const { QString toolFileName = m_toolchainPrefix + HostOsInfo::appendExecutableSuffix(toolName); if (QFile::exists(m_compilerDirPath + QLatin1Char('/') + toolFileName)) return; const QString toolFilePath = findExecutable(toolFileName); if (toolFilePath.isEmpty()) { qWarning("%s", qPrintable( QString(QLatin1String("'%1' exists neither in '%2' nor in PATH.")) .arg(toolFileName, m_compilerDirPath))); } m_profile->setValue(propertyName, toolFilePath); } private: Profile * const m_profile; const QString &m_compilerDirPath; const QString &m_toolchainPrefix; }; static Profile createGccProfile(const QString &compilerFilePath, Settings *settings, const QStringList &toolchainTypes, const QString &profileName = QString()) { const QString machineName = gccMachineName(compilerFilePath); const QStringList compilerTriplet = machineName.split(QLatin1Char('-')); if (toolchainTypes.contains(QLatin1String("mingw"))) { if (!validMinGWMachines().contains(machineName)) { throw ErrorInfo(Tr::tr("Detected gcc platform '%1' is not supported.") .arg(machineName)); } } else if (compilerTriplet.count() < 2) { throw qbs::ErrorInfo(Tr::tr("Architecture of compiler for platform '%1' at '%2' not understood.") .arg(machineName, compilerFilePath)); } Profile profile(!profileName.isEmpty() ? profileName : machineName, settings); profile.removeProfile(); setCommonProperties(profile, compilerFilePath, toolchainTypes, compilerTriplet.first()); // Check whether auxiliary tools reside within the toolchain's install path. // This might not be the case when using icecc or another compiler wrapper. const QString compilerDirPath = QFileInfo(compilerFilePath).absolutePath(); const ToolPathSetup toolPathSetup(&profile, compilerDirPath, profile.value(QStringLiteral("cpp.toolchainPrefix")) .toString()); toolPathSetup.apply(QLatin1String("ar"), QLatin1String("cpp.archiverPath")); toolPathSetup.apply(QLatin1String("nm"), QLatin1String("cpp.nmPath")); if (HostOsInfo::isOsxHost()) toolPathSetup.apply(QLatin1String("dsymutil"), QLatin1String("cpp.dsymutilPath")); else toolPathSetup.apply(QLatin1String("objcopy"), QLatin1String("cpp.objcopyPath")); toolPathSetup.apply(QLatin1String("strip"), QLatin1String("cpp.stripPath")); qStdout << Tr::tr("Profile '%1' created for '%2'.").arg(profile.name(), compilerFilePath) << endl; return profile; } static void gccProbe(Settings *settings, QList &profiles, const QString &compilerName) { qStdout << Tr::tr("Trying to detect %1...").arg(compilerName) << endl; const QString crossCompilePrefix = QString::fromLocal8Bit(qgetenv("CROSS_COMPILE")); const QString compilerFilePath = findExecutable(crossCompilePrefix + compilerName); if (!QFileInfo(compilerFilePath).exists()) { qStderr << Tr::tr("%1 not found.").arg(compilerName) << endl; return; } const QString profileName = QFileInfo(compilerFilePath).completeBaseName(); const QStringList toolchainTypes = toolchainTypeFromCompilerName(compilerName); profiles << createGccProfile(compilerFilePath, settings, toolchainTypes, profileName); } static void mingwProbe(Settings *settings, QList &profiles) { // List of possible compiler binary names for this platform QStringList compilerNames; if (HostOsInfo::isWindowsHost()) { compilerNames << QLatin1String("gcc"); } else { foreach (const QString &machineName, validMinGWMachines()) { compilerNames << machineName + QLatin1String("-gcc"); } } foreach (const QString &compilerName, compilerNames) { const QString gccPath = findExecutable(HostOsInfo::appendExecutableSuffix(compilerName)); if (!gccPath.isEmpty()) profiles << createGccProfile(gccPath, settings, completeToolchainList(QLatin1String("mingw"))); } } void probe(Settings *settings) { QList profiles; if (HostOsInfo::isWindowsHost()) { msvcProbe(settings, profiles); } else { gccProbe(settings, profiles, QLatin1String("gcc")); gccProbe(settings, profiles, QLatin1String("clang")); if (HostOsInfo::isOsxHost()) { xcodeProbe(settings, profiles); } } mingwProbe(settings, profiles); if (profiles.isEmpty()) { qStderr << Tr::tr("Could not detect any toolchains. No profile created.") << endl; } else if (profiles.count() == 1 && settings->defaultProfile().isEmpty()) { const QString profileName = profiles.first().name(); qStdout << Tr::tr("Making profile '%1' the default.").arg(profileName) << endl; settings->setValue(QLatin1String("defaultProfile"), profileName); } } void createProfile(const QString &profileName, const QString &toolchainType, const QString &compilerFilePath, Settings *settings) { QFileInfo compiler(compilerFilePath); if (compilerFilePath == compiler.fileName() && !compiler.exists()) compiler = QFileInfo(findExecutable(compilerFilePath)); if (!compiler.exists()) { throw qbs::ErrorInfo(Tr::tr("Compiler '%1' not found") .arg(compilerFilePath)); } QStringList toolchainTypes; if (toolchainType.isEmpty()) toolchainTypes = toolchainTypeFromCompilerName(compiler.fileName()); else toolchainTypes = completeToolchainList(toolchainType); if (toolchainTypes.contains(QLatin1String("msvc"))) { throw qbs::ErrorInfo(Tr::tr("Cannot create profile: MSVC toolchains can only be created " "via the auto-detection mechanism.")); } if (toolchainTypes.contains(QLatin1String("gcc"))) createGccProfile(compiler.absoluteFilePath(), settings, toolchainTypes, profileName); else throw qbs::ErrorInfo(Tr::tr("Cannot create profile: Unknown toolchain type.")); } qbs-src-1.4.5/src/app/qbs-setup-toolchains/probe.h000066400000000000000000000035661266132464200220260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROBE_H #define QBS_PROBE_H #include QT_BEGIN_NAMESPACE class QString; class QStringList; QT_END_NAMESPACE namespace qbs { class Settings; } void createProfile(const QString &profileName, const QString &toolchainType, const QString &compilerFilePath, qbs::Settings *settings); void probe(qbs::Settings *settings); #endif // Header guard qbs-src-1.4.5/src/app/qbs-setup-toolchains/qbs-setup-toolchains.exe.manifest000066400000000000000000000007361266132464200271360ustar00rootroot00000000000000 qbs-src-1.4.5/src/app/qbs-setup-toolchains/qbs-setup-toolchains.pro000066400000000000000000000006561266132464200253510ustar00rootroot00000000000000include(../app.pri) TARGET = qbs-setup-toolchains HEADERS += \ commandlineparser.h \ compilerversion.h \ msvcinfo.h \ msvcprobe.h \ probe.h \ vsenvironmentdetector.h \ xcodeprobe.h SOURCES += \ commandlineparser.cpp \ compilerversion.cpp \ main.cpp \ msvcprobe.cpp \ probe.cpp \ vsenvironmentdetector.cpp \ xcodeprobe.cpp mingw { RC_FILE = qbs-setup-toolchains.rc } qbs-src-1.4.5/src/app/qbs-setup-toolchains/qbs-setup-toolchains.qbs000066400000000000000000000010421266132464200253240ustar00rootroot00000000000000import qbs 1.0 QbsApp { name: "qbs-setup-toolchains" cpp.dynamicLibraries: qbs.targetOS.contains("windows") ? base.concat("shell32") : base files: [ "commandlineparser.cpp", "commandlineparser.h", "compilerversion.cpp", "compilerversion.h", "main.cpp", "msvcinfo.h", "msvcprobe.cpp", "msvcprobe.h", "probe.cpp", "probe.h", "vsenvironmentdetector.cpp", "vsenvironmentdetector.h", "xcodeprobe.cpp", "xcodeprobe.h" ] } qbs-src-1.4.5/src/app/qbs-setup-toolchains/qbs-setup-toolchains.rc000066400000000000000000000002301266132464200251410ustar00rootroot00000000000000#define RT_MANIFEST 24 #define CREATEPROCESS_MANIFEST_RESOURCE_ID 1 CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "qbs-setup-toolchains.exe.manifest" qbs-src-1.4.5/src/app/qbs-setup-toolchains/vsenvironmentdetector.cpp000066400000000000000000000141121266132464200257060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "vsenvironmentdetector.h" #include "msvcinfo.h" #include #include #include #include #include #include #include #ifdef Q_OS_WIN #include #include #endif using qbs::Internal::Tr; static QString windowsSystem32Path() { #ifdef Q_OS_WIN wchar_t str[MAX_PATH]; if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_SYSTEM, NULL, 0, str))) return QString::fromUtf16(reinterpret_cast(str)); #endif return QString(); } VsEnvironmentDetector::VsEnvironmentDetector(MSVC *msvc) : m_msvc(msvc) , m_windowsSystemDirPath(windowsSystem32Path()) { } bool VsEnvironmentDetector::start() { m_msvc->environments.clear(); const QString vcvarsallbat = QDir::cleanPath(m_msvc->installPath + QLatin1String("/../vcvarsall.bat")); if (!QFile::exists(vcvarsallbat)) { m_errorString = Tr::tr("Cannot find '%1'.").arg(QDir::toNativeSeparators(vcvarsallbat)); return false; } QTemporaryFile tmpFile(QDir::tempPath() + QLatin1Char('/') + QLatin1String("XXXXXX.bat")); if (!tmpFile.open()) { m_errorString = Tr::tr("Cannot open temporary file '%1' for writing.").arg( tmpFile.fileName()); return false; } writeBatchFile(&tmpFile, vcvarsallbat); tmpFile.flush(); QProcess process; const QString shellFilePath = QLatin1String("cmd.exe"); process.start(shellFilePath, QStringList() << QLatin1String("/C") << tmpFile.fileName()); if (!process.waitForStarted()) { m_errorString = Tr::tr("Failed to start '%1'.").arg(shellFilePath); return false; } process.waitForFinished(-1); if (process.exitStatus() != QProcess::NormalExit) { m_errorString = Tr::tr("Process '%1' did not exit normally.").arg(shellFilePath); return false; } if (process.exitCode() != 0) { m_errorString = Tr::tr("Failed to detect Visual Studio environment."); return false; } parseBatOutput(process.readAllStandardOutput()); return true; } static void batClearVars(QTextStream &s, const QStringList &varnames) { foreach (const QString &varname, varnames) s << "set " << varname << '=' << endl; } static void batPrintVars(QTextStream &s, const QStringList &varnames) { foreach (const QString &varname, varnames) s << "echo " << varname << "=%" << varname << '%' << endl; } static QString vcArchitecture(const QString &arch) { if (arch == QLatin1String("armv7")) return QLatin1String("arm"); if (arch == QLatin1String("x86_64")) return QLatin1String("amd64"); return arch; } void VsEnvironmentDetector::writeBatchFile(QIODevice *device, const QString &vcvarsallbat) const { const QStringList varnames = QStringList() << QLatin1String("PATH") << QLatin1String("INCLUDE") << QLatin1String("LIB"); QTextStream s(device); s << "@echo off" << endl; foreach (const QString &architecture, m_msvc->architectures) { s << "echo --" << architecture << "--" << endl << "setlocal" << endl; batClearVars(s, varnames); s << "set PATH=" << m_windowsSystemDirPath << endl; // vcvarsall.bat needs tools from here s << "call \"" << vcvarsallbat << "\" " << vcArchitecture(architecture) << " || exit /b 1" << endl; batPrintVars(s, varnames); s << "endlocal" << endl; } } void VsEnvironmentDetector::parseBatOutput(const QByteArray &output) { QString arch; QProcessEnvironment *targetEnv = 0; foreach (QByteArray line, output.split('\n')) { line = line.trimmed(); if (line.isEmpty()) continue; if (line.startsWith("--") && line.endsWith("--")) { line.remove(0, 2); line.chop(2); arch = QString::fromLocal8Bit(line); targetEnv = &m_msvc->environments[arch]; } else { int idx = line.indexOf('='); if (idx < 0) continue; QBS_CHECK(targetEnv); const QString name = QString::fromLocal8Bit(line.left(idx)); QString value = QString::fromLocal8Bit(line.mid(idx + 1)); if (name.compare(QLatin1String("PATH"), Qt::CaseInsensitive) == 0) value.remove(m_windowsSystemDirPath); if (value.endsWith(QLatin1Char(';'))) value.chop(1); if (value.endsWith(QLatin1Char('\\'))) value.chop(1); targetEnv->insert(name, value); } } } qbs-src-1.4.5/src/app/qbs-setup-toolchains/vsenvironmentdetector.h000066400000000000000000000041021266132464200253510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_VSENVIRONMENTDETECTOR_H #define QBS_VSENVIRONMENTDETECTOR_H #include QT_BEGIN_NAMESPACE class QIODevice; QT_END_NAMESPACE class MSVC; class VsEnvironmentDetector { public: VsEnvironmentDetector(MSVC *msvc); bool start(); QString errorString() const { return m_errorString; } private: void writeBatchFile(QIODevice *device, const QString &vcvarsallbat) const; void parseBatOutput(const QByteArray &output); MSVC *m_msvc; const QString m_windowsSystemDirPath; QString m_errorString; }; #endif // QBS_VSENVIRONMENTDETECTOR_H qbs-src-1.4.5/src/app/qbs-setup-toolchains/xcodeprobe.cpp000066400000000000000000000410551266132464200233770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "probe.h" #include "xcodeprobe.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include #include #include #include #include using namespace qbs; using Internal::Tr; namespace { static QString qsystem(const QString &exe, const QStringList &args = QStringList()) { QProcess p; p.setProcessChannelMode(QProcess::MergedChannels); p.start(exe, args); p.waitForFinished(); return QString::fromLocal8Bit(p.readAll()); } class XcodeProbe { public: XcodeProbe(qbs::Settings *settings, QList &profiles) : settings(settings), profiles(profiles) { } static int compareVersions(const QString &v1, const QString &v2); bool addDeveloperPath(const QString &path); void detectDeveloperPaths(); void setArch(Profile *profile, const QString &pathToGcc, const QStringList &extraFlags); void setupDefaultToolchains(const QString &devPath, const QString &xCodeName); void detectAll(); private: qbs::Settings *settings; QList &profiles; QStringList developerPaths; }; int XcodeProbe::compareVersions(const QString &v1, const QString &v2) { QStringList v1L = v1.split(QLatin1Char('.'), QString::SkipEmptyParts); QStringList v2L = v2.split(QLatin1Char('.'), QString::SkipEmptyParts); int i = 0; while (v1L.length() > i && v2L.length() > i) { bool n1Ok, n2Ok; int n1 = v1L.value(i).toInt(&n1Ok); int n2 = v2L.value(i).toInt(&n2Ok); if (!(n1Ok && n2Ok)) { qbsInfo() << Tr::tr("Failed to compare version %1 and %2").arg(v1,v2); return 0; } if (n1 > n2) return -1; else if (n1 < n2) return 1; ++i; } if (v1L.length() > v2L.length()) return -1; if (v1L.length() < v2L.length()) return 1; return 0; } bool XcodeProbe::addDeveloperPath(const QString &path) { if (path.isEmpty()) return false; QFileInfo pInfo(path); if (!pInfo.exists() || !pInfo.isDir()) return false; if (developerPaths.contains(path)) return false; developerPaths.append(path); qbsInfo() << Tr::tr("Added developer path %1").arg(path); return true; } void XcodeProbe::detectDeveloperPaths() { QProcess selectedXcode; QString program = QLatin1String("/usr/bin/xcode-select"); QStringList arguments(QLatin1String("--print-path")); selectedXcode.start(program, arguments, QProcess::ReadOnly); if (!selectedXcode.waitForFinished() || selectedXcode.exitCode()) { qbsInfo() << Tr::tr("Could not detect selected xcode with /usr/bin/xcode-select"); } else { QString path = QString::fromLocal8Bit(selectedXcode.readAllStandardOutput()); addDeveloperPath(path); } addDeveloperPath(QLatin1String("/Applications/Xcode.app/Contents/Developer")); } void XcodeProbe::setArch(Profile *profile, const QString &pathToGcc, const QStringList &extraFlags) { if (!extraFlags.isEmpty()) { profile->setValue(QLatin1String("cpp.platformCommonCompilerFlags"), extraFlags); profile->setValue(QLatin1String("cpp.platformLinkerFlags"), extraFlags); } // setting architecture only here, bercause the same compiler // can support several ones QStringList flags(extraFlags); flags << QLatin1String("-dumpmachine"); QString compilerTriplet = qsystem(pathToGcc, flags).simplified(); QStringList compilerTripletl = compilerTriplet.split(QLatin1Char('-')); if (compilerTripletl.count() < 2) { qbsError() << QString::fromLocal8Bit("Detected '%1', but I do not understand " "its architecture '%2'.") .arg(pathToGcc, compilerTriplet); return; } const QString architecture = compilerTripletl.at(0); qbsInfo() << Tr::tr(" Toolchain %1 detected:\n" " binary: %2\n" " triplet: %3\n" " arch: %4").arg(profile->name(), pathToGcc, compilerTriplet, architecture); profile->setValue(QLatin1String("qbs.architecture"), canonicalArchitecture(architecture)); } void XcodeProbe::setupDefaultToolchains(const QString &devPath, const QString &xCodeName) { qbsInfo() << Tr::tr("Setting up profile '%1'.").arg(xCodeName); QString indent = QLatin1String(" "); // detect clang (default toolchain) QFileInfo clangFileInfo(devPath + QLatin1String("/Toolchains/XcodeDefault.xctoolchain/usr/bin") + QLatin1String("/clang++")); bool hasClang = clangFileInfo.exists(); if (!hasClang) qbsInfo() << indent << Tr::tr("Default toolchain %1 not found.") .arg(clangFileInfo.canonicalFilePath()); // Platforms QDir platformsDir(devPath + QLatin1String("/Platforms")); QFileInfoList platforms = platformsDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); foreach (const QFileInfo &fInfo, platforms) { if (fInfo.isDir() && fInfo.suffix() == QLatin1String("platform")) { qbsInfo() << indent << Tr::tr("Setting up %1").arg(fInfo.fileName()); QSettings infoSettings(fInfo.absoluteFilePath() + QLatin1String("/Info.plist") , QSettings::NativeFormat); if (!infoSettings.contains(QLatin1String("Name"))) { qbsInfo() << indent << Tr::tr("Missing platform name in Info.plist of %1") .arg(fInfo.absoluteFilePath()); continue; } QStringList targetOS; targetOS << QLatin1String("darwin") << QLatin1String("bsd") << QLatin1String("unix"); QString name = infoSettings.value(QLatin1String("Name")).toString(); if (name == QLatin1String("macosx")) { targetOS << QLatin1String("osx"); } else if (name == QLatin1String("iphoneos")) { targetOS << QLatin1String("ios"); } else if (name == QLatin1String("iphonesimulator")) { targetOS << QLatin1String("ios") << QLatin1String("ios-simulator"); } else { qbsInfo() << indent << Tr::tr("Skipping unknown platform %1").arg(name); continue; } // prepare default platform properties QVariantMap defaultProp = infoSettings.value(QLatin1String("DefaultProperties")) .toMap(); QVariantMap overrideProp = infoSettings.value(QLatin1String("OverrideProperties")) .toMap(); QMapIterator i(overrideProp); while (i.hasNext()) { i.next(); // use unite? might lead to double insertions... defaultProp[i.key()] = i.value(); } QString clangFullName = xCodeName + QLatin1Char('-') + name + QLatin1String("-clang"); // detect gcc QFileInfo gccFileInfo(fInfo.absoluteFilePath() + QLatin1String("/Developer/usr/bin/g++")); QString gccFullName = xCodeName + QLatin1Char('-') + name + QLatin1String("-gcc"); if (!gccFileInfo.exists()) gccFileInfo = QFileInfo(devPath + QLatin1String("/usr/bin/g++")); bool hasGcc = gccFileInfo.exists(); // set SDKs/sysroot QString sysRoot; { QString sdkName; if (defaultProp.contains(QLatin1String("SDKROOT"))) sdkName = defaultProp.value(QLatin1String("SDKROOT")).toString(); QString sdkPath; QDir sdks(fInfo.absoluteFilePath() + QLatin1String("/Developer/SDKs")); QString maxVersion; foreach (const QFileInfo &sdkDirInfo, sdks.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) { indent = QLatin1String(" "); QSettings sdkInfo(sdkDirInfo.absoluteFilePath() + QLatin1String("/SDKSettings.plist") , QSettings::NativeFormat); QString versionStr = sdkInfo.value(QLatin1String("Version")).toString(); QVariant currentSdkName = sdkInfo.value(QLatin1String("CanonicalName")); bool isBaseSdk = sdkInfo.value((QLatin1String("isBaseSDK"))).toString() .toLower() != QLatin1String("no"); if (!isBaseSdk) { qbsInfo() << indent << Tr::tr("Skipping non base Sdk %1").arg(currentSdkName.toString()); continue; } QString safeName = currentSdkName.toString() .replace(QRegExp(QLatin1String("[^-a-zA-Z0-9]")),QLatin1String("-")); if (sdkName.isEmpty()) { if (compareVersions(maxVersion,versionStr) > 0) { maxVersion = versionStr; sdkPath = sdkDirInfo.canonicalFilePath(); } } else if (currentSdkName == sdkName) { sdkPath = sdkDirInfo.canonicalFilePath(); } if (hasClang){ Profile pSdk(xCodeName + QLatin1Char('-') + safeName + QLatin1String("-clang"), settings); pSdk.removeProfile(); pSdk.setBaseProfile(clangFullName); pSdk.setValue(QLatin1String("qbs.sysroot"), sdkDirInfo.canonicalFilePath()); pSdk.setValue(QLatin1String("cpp.xcodeSdkName"), currentSdkName.toString()); pSdk.setValue(QLatin1String("cpp.xcodeSdkVersion"), versionStr); qbsInfo() << indent << Tr::tr("* adding profile %1").arg(pSdk.name()); profiles << pSdk; } if (hasGcc) { Profile pSdk(xCodeName + QLatin1Char('-') + safeName + QLatin1String("-gcc"), settings); pSdk.removeProfile(); pSdk.setBaseProfile(gccFullName); pSdk.setValue(QLatin1String("qbs.sysroot"), sdkDirInfo.canonicalFilePath()); pSdk.setValue(QLatin1String("cpp.xcodeSdkName"), currentSdkName.toString()); pSdk.setValue(QLatin1String("cpp.xcodeSdkVersion"), versionStr); qbsInfo() << indent << Tr::tr("* adding profile %1").arg(pSdk.name()); profiles << pSdk; } } if (!sdkPath.isEmpty()) sysRoot = sdkPath; else if (!sdkName.isEmpty()) qbsInfo() << indent << Tr::tr("Failed to find sysroot %1").arg(sdkName); } if (hasClang) { Profile clangProfile(clangFullName, settings); clangProfile.removeProfile(); clangProfile.setValue(QLatin1String("qbs.targetOS"), targetOS); clangProfile.setValue(QLatin1String("qbs.toolchain"), QStringList() << QLatin1String("clang") << QLatin1String("llvm") << QLatin1String("gcc")); QStringList extraFlags; if (defaultProp.contains(QLatin1String("ARCHS"))) { QString arch = defaultProp.value(QLatin1String("ARCHS")).toString(); if (arch == QLatin1String("$(NATIVE_ARCH_32_BIT)")) extraFlags << QLatin1String("-arch") << QLatin1String("i386"); } if (defaultProp.contains(QLatin1String("NATIVE_ARCH"))) { QString arch = defaultProp.value(QLatin1String("NATIVE_ARCH")).toString(); if (!arch.startsWith(QLatin1String("arm"))) qbsInfo() << indent << Tr::tr("Expected arm architecture, not %1").arg(arch); extraFlags << QLatin1String("-arch") << arch; } if (!sysRoot.isEmpty()) clangProfile.setValue(QLatin1String("qbs.sysroot"), sysRoot); clangProfile.setValue(QLatin1String("cpp.platformPath"), fInfo.canonicalFilePath()); clangProfile.setValue(QLatin1String("cpp.compilerName"), clangFileInfo.fileName()); clangProfile.setValue(QLatin1String("cpp.linkerName"), QLatin1String("clang++")); clangProfile.setValue(QLatin1String("cpp.toolchainInstallPath"), clangFileInfo.canonicalPath()); setArch(&clangProfile, clangFileInfo.canonicalFilePath(), extraFlags); qbsInfo() << indent << Tr::tr("* adding profile %1").arg(clangProfile.name()); profiles << clangProfile; } if (hasGcc) { Profile gccProfile(gccFullName, settings); gccProfile.removeProfile(); // use the arm-apple-darwin10-llvm-* variant if available??? gccProfile.setValue(QLatin1String("qbs.targetOS"), targetOS); QStringList toolchainTypes; toolchainTypes << QLatin1String("gcc"); if (gccFullName.contains(QLatin1String("llvm"))) toolchainTypes << QLatin1String("llvm"); gccProfile.setValue(QLatin1String("qbs.toolchain"), toolchainTypes); if (!sysRoot.isEmpty()) gccProfile.setValue(QLatin1String("qbs.sysroot"), sysRoot); gccProfile.setValue(QLatin1String("cpp.platformPath"),fInfo.canonicalFilePath()); gccProfile.setValue(QLatin1String("cpp.compilerName"), gccFileInfo.fileName()); gccProfile.setValue(QLatin1String("cpp.linkerName"), QLatin1String("g++")); gccProfile.setValue(QLatin1String("cpp.toolchainInstallPath"), gccFileInfo.canonicalPath()); setArch(&gccProfile, gccFileInfo.canonicalFilePath(), QStringList()); qbsInfo() << indent << Tr::tr("* adding profile %1").arg(gccProfile.name()); profiles << gccProfile; } } indent = QLatin1String(" "); } } void XcodeProbe::detectAll() { detectDeveloperPaths(); QString xcodeName = QLatin1String("xcode"); for (int iXcode = 0; iXcode < developerPaths.count(); ++iXcode) { setupDefaultToolchains(developerPaths.value(iXcode), xcodeName); xcodeName = QString::fromLatin1("xcode%1").arg(iXcode + 2); } } } // end anonymous namespace void xcodeProbe(qbs::Settings *settings, QList &profiles) { XcodeProbe probe(settings, profiles); probe.detectAll(); } qbs-src-1.4.5/src/app/qbs-setup-toolchains/xcodeprobe.h000066400000000000000000000033061266132464200230410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef XCODEPROBE_H #define XCODEPROBE_H #include namespace qbs { class Profile; class Settings; } void xcodeProbe(qbs::Settings *settings, QList &profiles); #endif // XCODEPROBE_H qbs-src-1.4.5/src/app/qbs/000077500000000000000000000000001266132464200152355ustar00rootroot00000000000000qbs-src-1.4.5/src/app/qbs/application.cpp000066400000000000000000000045641266132464200202550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "application.h" #include "commandlinefrontend.h" #include "ctrlchandler.h" namespace qbs { Application::Application(int &argc, char **argv) : QCoreApplication(argc, argv), m_clFrontend(0), m_canceled(false) { setApplicationName(QLatin1String("qbs")); setOrganizationName(QLatin1String("QtProject")); setOrganizationDomain(QLatin1String("qt-project.org")); } Application *Application::instance() { return qobject_cast(QCoreApplication::instance()); } void Application::setCommandLineFrontend(CommandLineFrontend *clFrontend) { installCtrlCHandler(); m_clFrontend = clFrontend; } /** * Interrupt the application. This is directly called from a signal handler. */ void Application::userInterrupt() { if (m_canceled) return; Q_ASSERT(m_clFrontend); m_canceled = true; m_clFrontend->cancel(); } } // namespace qbs qbs-src-1.4.5/src/app/qbs/application.h000066400000000000000000000037201266132464200177130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef APPLICATION_H #define APPLICATION_H #include namespace qbs { class CommandLineFrontend; class Application : public QCoreApplication { Q_OBJECT public: Application(int &argc, char **argv); static Application *instance(); void setCommandLineFrontend(CommandLineFrontend *clFrontend); void userInterrupt(); private: CommandLineFrontend *m_clFrontend; bool m_canceled; }; } // namespace qbs #endif // APPLICATION_H qbs-src-1.4.5/src/app/qbs/commandlinefrontend.cpp000066400000000000000000000600341266132464200217720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "commandlinefrontend.h" #include "application.h" #include "consoleprogressobserver.h" #include "status.h" #include "parser/commandlineoption.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { using namespace Internal; CommandLineFrontend::CommandLineFrontend(const CommandLineParser &parser, Settings *settings, QObject *parent) : QObject(parent) , m_parser(parser) , m_settings(settings) , m_observer(0) , m_cancelStatus(CancelStatusNone) , m_cancelTimer(new QTimer(this)) { } CommandLineFrontend::~CommandLineFrontend() { m_cancelTimer->stop(); } // Called from interrupt handler. Don't do anything non-trivial here. void CommandLineFrontend::cancel() { m_cancelStatus = CancelStatusRequested; } void CommandLineFrontend::checkCancelStatus() { switch (m_cancelStatus) { case CancelStatusNone: break; case CancelStatusRequested: m_cancelStatus = CancelStatusCanceling; m_cancelTimer->stop(); if (m_resolveJobs.isEmpty() && m_buildJobs.isEmpty()) std::exit(EXIT_FAILURE); foreach (AbstractJob * const job, m_resolveJobs) job->cancel(); foreach (AbstractJob * const job, m_buildJobs) job->cancel(); break; case CancelStatusCanceling: QBS_ASSERT(false, return); break; } } void CommandLineFrontend::start() { try { switch (m_parser.command()) { case RunCommandType: case ShellCommandType: if (m_parser.products().count() > 1) { throw ErrorInfo(Tr::tr("Invalid use of command '%1': Cannot use more than one " "product.\nUsage: %2") .arg(m_parser.commandName(), m_parser.commandDescription())); } // Fall-through intended. case StatusCommandType: case InstallCommandType: case DumpNodesTreeCommandType: if (m_parser.buildConfigurations().count() > 1) { QString error = Tr::tr("Invalid use of command '%1': There can be only one " "build configuration.\n").arg(m_parser.commandName()); error += Tr::tr("Usage: %1").arg(m_parser.commandDescription()); throw ErrorInfo(error); } break; default: break; } if (m_parser.showVersion()) { puts(QBS_VERSION); qApp->exit(EXIT_SUCCESS); return; } if (m_parser.showProgress()) m_observer = new ConsoleProgressObserver; SetupProjectParameters params; params.setProjectFilePath(m_parser.projectFilePath()); params.setIgnoreDifferentProjectFilePath(m_parser.force()); params.setDryRun(m_parser.dryRun()); params.setLogElapsedTime(m_parser.logTime()); params.setSettingsDirectory(m_settings->baseDirectoy()); if (!m_parser.buildBeforeInstalling() || m_parser.command() == DumpNodesTreeCommandType) params.setRestoreBehavior(SetupProjectParameters::RestoreOnly); foreach (const QVariantMap &buildConfig, m_parser.buildConfigurations()) { QVariantMap userConfig = buildConfig; const QString buildVariantKey = QLatin1String("qbs.buildVariant"); const QString profileKey = QLatin1String("qbs.profile"); const QString installRootKey = QLatin1String("qbs.installRoot"); QString installRoot = userConfig.value(installRootKey).toString(); if (!installRoot.isEmpty() && QFileInfo(installRoot).isRelative()) { installRoot.prepend(QLatin1Char('/')).prepend(QDir::currentPath()); userConfig.insert(installRootKey, installRoot); } const QString buildVariant = userConfig.take(buildVariantKey).toString(); QString profileName = userConfig.take(profileKey).toString(); if (profileName.isEmpty()) profileName = m_settings->defaultProfile(); if (profileName.isEmpty()) { ErrorInfo error(Tr::tr("No profile specified and no default profile exists.")); error.append(Tr::tr("To set a default profile, run " "'qbs config defaultProfile '.")); throw error; } const Preferences prefs(m_settings); params.setSearchPaths(prefs.searchPaths(QDir::cleanPath(QCoreApplication::applicationDirPath() + QLatin1String("/" QBS_RELATIVE_SEARCH_PATH)))); params.setPluginPaths(prefs.pluginPaths(QDir::cleanPath(QCoreApplication::applicationDirPath() + QLatin1String("/" QBS_RELATIVE_PLUGINS_PATH)))); params.setLibexecPath(QDir::cleanPath(QCoreApplication::applicationDirPath() + QLatin1String("/" QBS_RELATIVE_LIBEXEC_PATH))); params.setTopLevelProfile(profileName); params.setBuildVariant(buildVariant); params.setBuildRoot(buildDirectory(profileName)); params.setOverriddenValues(userConfig); SetupProjectJob * const job = Project().setupProject(params, ConsoleLogger::instance().logSink(), this); connectJob(job); m_resolveJobs << job; } /* * Progress reporting on the terminal gets a bit tricky when resolving several projects * concurrently, since we cannot show multiple progress bars at the same time. Instead, * we just set the total effort to the number of projects and increase the progress * every time one of them finishes, ingoring the progress reports from the jobs themselves. * (Yes, that does mean it will take disproportionately long for the first progress * notification to arrive.) */ if (m_parser.showProgress() && resolvingMultipleProjects()) m_observer->initialize(tr("Setting up projects"), m_resolveJobs.count()); // Check every two seconds whether we received a cancel request. This value has been // experimentally found to be acceptable. // Note that this polling approach is not problematic here, since we are doing work anyway, // so there's no danger of waking up the processor for no reason. connect(m_cancelTimer, SIGNAL(timeout()), SLOT(checkCancelStatus())); m_cancelTimer->start(2000); } catch (const ErrorInfo &error) { qbsError() << error.toString(); if (m_buildJobs.isEmpty() && m_resolveJobs.isEmpty()) { qApp->exit(EXIT_FAILURE); } else { cancel(); checkCancelStatus(); } } } void CommandLineFrontend::handleCommandDescriptionReport(const QString &highlight, const QString &message) { qbsInfo() << MessageTag(highlight) << message; } void CommandLineFrontend::handleJobFinished(bool success, AbstractJob *job) { try { job->deleteLater(); if (!success) { qbsError() << job->error().toString(); m_resolveJobs.removeOne(job); m_buildJobs.removeOne(job); if (m_resolveJobs.isEmpty() && m_buildJobs.isEmpty()) { qApp->exit(EXIT_FAILURE); return; } cancel(); } else if (SetupProjectJob * const setupJob = qobject_cast(job)) { m_resolveJobs.removeOne(job); m_projects << setupJob->project(); if (m_observer && resolvingMultipleProjects()) m_observer->incrementProgressValue(); if (m_resolveJobs.isEmpty()) handleProjectsResolved(); } else if (qobject_cast(job)) { if (m_parser.command() == RunCommandType) qApp->exit(runTarget()); else qApp->quit(); } else { // Build or clean. m_buildJobs.removeOne(job); if (m_buildJobs.isEmpty()) { switch (m_parser.command()) { case RunCommandType: case InstallCommandType: install(); break; case GenerateCommandType: generate(); // fall through case BuildCommandType: case CleanCommandType: qApp->quit(); break; default: Q_ASSERT_X(false, Q_FUNC_INFO, "Missing case in switch statement"); } } } } catch (const ErrorInfo &error) { qbsError() << error.toString(); qApp->exit(EXIT_FAILURE); } } void CommandLineFrontend::handleNewTaskStarted(const QString &description, int totalEffort) { // If the user does not want a progress bar, we just print the current activity. if (!m_parser.showProgress()) { if (!m_parser.logTime()) qbsInfo() << description; return; } if (isBuilding()) { m_totalBuildEffort += totalEffort; if (++m_buildEffortsRetrieved == m_buildEffortsNeeded) { m_observer->initialize(tr("Building"), m_totalBuildEffort); if (m_currentBuildEffort > 0) m_observer->setProgressValue(m_currentBuildEffort); } } else if (!resolvingMultipleProjects()) { m_observer->initialize(description, totalEffort); } } void CommandLineFrontend::handleTotalEffortChanged(int totalEffort) { // Can only happen when resolving. if (m_parser.showProgress() && !isBuilding() && !resolvingMultipleProjects()) m_observer->setMaximum(totalEffort); } void CommandLineFrontend::handleTaskProgress(int value, AbstractJob *job) { if (isBuilding()) { int ¤tJobEffort = m_buildEfforts[job]; m_currentBuildEffort += value - currentJobEffort; currentJobEffort = value; if (m_buildEffortsRetrieved == m_buildEffortsNeeded) m_observer->setProgressValue(m_currentBuildEffort); } else if (!resolvingMultipleProjects()) { m_observer->setProgressValue(value); } } void CommandLineFrontend::handleProcessResultReport(const qbs::ProcessResult &result) { bool hasOutput = !result.stdOut().isEmpty() || !result.stdErr().isEmpty(); if (!hasOutput && result.success()) return; (result.success() ? qbsInfo() : qbsError()) << shellQuote(QDir::toNativeSeparators(result.executableFilePath()), result.arguments()) << (hasOutput ? QString::fromLatin1("\n") : QString()) << (result.stdOut().isEmpty() ? QString() : result.stdOut().join(QLatin1Char('\n'))) << (result.stdErr().isEmpty() ? QString() : result.stdErr().join(QLatin1Char('\n'))); } bool CommandLineFrontend::resolvingMultipleProjects() const { return isResolving() && m_resolveJobs.count() + m_projects.count() > 1; } bool CommandLineFrontend::isResolving() const { return !m_resolveJobs.isEmpty(); } bool CommandLineFrontend::isBuilding() const { return !m_buildJobs.isEmpty(); } CommandLineFrontend::ProductMap CommandLineFrontend::productsToUse() const { ProductMap products; QStringList productNames; const bool useAll = m_parser.products().isEmpty(); foreach (const Project &project, m_projects) { QList &productList = products[project]; const ProjectData projectData = project.projectData(); foreach (const ProductData &product, projectData.allProducts()) { if (useAll || m_parser.products().contains(product.name())) { productList << product; productNames << product.name(); } } } foreach (const QString &productName, m_parser.products()) { if (!productNames.contains(productName)) throw ErrorInfo(Tr::tr("No such product '%1'.").arg(productName)); } return products; } void CommandLineFrontend::handleProjectsResolved() { if (m_cancelStatus != CancelStatusNone) throw ErrorInfo(Tr::tr("Execution canceled.")); switch (m_parser.command()) { case ResolveCommandType: qApp->quit(); break; case CleanCommandType: makeClean(); break; case ShellCommandType: qApp->exit(runShell()); break; case StatusCommandType: qApp->exit(printStatus(m_projects.first().projectData())); break; case BuildCommandType: case GenerateCommandType: build(); break; case InstallCommandType: case RunCommandType: if (m_parser.buildBeforeInstalling()) build(); else install(); break; case UpdateTimestampsCommandType: updateTimestamps(); qApp->quit(); break; case DumpNodesTreeCommandType: dumpNodesTree(); qApp->quit(); break; case HelpCommandType: Q_ASSERT_X(false, Q_FUNC_INFO, "Impossible."); } } void CommandLineFrontend::makeClean() { if (m_parser.products().isEmpty()) { foreach (const Project &project, m_projects) { m_buildJobs << project.cleanAllProducts(m_parser.cleanOptions(project.profile()), this); } } else { const ProductMap &products = productsToUse(); for (ProductMap::ConstIterator it = products.begin(); it != products.end(); ++it) { m_buildJobs << it.key().cleanSomeProducts(it.value(), m_parser.cleanOptions(it.key().profile()), this); } } connectBuildJobs(); } int CommandLineFrontend::runShell() { const ProductData productToRun = getTheOneRunnableProduct(); RunEnvironment runEnvironment = m_projects.first().getRunEnvironment(productToRun, m_parser.installOptions(m_projects.first().profile()), QProcessEnvironment::systemEnvironment(), m_settings); return runEnvironment.runShell(); } BuildOptions CommandLineFrontend::buildOptions(const Project &project) const { BuildOptions options = m_parser.buildOptions(m_projects.first().profile()); if (options.maxJobCount() <= 0) { const QString profileName = project.profile(); QBS_CHECK(!profileName.isEmpty()); options.setMaxJobCount(Preferences(m_settings, profileName).jobs()); } return options; } QString CommandLineFrontend::buildDirectory(const QString &profileName) const { QString buildDir = m_parser.projectBuildDirectory(); if (buildDir.isEmpty()) { buildDir = Preferences(m_settings, profileName).defaultBuildDirectory(); if (buildDir.isEmpty()) { qbsDebug() << "No project build directory given; using current directory."; buildDir = QDir::currentPath(); } else { qbsDebug() << "No project build directory given; using directory from preferences."; } } QString projectName(QFileInfo(m_parser.projectFilePath()).baseName()); buildDir.replace(BuildDirectoryOption::magicProjectString(), projectName); QString projectDir(QFileInfo(m_parser.projectFilePath()).path()); buildDir.replace(BuildDirectoryOption::magicProjectDirString(), projectDir); if (!QFileInfo(buildDir).isAbsolute()) buildDir = QDir::currentPath() + QLatin1Char('/') + buildDir; buildDir = QDir::cleanPath(buildDir); return buildDir; } void CommandLineFrontend::build() { if (m_parser.products().isEmpty()) { const Project::ProductSelection productSelection = m_parser.withNonDefaultProducts() ? Project::ProductSelectionWithNonDefault : Project::ProductSelectionDefaultOnly; foreach (const Project &project, m_projects) m_buildJobs << project.buildAllProducts(buildOptions(project), productSelection, this); } else { const ProductMap &products = productsToUse(); for (ProductMap::ConstIterator it = products.begin(); it != products.end(); ++it) m_buildJobs << it.key().buildSomeProducts(it.value(), buildOptions(it.key()), this); } connectBuildJobs(); /* * Progress reporting for the build jobs works as follows: We know that for every job, * the newTaskStarted() signal is emitted exactly once (unless there's an error). So we add up * the respective total efforts as they come in. Once all jobs have reported their total * efforts, we can start the overall progress report. */ m_buildEffortsNeeded = m_buildJobs.count(); m_buildEffortsRetrieved = 0; m_totalBuildEffort = 0; m_currentBuildEffort = 0; } void CommandLineFrontend::generate() { const QString generatorName = m_parser.generateOptions().generatorName(); QSharedPointer generator(ProjectGeneratorManager::findGenerator(generatorName)); if (!generator) { const QString generatorNames = ProjectGeneratorManager::loadedGeneratorNames() .join(QLatin1String("\n\t")); if (generatorName.isEmpty()) { throw ErrorInfo(Tr::tr("No generator specified. Available generators:\n\t%1") .arg(generatorNames)); } throw ErrorInfo(Tr::tr("No generator named '%1'. Available generators:\n\t%2") .arg(generatorName) .arg(generatorNames)); } generator->clearProjects(); generator->addProjects(m_projects); generator->generate(m_parser.installOptions(m_projects.first().profile())); } int CommandLineFrontend::runTarget() { const ProductData productToRun = getTheOneRunnableProduct(); const QString executableFilePath = m_projects.first().targetExecutable(productToRun, m_parser.installOptions(m_projects.first().profile())); if (executableFilePath.isEmpty()) { throw ErrorInfo(Tr::tr("Cannot run: Product '%1' is not an application.") .arg(productToRun.name())); } RunEnvironment runEnvironment = m_projects.first().getRunEnvironment(productToRun, m_parser.installOptions(m_projects.first().profile()), QProcessEnvironment::systemEnvironment(), m_settings); return runEnvironment.runTarget(executableFilePath, m_parser.runArgs()); } void CommandLineFrontend::updateTimestamps() { const ProductMap &products = productsToUse(); for (ProductMap::ConstIterator it = products.constBegin(); it != products.constEnd(); ++it) { Project p = it.key(); p.updateTimestamps(it.value()); } } void CommandLineFrontend::dumpNodesTree() { QFile stdOut; stdOut.open(stdout, QIODevice::WriteOnly); const ErrorInfo error = m_projects.first().dumpNodesTree(stdOut, productsToUse() .value(m_projects.first())); if (error.hasError()) throw error; } void CommandLineFrontend::connectBuildJobs() { foreach (AbstractJob * const job, m_buildJobs) connectBuildJob(job); } void CommandLineFrontend::connectBuildJob(AbstractJob *job) { connectJob(job); BuildJob *bjob = qobject_cast(job); if (!bjob) return; connect(bjob, SIGNAL(reportCommandDescription(QString,QString)), this, SLOT(handleCommandDescriptionReport(QString,QString))); connect(bjob, SIGNAL(reportProcessResult(qbs::ProcessResult)), this, SLOT(handleProcessResultReport(qbs::ProcessResult))); } void CommandLineFrontend::connectJob(AbstractJob *job) { connect(job, SIGNAL(finished(bool,qbs::AbstractJob*)), SLOT(handleJobFinished(bool,qbs::AbstractJob*))); connect(job, SIGNAL(taskStarted(QString,int,qbs::AbstractJob*)), SLOT(handleNewTaskStarted(QString,int))); connect(job, SIGNAL(totalEffortChanged(int,qbs::AbstractJob*)), SLOT(handleTotalEffortChanged(int))); if (m_parser.showProgress()) { connect(job, SIGNAL(taskProgress(int,qbs::AbstractJob*)), SLOT(handleTaskProgress(int,qbs::AbstractJob*))); } } ProductData CommandLineFrontend::getTheOneRunnableProduct() { QBS_CHECK(m_projects.count() == 1); // Has been checked earlier. if (m_parser.products().count() == 1) { foreach (const ProductData &p, m_projects.first().projectData().allProducts()) { if (p.name() == m_parser.products().first()) return p; } QBS_CHECK(false); } QBS_CHECK(m_parser.products().count() == 0); QList runnableProducts; foreach (const ProductData &p, m_projects.first().projectData().allProducts()) { if (p.isRunnable()) runnableProducts << p; } if (runnableProducts.count() == 1) return runnableProducts.first(); if (runnableProducts.isEmpty()) { throw ErrorInfo(Tr::tr("Cannot execute command '%1': Project has no runnable product.") .arg(m_parser.commandName())); } ErrorInfo error(Tr::tr("Ambiguous use of command '%1': No product given, but project " "has more than one runnable product.").arg(m_parser.commandName())); error.append(Tr::tr("Use the '--products' option with one of the following products:")); foreach (const ProductData &p, runnableProducts) { QString productRepr = QLatin1String("\t") + p.name(); if (p.profile() != m_projects.first().profile()) { productRepr.append(QLatin1String(" [")).append(p.profile()) .append(QLatin1Char(']')); } error.append(productRepr); } throw error; } void CommandLineFrontend::install() { Q_ASSERT(m_projects.count() == 1); const Project project = m_projects.first(); InstallJob *installJob; if (m_parser.products().isEmpty()) { const Project::ProductSelection productSelection = m_parser.withNonDefaultProducts() ? Project::ProductSelectionWithNonDefault : Project::ProductSelectionDefaultOnly; installJob = project.installAllProducts(m_parser.installOptions(project.profile()), productSelection); } else { const Project project = m_projects.first(); const ProductMap products = productsToUse(); installJob = project.installSomeProducts(products.value(project), m_parser.installOptions(project.profile())); } connectJob(installJob); } } // namespace qbs qbs-src-1.4.5/src/app/qbs/commandlinefrontend.h000066400000000000000000000075561266132464200214510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef COMMANDLINEFRONTEND_H #define COMMANDLINEFRONTEND_H #include "parser/commandlineparser.h" #include #include #include #include #include QT_BEGIN_NAMESPACE class QTimer; QT_END_NAMESPACE namespace qbs { class AbstractJob; class ConsoleProgressObserver; class ErrorInfo; class ProcessResult; class Settings; class CommandLineFrontend : public QObject { Q_OBJECT public: explicit CommandLineFrontend(const CommandLineParser &parser, Settings *settings, QObject *parent = 0); ~CommandLineFrontend(); void cancel(); private slots: void start(); void handleCommandDescriptionReport(const QString &highlight, const QString &message); void handleJobFinished(bool success, qbs::AbstractJob *job); void handleNewTaskStarted(const QString &description, int totalEffort); void handleTotalEffortChanged(int totalEffort); void handleTaskProgress(int value, qbs::AbstractJob *job); void handleProcessResultReport(const qbs::ProcessResult &result); void checkCancelStatus(); private: typedef QHash > ProductMap; ProductMap productsToUse() const; bool resolvingMultipleProjects() const; bool isResolving() const; bool isBuilding() const; void handleProjectsResolved(); void makeClean(); int runShell(); void build(); void generate(); int runTarget(); void updateTimestamps(); void dumpNodesTree(); void connectBuildJobs(); void connectBuildJob(AbstractJob *job); void connectJob(AbstractJob *job); ProductData getTheOneRunnableProduct(); void install(); BuildOptions buildOptions(const Project &project) const; QString buildDirectory(const QString &profileName) const; const CommandLineParser &m_parser; Settings * const m_settings; QList m_resolveJobs; QList m_buildJobs; QList m_projects; ConsoleProgressObserver *m_observer; enum CancelStatus { CancelStatusNone, CancelStatusRequested, CancelStatusCanceling }; CancelStatus m_cancelStatus; QTimer * const m_cancelTimer; int m_buildEffortsNeeded; int m_buildEffortsRetrieved; int m_totalBuildEffort; int m_currentBuildEffort; QHash m_buildEfforts; }; } // namespace qbs #endif // COMMANDLINEFRONTEND_H qbs-src-1.4.5/src/app/qbs/consoleprogressobserver.cpp000066400000000000000000000071411266132464200227430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "consoleprogressobserver.h" #include #include #include namespace qbs { void ConsoleProgressObserver::initialize(const QString &task, int max) { m_maximum = max; m_value = 0; m_percentage = 0; m_hashesPrinted = 0; std::cout << task.toLocal8Bit().constData() << ": 0%" << std::flush; setMaximum(max); } void ConsoleProgressObserver::setMaximum(int maximum) { m_maximum = maximum; if (maximum == 0) { m_percentage = 100; updateProgressBarIfNecessary(); writePercentageString(); std::cout << std::endl; } } void ConsoleProgressObserver::setProgressValue(int value) { if (value > m_maximum || value <= m_value) return; // TODO: Should be an assertion, but the executor currently breaks it. m_value = value; const int newPercentage = (100 * m_value) / m_maximum; if (newPercentage == m_percentage) return; eraseCurrentPercentageString(); m_percentage = newPercentage; updateProgressBarIfNecessary(); writePercentageString(); if (m_value == m_maximum) std::cout << std::endl; else std::cout << std::flush; } void ConsoleProgressObserver::eraseCurrentPercentageString() { const int charsToErase = m_percentage == 0 ? 2 : m_percentage < 10 ? 3 : 4; // (1) Move cursor before the old percentage string. // (2) Erase current line content to the right of the cursor. std::cout << QString::fromLocal8Bit("\x1b[%1D").arg(charsToErase).toLocal8Bit().constData(); std::cout << "\x1b[K"; } void ConsoleProgressObserver::updateProgressBarIfNecessary() { static const int TotalHashCount = 50; // Should fit on most terminals without a line break. const int hashesNeeded = (m_percentage * TotalHashCount) / 100; if (m_hashesPrinted < hashesNeeded) { std::cout << QByteArray(hashesNeeded - m_hashesPrinted, '#').constData(); m_hashesPrinted = hashesNeeded; } } void ConsoleProgressObserver::writePercentageString() { std::cout << QString::fromLocal8Bit(" %1%").arg(m_percentage).toLocal8Bit().constData(); } } // namespace qbs qbs-src-1.4.5/src/app/qbs/consoleprogressobserver.h000066400000000000000000000042121266132464200224040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef CONSOLEPROGRESSOBSERVER_H #define CONSOLEPROGRESSOBSERVER_H #include QT_BEGIN_NAMESPACE class QString; QT_END_NAMESPACE namespace qbs { class ConsoleProgressObserver { public: void initialize(const QString &task, int max); void setMaximum(int maximum); void setProgressValue(int value); void incrementProgressValue() { setProgressValue(m_value + 1); } private: void eraseCurrentPercentageString(); void updateProgressBarIfNecessary(); void writePercentageString(); int m_maximum; int m_value; int m_percentage; int m_hashesPrinted; }; } // namespace qbs #endif // CONSOLEPROGRESSOBSERVER_H qbs-src-1.4.5/src/app/qbs/ctrlchandler.cpp000066400000000000000000000041521266132464200204100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "application.h" static void cancel() { qbs::Application * const app = qbs::Application::instance(); if (app) app->userInterrupt(); } #if defined(Q_OS_WIN) && defined(Q_CC_MSVC) #include static BOOL WINAPI consoleCtrlHandlerRoutine(__in DWORD dwCtrlType) { Q_UNUSED(dwCtrlType); cancel(); return TRUE; } void installCtrlCHandler() { SetConsoleCtrlHandler(&consoleCtrlHandlerRoutine, TRUE); } #else #include static void sigIntHandler(int sig) { Q_UNUSED(sig); cancel(); } void installCtrlCHandler() { signal(SIGINT, sigIntHandler); } #endif qbs-src-1.4.5/src/app/qbs/ctrlchandler.h000066400000000000000000000031331266132464200200530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef CTRLCHANDLER_H #define CTRLCHANDLER_H void installCtrlCHandler(); #endif // CTRLCHANDLER_H qbs-src-1.4.5/src/app/qbs/main.cpp000066400000000000000000000060061266132464200166670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "application.h" #include "commandlinefrontend.h" #include "qbstool.h" #include "parser/commandlineparser.h" #include "../shared/logging/consolelogger.h" #include #include #include using namespace qbs; static bool tryToRunTool(const QStringList &arguments, int &exitCode) { if (arguments.isEmpty()) return false; QStringList toolArgs = arguments; const QString toolName = toolArgs.takeFirst(); if (toolName.startsWith(QLatin1Char('-'))) return false; return QbsTool::tryToRunTool(toolName, toolArgs, &exitCode); } int main(int argc, char *argv[]) { ConsoleLogger::instance(); try { Application app(argc, argv); QStringList arguments = app.arguments(); arguments.removeFirst(); int toolExitCode = 0; if (tryToRunTool(arguments, toolExitCode)) return toolExitCode; CommandLineParser parser; if (!parser.parseCommandLine(arguments)) return EXIT_FAILURE; if (parser.command() == HelpCommandType) { parser.printHelp(); return 0; } Settings settings(parser.settingsDir()); ConsoleLogger::instance().setSettings(&settings); CommandLineFrontend clFrontend(parser, &settings); app.setCommandLineFrontend(&clFrontend); QTimer::singleShot(0, &clFrontend, SLOT(start())); return app.exec(); } catch (const ErrorInfo &error) { qbsError() << error.toString(); return EXIT_FAILURE; } } qbs-src-1.4.5/src/app/qbs/parser/000077500000000000000000000000001266132464200165315ustar00rootroot00000000000000qbs-src-1.4.5/src/app/qbs/parser/command.cpp000066400000000000000000000445471266132464200206710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "command.h" #include "commandlineoption.h" #include "commandlineoptionpool.h" #include #include #include #include #include namespace qbs { using namespace Internal; Command::~Command() { } void Command::parse(QStringList &input) { parseOptions(input); parseMore(input); if (!input.isEmpty()) { throw ErrorInfo(Tr::tr("Invalid use of command '%1': Extraneous input '%2'.\nUsage: %3") .arg(representation(), input.join(QLatin1Char(' ')), longDescription())); } } void Command::addAllToAdditionalArguments(QStringList &input) { while (!input.isEmpty()) addOneToAdditionalArguments(input.takeFirst()); } // TODO: Stricter checking for build variants and properties. void Command::addOneToAdditionalArguments(const QString &argument) { if (argument.startsWith(QLatin1Char('-'))) { throw ErrorInfo(Tr::tr("Invalid use of command '%1': Encountered option '%2', expected a " "build variant or property.\nUsage: %3") .arg(representation(), argument, longDescription())); } m_additionalArguments << argument; } QList Command::actualSupportedOptions() const { QList options = supportedOptions(); if (!HostOsInfo::isAnyUnixHost()) options.removeOne(CommandLineOption::ShowProgressOptionType); if (type() != HelpCommandType) options << CommandLineOption::SettingsDirOptionType; // Valid for almost all commands. return options; } void Command::parseOptions(QStringList &input) { QSet usedOptions; while (!input.isEmpty()) { const QString optionString = input.first(); if (!optionString.startsWith(QLatin1Char('-'))) break; if (optionString == QLatin1String("--")) break; input.removeFirst(); if (optionString.count() == 1) { throw ErrorInfo(Tr::tr("Invalid use of command '%1': Empty options are not allowed.\n" "Usage: %2").arg(representation(), longDescription())); } // Split up grouped short options. if (optionString.at(1) != QLatin1Char('-') && optionString.count() > 2) { for (int i = optionString.count(); --i > 0;) input.prepend(QLatin1Char('-') + optionString.at(i)); continue; } bool matchFound = false; foreach (const CommandLineOption::Type optionType, actualSupportedOptions()) { CommandLineOption * const option = optionPool().getOption(optionType); if (option->shortRepresentation() != optionString && option->longRepresentation() != optionString) { continue; } if (usedOptions.contains(option) && !option->canAppearMoreThanOnce()) { throw ErrorInfo(Tr::tr("Invalid use of command '%1': Option '%2' cannot appear " "more than once.\nUsage: %3") .arg(representation(), optionString, longDescription())); } option->parse(type(), optionString, input); usedOptions << option; matchFound = true; break; } if (!matchFound) { throw ErrorInfo(Tr::tr("Invalid use of command '%1': Unknown option '%2'.\nUsage: %3") .arg(representation(), optionString, longDescription())); } } } QString Command::supportedOptionsDescription() const { // Sorting the options by name is nicer for the user. QMap optionMap; foreach (const CommandLineOption::Type opType, actualSupportedOptions()) { const CommandLineOption * const option = optionPool().getOption(opType); optionMap.insert(option->longRepresentation(), option); } QString s = Tr::tr("The possible options are:\n"); foreach (const CommandLineOption *option, optionMap) s += option->description(type()); return s; } void Command::parseMore(QStringList &input) { addAllToAdditionalArguments(input); } QString ResolveCommand::shortDescription() const { return Tr::tr("Resolve a project without building it."); } QString ResolveCommand::longDescription() const { QString description = Tr::tr("qbs %1 [options] [[variant] [property:value] ...] ...\n") .arg(representation()); description += Tr::tr("Resolves a project in one or more configuration(s).\n"); return description += supportedOptionsDescription(); } QString ResolveCommand::representation() const { return QLatin1String("resolve"); } static QList resolveOptions() { return QList() << CommandLineOption::FileOptionType << CommandLineOption::BuildDirectoryOptionType << CommandLineOption::LogLevelOptionType << CommandLineOption::VerboseOptionType << CommandLineOption::QuietOptionType << CommandLineOption::ShowProgressOptionType << CommandLineOption::JobsOptionType << CommandLineOption::DryRunOptionType << CommandLineOption::LogTimeOptionType << CommandLineOption::ForceOptionType; } QList ResolveCommand::supportedOptions() const { return resolveOptions(); } QString GenerateCommand::shortDescription() const { return Tr::tr("Generate project files for another build tool."); } QString GenerateCommand::longDescription() const { QString description = Tr::tr("qbs %1 [options] [[variant] [property:value] ...] ...\n") .arg(representation()); description += Tr::tr("Generates files to build the project using another build tool.\n"); return description += supportedOptionsDescription(); } QString GenerateCommand::representation() const { return QLatin1String("generate"); } QList GenerateCommand::supportedOptions() const { return QList() << CommandLineOption::FileOptionType << CommandLineOption::BuildDirectoryOptionType << CommandLineOption::LogLevelOptionType << CommandLineOption::VerboseOptionType << CommandLineOption::QuietOptionType << CommandLineOption::ShowProgressOptionType << CommandLineOption::LogTimeOptionType << CommandLineOption::GeneratorOptionType; } QString BuildCommand::shortDescription() const { return Tr::tr("Build (parts of) a project. This is the default command."); } QString BuildCommand::longDescription() const { QString description = Tr::tr("qbs %1 [options] [[variant] [property:value] ...] ...\n") .arg(representation()); description += Tr::tr("Builds a project in one or more configuration(s).\n"); return description += supportedOptionsDescription(); } static QString buildCommandRepresentation() { return QLatin1String("build"); } QString BuildCommand::representation() const { return buildCommandRepresentation(); } static QList buildOptions() { QList options = resolveOptions(); return options << CommandLineOption::KeepGoingOptionType << CommandLineOption::ProductsOptionType << CommandLineOption::ChangedFilesOptionType << CommandLineOption::ForceTimestampCheckOptionType << CommandLineOption::BuildNonDefaultOptionType << CommandLineOption::VersionOptionType << CommandLineOption::CommandEchoModeOptionType << CommandLineOption::NoInstallOptionType << CommandLineOption::RemoveFirstOptionType; } QList BuildCommand::supportedOptions() const { return buildOptions(); } QString CleanCommand::shortDescription() const { return Tr::tr("Remove the files generated during a build."); } QString CleanCommand::longDescription() const { QString description = Tr::tr("qbs %1 [options] [[variant] [property:value] ...] ...\n") .arg(representation()); description += Tr::tr("Removes build artifacts for the given project and configuration(s).\n"); return description += supportedOptionsDescription(); } QString CleanCommand::representation() const { return QLatin1String("clean"); } QList CleanCommand::supportedOptions() const { QList options = buildOptions(); options.removeOne(CommandLineOption::ChangedFilesOptionType); options.removeOne(CommandLineOption::JobsOptionType); options.removeOne(CommandLineOption::BuildNonDefaultOptionType); options.removeOne(CommandLineOption::CommandEchoModeOptionType); return options << CommandLineOption::AllArtifactsOptionType; } QString InstallCommand::shortDescription() const { return Tr::tr("Install (parts of) a project."); } QString InstallCommand::longDescription() const { QString description = Tr::tr("qbs %1 [options] [[variant] [property:value] ...]\n") .arg(representation()); description += Tr::tr("Install all files marked as installable " "to their respective destinations.\n" "The project is built first, if necessary, unless the '%1' option " "is given.\n").arg(optionPool().noBuildOption()->longRepresentation()); return description += supportedOptionsDescription(); } QString InstallCommand::representation() const { return QLatin1String("install"); } QList installOptions() { QList options = buildOptions() << CommandLineOption::InstallRootOptionType << CommandLineOption::NoBuildOptionType; options.removeOne(CommandLineOption::NoInstallOptionType); return options; } QList InstallCommand::supportedOptions() const { return installOptions(); } QString RunCommand::shortDescription() const { return QLatin1String("Run an executable generated by building a project."); } QString RunCommand::longDescription() const { QString description = Tr::tr("qbs %1 [options] [variant] [property:value] ... " "[ -- ]\n").arg(representation()); description += Tr::tr("Run the specified product's executable with the specified arguments.\n"); description += Tr::tr("If the project has only one product, the '%1' option may be omitted.\n") .arg(optionPool().productsOption()->longRepresentation()); description += Tr::tr("The product will be built if it is not up to date; " "see the '%2' command.\n").arg(buildCommandRepresentation()); return description += supportedOptionsDescription(); } QString RunCommand::representation() const { return QLatin1String("run"); } QList RunCommand::supportedOptions() const { return installOptions(); } void RunCommand::parseMore(QStringList &input) { // Build variants and properties while (!input.isEmpty()) { const QString arg = input.takeFirst(); if (arg == QLatin1String("--")) break; addOneToAdditionalArguments(arg); } m_targetParameters = input; input.clear(); } QString ShellCommand::shortDescription() const { return Tr::tr("Open a shell with a product's environment."); } QString ShellCommand::longDescription() const { QString description = Tr::tr("qbs %1 [options] [variant] [property:value] ...\n") .arg(representation()); description += Tr::tr("Opens a shell in the same environment that a build with the given " "parameters would use.\n"); const ProductsOption * const option = optionPool().productsOption(); description += Tr::tr("The '%1' option may be omitted if and only if the project has " "exactly one product.").arg(option->longRepresentation()); return description += supportedOptionsDescription(); } QString ShellCommand::representation() const { return QLatin1String("shell"); } QList ShellCommand::supportedOptions() const { return QList() << CommandLineOption::FileOptionType << CommandLineOption::BuildDirectoryOptionType << CommandLineOption::LogLevelOptionType << CommandLineOption::VerboseOptionType << CommandLineOption::QuietOptionType << CommandLineOption::ShowProgressOptionType << CommandLineOption::ProductsOptionType; } QString StatusCommand::shortDescription() const { return Tr::tr("Show the status of files in the project directory."); } QString StatusCommand::longDescription() const { QString description = Tr::tr("qbs %1 [options] [variant] [property:value] ...\n") .arg(representation()); description += Tr::tr("Lists all the files in the project directory and shows whether " "they are known to qbs in the respective configuration.\n"); return description += supportedOptionsDescription(); } QString StatusCommand::representation() const { return QLatin1String("status"); } QList StatusCommand::supportedOptions() const { return QList() << CommandLineOption::FileOptionType << CommandLineOption::BuildDirectoryOptionType << CommandLineOption::LogLevelOptionType << CommandLineOption::VerboseOptionType << CommandLineOption::QuietOptionType << CommandLineOption::ShowProgressOptionType; } QString UpdateTimestampsCommand::shortDescription() const { return Tr::tr("Mark the build as up to date."); } QString UpdateTimestampsCommand::longDescription() const { QString description = Tr::tr("qbs %1 [options] [[variant] [property:value] ...] ...\n") .arg(representation()); description += Tr::tr("Update the timestamps of all build artifacts, causing the next " "builds of the project to do nothing if no updates to source files happen in between.\n" "This functionality is useful if you know that the current changes to source files " "are irrelevant to the build.\n" "NOTE: Doing this causes a discrepancy between the \"real world\" and the information " "in the build graph, so use with care.\n"); return description += supportedOptionsDescription(); } QString UpdateTimestampsCommand::representation() const { return QLatin1String("update-timestamps"); } QList UpdateTimestampsCommand::supportedOptions() const { return QList() << CommandLineOption::FileOptionType << CommandLineOption::BuildDirectoryOptionType << CommandLineOption::LogLevelOptionType << CommandLineOption::VerboseOptionType << CommandLineOption::QuietOptionType << CommandLineOption::ProductsOptionType; } QString DumpNodesTreeCommand::shortDescription() const { return Tr::tr("Dumps the nodes in the build graph to stdout."); } QString DumpNodesTreeCommand::longDescription() const { QString description = Tr::tr("qbs %1 [options] [[variant] [property:value] ...] ...\n") .arg(representation()); description += Tr::tr("Internal command; for debugging purposes only.\n"); return description += supportedOptionsDescription(); } QString DumpNodesTreeCommand::representation() const { return QLatin1String("dump-nodes-tree"); } QList DumpNodesTreeCommand::supportedOptions() const { return QList() << CommandLineOption::LogLevelOptionType << CommandLineOption::VerboseOptionType << CommandLineOption::QuietOptionType << CommandLineOption::FileOptionType << CommandLineOption::BuildDirectoryOptionType << CommandLineOption::ProductsOptionType; } QString HelpCommand::shortDescription() const { return Tr::tr("Show general or command-specific help."); } QString HelpCommand::longDescription() const { QString description = Tr::tr("qbs %1 []\n").arg(representation()); return description += Tr::tr("Shows either the general help or a description of " "the given command.\n"); } QString HelpCommand::representation() const { return QLatin1String("help"); } QList HelpCommand::supportedOptions() const { return QList(); } void HelpCommand::parseMore(QStringList &input) { if (input.isEmpty()) return; if (input.count() > 1) { throw ErrorInfo(Tr::tr("Invalid use of command '%1': Cannot describe more than one command.\n" "Usage: %2").arg(representation(), longDescription())); } m_command = input.takeFirst(); Q_ASSERT(input.isEmpty()); } } // namespace qbs qbs-src-1.4.5/src/app/qbs/parser/command.h000066400000000000000000000163041266132464200203240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_COMMAND_H #define QBS_COMMAND_H #include "commandlineoption.h" #include "commandtype.h" namespace qbs { class CommandLineOptionPool; class Command { public: virtual ~Command(); virtual CommandType type() const = 0; virtual QString shortDescription() const = 0; virtual QString longDescription() const = 0; virtual QString representation() const = 0; void parse(QStringList &input); QStringList additionalArguments() const { return m_additionalArguments; } protected: Command(CommandLineOptionPool &optionPool) : m_optionPool(optionPool) {} const CommandLineOptionPool &optionPool() const { return m_optionPool; } void addAllToAdditionalArguments(QStringList &input); void addOneToAdditionalArguments(const QString &argument); QString supportedOptionsDescription() const; private: QList actualSupportedOptions() const; void parseOptions(QStringList &input); virtual void parseMore(QStringList &input); virtual QList supportedOptions() const = 0; QStringList m_additionalArguments; const CommandLineOptionPool &m_optionPool; }; class ResolveCommand : public Command { public: ResolveCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const { return ResolveCommandType; } QString shortDescription() const; QString longDescription() const; QString representation() const; QList supportedOptions() const; }; class GenerateCommand : public Command { public: GenerateCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const { return GenerateCommandType; } QString shortDescription() const; QString longDescription() const; QString representation() const; QList supportedOptions() const; }; class BuildCommand : public Command { public: BuildCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const { return BuildCommandType; } QString shortDescription() const; QString longDescription() const; QString representation() const; QList supportedOptions() const; }; class CleanCommand : public Command { public: CleanCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const { return CleanCommandType; } QString shortDescription() const; QString longDescription() const; QString representation() const; QList supportedOptions() const; }; class InstallCommand : public Command { public: InstallCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const { return InstallCommandType; } QString shortDescription() const; QString longDescription() const; QString representation() const; QList supportedOptions() const; }; class RunCommand : public Command { public: RunCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} QStringList targetParameters() const { return m_targetParameters; } private: CommandType type() const { return RunCommandType; } QString shortDescription() const; QString longDescription() const; QString representation() const; QList supportedOptions() const; void parseMore(QStringList &input); QStringList m_targetParameters; }; class ShellCommand : public Command { public: ShellCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const { return ShellCommandType; } QString shortDescription() const; QString longDescription() const; QString representation() const; QList supportedOptions() const; }; // TODO: It seems wrong that a configuration has to be given here. Ideally, this command would just track *all* files regardless of conditions. Is that possible? class StatusCommand : public Command { public: StatusCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const { return StatusCommandType; } QString shortDescription() const; QString longDescription() const; QString representation() const; QList supportedOptions() const; }; class UpdateTimestampsCommand : public Command { public: UpdateTimestampsCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const { return UpdateTimestampsCommandType; } QString shortDescription() const; QString longDescription() const; QString representation() const; QList supportedOptions() const; }; class DumpNodesTreeCommand : public Command { public: DumpNodesTreeCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} private: CommandType type() const Q_DECL_OVERRIDE { return DumpNodesTreeCommandType; } QString shortDescription() const Q_DECL_OVERRIDE; QString longDescription() const Q_DECL_OVERRIDE; QString representation() const Q_DECL_OVERRIDE; QList supportedOptions() const Q_DECL_OVERRIDE; }; class HelpCommand : public Command { public: HelpCommand(CommandLineOptionPool &optionPool) : Command(optionPool) {} QString commandToDescribe() const { return m_command; } private: CommandType type() const { return HelpCommandType; } QString shortDescription() const; QString longDescription() const; QString representation() const; QList supportedOptions() const; void parseMore(QStringList &input); QString m_command; }; } // namespace qbs #endif // QBS_COMMAND_H qbs-src-1.4.5/src/app/qbs/parser/commandlineoption.cpp000066400000000000000000000471121266132464200227610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "commandlineoption.h" #include #include #include #include namespace qbs { using namespace Internal; CommandLineOption::~CommandLineOption() { } void CommandLineOption::parse(CommandType command, const QString &representation, QStringList &input) { m_command = command; doParse(representation, input); } CommandLineOption::CommandLineOption() : m_command(static_cast(-1)) { } QString CommandLineOption::getArgument(const QString &representation, QStringList &input) { if (input.isEmpty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1': Missing argument.\nUsage: %2") .arg(representation, description(command()))); } return input.takeFirst(); } QString FileOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2 \n" "\tUse as the project file.\n" "\tIf is a directory and it contains a single file ending in '.qbs',\n" "\tthat file will be used.\n" "\tIf this option is not given at all, behavior is the same as for '-f .'.\n") .arg(longRepresentation(), shortRepresentation()); } QString FileOption::shortRepresentation() const { return QLatin1String("-f"); } QString FileOption::longRepresentation() const { return QLatin1String("--file"); } void FileOption::doParse(const QString &representation, QStringList &input) { m_projectFilePath = getArgument(representation, input); } QString BuildDirectoryOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2 \n" "\tBuild in the given directory. The default value is the current directory\n" "\tunless preferences.defaultBuildDirectory is set.\n" "\tRelative paths will be interpreted relative to the current directory.\n" "\tIf the directory does not exist, it will be created. Use the following\n" "\tspecial values as placeholders:\n" "\t%3: name of the project file excluding the extension\n" "\t%4: directory containing the project file\n") .arg(longRepresentation(), shortRepresentation(), magicProjectString(), magicProjectDirString()); } QString BuildDirectoryOption::shortRepresentation() const { return QLatin1String("-d"); } QString BuildDirectoryOption::longRepresentation() const { return QLatin1String("--build-directory"); } QString BuildDirectoryOption::magicProjectString() { return QLatin1String("@project"); } QString BuildDirectoryOption::magicProjectDirString() { return QLatin1String("@path"); } void BuildDirectoryOption::doParse(const QString &representation, QStringList &input) { m_projectBuildDirectory = getArgument(representation, input); } QString GeneratorOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2 \n" "\tUse the given build system generator.\n") .arg(longRepresentation(), shortRepresentation()); } QString GeneratorOption::shortRepresentation() const { return QLatin1String("-g"); } QString GeneratorOption::longRepresentation() const { return QLatin1String("--generator"); } void GeneratorOption::doParse(const QString &representation, QStringList &input) { m_generatorName = getArgument(representation, input); if (m_generatorName.isEmpty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1': No generator given.\nUsage: %2") .arg(representation, description(command()))); } } static QString loglevelLongRepresentation() { return QLatin1String("--log-level"); } QString VerboseOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2\n" "\tBe more verbose. Increases the log level by one.\n" "\tThis option can be given more than once.\n" "\tExcessive occurrences have no effect.\n" "\tIf option '%3' appears anywhere on the command line in addition\n" "\tto this option, its value is taken as the base which to increase.\n") .arg(longRepresentation(), shortRepresentation(), loglevelLongRepresentation()); } QString VerboseOption::shortRepresentation() const { return QLatin1String("-v"); } QString VerboseOption::longRepresentation() const { return QLatin1String("--more-verbose"); } QString QuietOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2\n" "\tBe more quiet. Decreases the log level by one.\n" "\tThis option can be given more than once.\n" "\tExcessive occurrences have no effect.\n" "\tIf option '%3' appears anywhere on the command line in addition\n" "\tto this option, its value is taken as the base which to decrease.\n") .arg(longRepresentation(), shortRepresentation(), loglevelLongRepresentation()); } QString QuietOption::shortRepresentation() const { return QLatin1String("-q"); } QString QuietOption::longRepresentation() const { return QLatin1String("--less-verbose"); } QString JobsOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2 \n" "\tUse concurrent build jobs. must be an integer greater than zero.\n" "\tThe default is the number of cores.\n") .arg(longRepresentation(), shortRepresentation()); } QString JobsOption::shortRepresentation() const { return QLatin1String("-j"); } QString JobsOption::longRepresentation() const { return QLatin1String("--jobs"); } void JobsOption::doParse(const QString &representation, QStringList &input) { const QString jobCountString = getArgument(representation, input); bool stringOk; m_jobCount = jobCountString.toInt(&stringOk); if (!stringOk || m_jobCount <= 0) throw ErrorInfo(Tr::tr("Invalid use of option '%1': Illegal job count '%2'.\nUsage: %3") .arg(representation, jobCountString, description(command()))); } QString KeepGoingOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2\n" "\tKeep going when errors occur (if at all possible).\n") .arg(longRepresentation(), shortRepresentation()); } QString KeepGoingOption::shortRepresentation() const { return QLatin1String("-k"); } QString KeepGoingOption::longRepresentation() const { return QLatin1String("--keep-going"); } QString DryRunOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1|%2\n" "\tDry run. No commands will be executed and no permanent changes to the\n" "\tbuild graph will be done.\n") .arg(longRepresentation(), shortRepresentation()); } QString DryRunOption::shortRepresentation() const { return QLatin1String("-n"); } QString DryRunOption::longRepresentation() const { return QLatin1String("--dry-run"); } QString NoInstallOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n" "\tDo not install any artifacts as part of the build process.\n") .arg(longRepresentation()); } QString NoInstallOption::longRepresentation() const { return QLatin1String("--no-install"); } static QString logTimeRepresentation() { return QLatin1String("--log-time"); } QString ShowProgressOption::description(CommandType command) const { Q_UNUSED(command); QString desc = Tr::tr("%1\n" "\tShow a progress bar. Implies '%2=%3'.\n").arg(longRepresentation(), loglevelLongRepresentation(), logLevelName(LoggerMinLevel)); return desc += Tr::tr("\tThis option is mutually exclusive with '%1'.\n") .arg(logTimeRepresentation()); } static QString showProgressRepresentation() { return QLatin1String("--show-progress"); } QString ShowProgressOption::longRepresentation() const { return showProgressRepresentation(); } void StringListOption::doParse(const QString &representation, QStringList &input) { m_arguments = getArgument(representation, input).split(QLatin1Char(',')); if (m_arguments.isEmpty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1': Argument list must not be empty.\n" "Usage: %2").arg(representation, description(command()))); } foreach (const QString &element, m_arguments) { if (element.isEmpty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1': Argument list must not contain " "empty elements.\nUsage: %2") .arg(representation, description(command()))); } } } QString ChangedFilesOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1 [,...]\n" "\tAssume these and only these files have changed.\n").arg(longRepresentation()); } QString ChangedFilesOption::longRepresentation() const { return QLatin1String("--changed-files"); } QString ProductsOption::description(CommandType command) const { const QString prefix = Tr::tr("%1|%2").arg(longRepresentation(), shortRepresentation()); switch (command) { case InstallCommandType: case RunCommandType: case ShellCommandType: return Tr::tr("%1 \n\tUse the specified product.\n").arg(prefix); default: return Tr::tr("%1 [,...]\n" "\tTake only the specified products into account.\n").arg(prefix); } } QString ProductsOption::shortRepresentation() const { return QLatin1String("-p"); } QString ProductsOption::longRepresentation() const { return QLatin1String("--products"); } static QStringList allLogLevelStrings() { QStringList result; for (int i = static_cast(LoggerMinLevel); i <= static_cast(LoggerMaxLevel); ++i) result << logLevelName(static_cast(i)); return result; } LogLevelOption::LogLevelOption() : m_logLevel(defaultLogLevel()) { } QString LogLevelOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1 \n" "\tUse the specified log level.\n" "\tPossible values are '%2'.\n" "\tThe default is '%3'.\n").arg(longRepresentation(), allLogLevelStrings().join(QLatin1String("', '")), logLevelName(defaultLogLevel())); } QString LogLevelOption::longRepresentation() const { return loglevelLongRepresentation(); } void LogLevelOption::doParse(const QString &representation, QStringList &input) { const QString levelString = getArgument(representation, input); const QList levels = QList() << LoggerError << LoggerWarning << LoggerInfo << LoggerDebug << LoggerTrace; foreach (LoggerLevel l, levels) { if (logLevelName(l) == levelString) { m_logLevel = l; return; } } throw ErrorInfo(Tr::tr("Invalid use of option '%1': Unknown log level '%2'.\nUsage: %3") .arg(representation, levelString, description(command()))); } QString AllArtifactsOption::description(CommandType command) const { Q_UNUSED(command); Q_ASSERT(command == CleanCommandType); return Tr::tr("%1\n\tRemove all build artifacts, not just intermediate ones.\n") .arg(longRepresentation()); } QString AllArtifactsOption::longRepresentation() const { return QLatin1String("--all-artifacts"); } QString ForceOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n\tDisregard objections.\n" "\tqbs might refuse to execute a given command because certain\n" "\tcircumstances make it seem dubious. This option switches the\n" "\trespective checks off.\n").arg(longRepresentation()); } QString ForceOption::longRepresentation() const { return QLatin1String("--force"); } QString ForceTimeStampCheckOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n\tForce timestamp checks.\n" "\tInstead of using the file timestamps that are stored in the build graph,\n" "\tretrieve the timestamps from the file system.\n").arg(longRepresentation()); } QString ForceTimeStampCheckOption::longRepresentation() const { return QLatin1String("--check-timestamps"); } QString BuildNonDefaultOption::description(CommandType command) const { Q_ASSERT(command == BuildCommandType || command == InstallCommandType); Q_UNUSED(command); return Tr::tr("%1\n\tBuild all products, even if their builtByDefault property is false.\n") .arg(longRepresentation()); } QString BuildNonDefaultOption::longRepresentation() const { return QLatin1String("--all-products"); } QString VersionOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n" "\tDisplay the qbs version and exit.\n").arg(longRepresentation()); } QString VersionOption::shortRepresentation() const { return QString(); } QString VersionOption::longRepresentation() const { return QStringLiteral("--version"); } InstallRootOption::InstallRootOption() : m_useSysroot(false) { } static QString magicSysrootString() { return QLatin1String("@sysroot"); } QString InstallRootOption::description(CommandType command) const { Q_ASSERT(command == InstallCommandType || command == RunCommandType); Q_UNUSED(command); return Tr::tr("%1 \n" "\tInstall into the given directory.\n" "\tThe default value is '/%2'.\n" "\tIf the directory does not exist, it will be created. Use the special\n" "\tvalue '%3' to install into the sysroot (i.e. the value of the\n" "\tproperty qbs.sysroot).\n") .arg(longRepresentation(), InstallOptions::defaultInstallRoot(), magicSysrootString()); } QString InstallRootOption::longRepresentation() const { return QLatin1String("--install-root"); } void InstallRootOption::doParse(const QString &representation, QStringList &input) { if (input.isEmpty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1: Argument expected.\n" "Usage: %2").arg(representation, description(command()))); } const QString installRoot = input.takeFirst(); if (installRoot == magicSysrootString()) m_useSysroot = true; else m_installRoot = installRoot; } QString RemoveFirstOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1\n\tRemove the installation base directory before installing.\n") .arg(longRepresentation()); } QString RemoveFirstOption::longRepresentation() const { return QLatin1String("--clean-install-root"); } QString NoBuildOption::description(CommandType command) const { Q_ASSERT(command == InstallCommandType || command == RunCommandType); Q_UNUSED(command); return Tr::tr("%1\n\tDo not build before installing.\n") .arg(longRepresentation()); } QString NoBuildOption::longRepresentation() const { return QLatin1String("--no-build"); } QString LogTimeOption::description(CommandType command) const { Q_UNUSED(command); QString desc = Tr::tr("%1\n\tLog the time that the operations involved in this command take.\n") .arg(longRepresentation()); desc += Tr::tr("\tThis option is implied in log levels '%1' and higher.\n") .arg(logLevelName(LoggerDebug)); return desc += Tr::tr("\tThis option is mutually exclusive with '%1'.\n") .arg(showProgressRepresentation()); } QString LogTimeOption::shortRepresentation() const { return QLatin1String("-t"); } QString LogTimeOption::longRepresentation() const { return logTimeRepresentation(); } SettingsDirOption::SettingsDirOption() { } QString SettingsDirOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1 \n" "\tRead all settings (such as profile information) from the given directory.\n" "\tThe default value is system-specific (see the QSettings documentation).\n" "\tIf the directory does not exist, it will be created.\n") .arg(longRepresentation()); } QString SettingsDirOption::longRepresentation() const { return QLatin1String("--settings-dir"); } void SettingsDirOption::doParse(const QString &representation, QStringList &input) { if (input.isEmpty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1: Argument expected.\n" "Usage: %2").arg(representation, description(command()))); } m_settingsDir = input.takeFirst(); } CommandEchoModeOption::CommandEchoModeOption() : m_echoMode(static_cast(-1)) { } QString CommandEchoModeOption::description(CommandType command) const { Q_UNUSED(command); return Tr::tr("%1 \n" "\tKind of output to show when executing commands.\n" "\tPossible values are '%2'.\n" "\tThe default is '%3'.\n") .arg(longRepresentation(), allCommandEchoModeStrings().join(QLatin1String("', '")), commandEchoModeName(defaultCommandEchoMode())); } QString CommandEchoModeOption::longRepresentation() const { return QLatin1String("--command-echo-mode"); } CommandEchoMode CommandEchoModeOption::commandEchoMode() const { return m_echoMode; } void CommandEchoModeOption::doParse(const QString &representation, QStringList &input) { const QString mode = getArgument(representation, input); if (mode.isEmpty()) { throw ErrorInfo(Tr::tr("Invalid use of option '%1': No command echo mode given.\nUsage: %2") .arg(representation, description(command()))); } if (!allCommandEchoModeStrings().contains(mode)) { throw ErrorInfo(Tr::tr("Invalid use of option '%1': " "Invalid command echo mode '%2' given.\nUsage: %3") .arg(representation, mode, description(command()))); } m_echoMode = commandEchoModeFromName(mode); } } // namespace qbs qbs-src-1.4.5/src/app/qbs/parser/commandlineoption.h000066400000000000000000000244171266132464200224310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_COMMANDLINEOPTION_H #define QBS_COMMANDLINEOPTION_H #include "commandtype.h" #include #include namespace qbs { class CommandLineOption { public: enum Type { FileOptionType, BuildDirectoryOptionType, LogLevelOptionType, VerboseOptionType, QuietOptionType, JobsOptionType, KeepGoingOptionType, DryRunOptionType, ShowProgressOptionType, ChangedFilesOptionType, ProductsOptionType, AllArtifactsOptionType, NoInstallOptionType, InstallRootOptionType, RemoveFirstOptionType, NoBuildOptionType, ForceOptionType, ForceTimestampCheckOptionType, BuildNonDefaultOptionType, VersionOptionType, LogTimeOptionType, CommandEchoModeOptionType, SettingsDirOptionType, GeneratorOptionType }; virtual ~CommandLineOption(); virtual QString description(CommandType command) const = 0; virtual QString shortRepresentation() const = 0; virtual QString longRepresentation() const = 0; virtual bool canAppearMoreThanOnce() const { return false; } void parse(CommandType command, const QString &representation, QStringList &input); protected: CommandLineOption(); QString getArgument(const QString &representation, QStringList &input); CommandType command() const { return m_command; } private: virtual void doParse(const QString &representation, QStringList &input) = 0; CommandType m_command; }; class FileOption : public CommandLineOption { public: QString projectFilePath() const { return m_projectFilePath; } private: QString description(CommandType command) const; QString shortRepresentation() const; QString longRepresentation() const; void doParse(const QString &representation, QStringList &input); private: QString m_projectFilePath; }; class BuildDirectoryOption : public CommandLineOption { public: QString projectBuildDirectory() const { return m_projectBuildDirectory; } static QString magicProjectString(); static QString magicProjectDirString(); private: QString description(CommandType command) const; QString shortRepresentation() const; QString longRepresentation() const; void doParse(const QString &representation, QStringList &input); private: QString m_projectBuildDirectory; }; class GeneratorOption : public CommandLineOption { public: QString generatorName() const { return m_generatorName; } private: QString description(CommandType command) const; QString shortRepresentation() const; QString longRepresentation() const; void doParse(const QString &representation, QStringList &input); private: QString m_generatorName; }; class CountingOption : public CommandLineOption { public: int count() const { return m_count; } protected: CountingOption() : m_count(0) {} private: bool canAppearMoreThanOnce() const { return true; } void doParse(const QString & /* representation */, QStringList & /* input */) { ++m_count; } int m_count; }; class VerboseOption : public CountingOption { QString description(CommandType command) const; QString shortRepresentation() const; QString longRepresentation() const; }; class QuietOption : public CountingOption { QString description(CommandType command) const; QString shortRepresentation() const; QString longRepresentation() const; }; class JobsOption : public CommandLineOption { public: JobsOption() : m_jobCount(0) {} int jobCount() const { return m_jobCount; } private: QString description(CommandType command) const; QString shortRepresentation() const; QString longRepresentation() const; void doParse(const QString &representation, QStringList &input); int m_jobCount; }; class OnOffOption : public CommandLineOption { public: bool enabled() const { return m_enabled; } protected: OnOffOption() : m_enabled(false) {} private: void doParse(const QString & /* representation */, QStringList & /* input */) { m_enabled = true; } bool m_enabled; }; class KeepGoingOption : public OnOffOption { QString description(CommandType command) const; QString shortRepresentation() const; QString longRepresentation() const; }; class DryRunOption : public OnOffOption { QString description(CommandType command) const; QString shortRepresentation() const; QString longRepresentation() const; }; class NoInstallOption : public OnOffOption { QString description(CommandType command) const; QString shortRepresentation() const { return QString(); } QString longRepresentation() const; }; class ShowProgressOption : public OnOffOption { public: QString description(CommandType command) const; QString shortRepresentation() const { return QString(); } QString longRepresentation() const; }; class AllArtifactsOption : public OnOffOption { QString description(CommandType command) const; QString shortRepresentation() const { return QString(); } QString longRepresentation() const; }; class ForceOption : public OnOffOption { QString description(CommandType command) const; QString shortRepresentation() const { return QString(); } QString longRepresentation() const; }; class ForceTimeStampCheckOption : public OnOffOption { QString description(CommandType command) const; QString shortRepresentation() const { return QString(); } QString longRepresentation() const; }; class BuildNonDefaultOption : public OnOffOption { QString description(CommandType command) const; QString shortRepresentation() const { return QString(); } QString longRepresentation() const; }; class VersionOption : public OnOffOption { private: QString description(CommandType command) const; QString shortRepresentation() const; QString longRepresentation() const; private: QString m_projectFilePath; }; class StringListOption : public CommandLineOption { public: QStringList arguments() const { return m_arguments; } private: void doParse(const QString &representation, QStringList &input); QStringList m_arguments; }; class ChangedFilesOption : public StringListOption { QString description(CommandType command) const; QString shortRepresentation() const { return QString(); } QString longRepresentation() const; }; class ProductsOption : public StringListOption { public: QString description(CommandType command) const; QString shortRepresentation() const; QString longRepresentation() const; }; class LogLevelOption : public CommandLineOption { public: LogLevelOption(); int logLevel() const { return m_logLevel; } private: QString description(CommandType command) const; QString shortRepresentation() const { return QString(); } QString longRepresentation() const; void doParse(const QString &representation, QStringList &input); int m_logLevel; }; class InstallRootOption : public CommandLineOption { public: InstallRootOption(); QString installRoot() const { return m_installRoot; } bool useSysroot() const { return m_useSysroot; } QString description(CommandType command) const; QString shortRepresentation() const { return QString(); } QString longRepresentation() const; private: void doParse(const QString &representation, QStringList &input); QString m_installRoot; bool m_useSysroot; }; class RemoveFirstOption : public OnOffOption { public: QString description(CommandType command) const; QString shortRepresentation() const { return QString(); } QString longRepresentation() const; }; class NoBuildOption : public OnOffOption { public: QString description(CommandType command) const; QString shortRepresentation() const { return QString(); } QString longRepresentation() const; }; class LogTimeOption : public OnOffOption { public: QString description(CommandType command) const; QString shortRepresentation() const; QString longRepresentation() const; }; class CommandEchoModeOption : public CommandLineOption { public: CommandEchoModeOption(); QString description(CommandType command) const; QString shortRepresentation() const { return QString(); } QString longRepresentation() const; CommandEchoMode commandEchoMode() const; private: void doParse(const QString &representation, QStringList &input); CommandEchoMode m_echoMode; }; class SettingsDirOption : public CommandLineOption { public: SettingsDirOption(); QString settingsDir() const { return m_settingsDir; } QString description(CommandType command) const; QString shortRepresentation() const { return QString(); } QString longRepresentation() const; private: void doParse(const QString &representation, QStringList &input); QString m_settingsDir; }; } // namespace qbs #endif // QBS_COMMANDLINEOPTION_H qbs-src-1.4.5/src/app/qbs/parser/commandlineoptionpool.cpp000066400000000000000000000210561266132464200236520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "commandlineoptionpool.h" namespace qbs { CommandLineOptionPool::~CommandLineOptionPool() { qDeleteAll(m_options); } CommandLineOption *CommandLineOptionPool::getOption(CommandLineOption::Type type) const { CommandLineOption *& option = m_options[type]; if (!option) { switch (type) { case CommandLineOption::FileOptionType: option = new FileOption; break; case CommandLineOption::BuildDirectoryOptionType: option = new BuildDirectoryOption; break; case CommandLineOption::LogLevelOptionType: option = new LogLevelOption; break; case CommandLineOption::VerboseOptionType: option = new VerboseOption; break; case CommandLineOption::QuietOptionType: option = new QuietOption; break; case CommandLineOption::JobsOptionType: option = new JobsOption; break; case CommandLineOption::KeepGoingOptionType: option = new KeepGoingOption; break; case CommandLineOption::DryRunOptionType: option = new DryRunOption; break; case CommandLineOption::ShowProgressOptionType: option = new ShowProgressOption; break; case CommandLineOption::ChangedFilesOptionType: option = new ChangedFilesOption; break; case CommandLineOption::ProductsOptionType: option = new ProductsOption; break; case CommandLineOption::AllArtifactsOptionType: option = new AllArtifactsOption; break; case CommandLineOption::NoInstallOptionType: option = new NoInstallOption; break; case CommandLineOption::InstallRootOptionType: option = new InstallRootOption; break; case CommandLineOption::RemoveFirstOptionType: option = new RemoveFirstOption; break; case CommandLineOption::NoBuildOptionType: option = new NoBuildOption; break; case CommandLineOption::ForceOptionType: option = new ForceOption; break; case CommandLineOption::ForceTimestampCheckOptionType: option = new ForceTimeStampCheckOption; break; case CommandLineOption::BuildNonDefaultOptionType: option = new BuildNonDefaultOption; break; case CommandLineOption::VersionOptionType: option = new VersionOption; break; case CommandLineOption::LogTimeOptionType: option = new LogTimeOption; break; case CommandLineOption::CommandEchoModeOptionType: option = new CommandEchoModeOption; break; case CommandLineOption::SettingsDirOptionType: option = new SettingsDirOption; break; case CommandLineOption::GeneratorOptionType: option = new GeneratorOption; break; default: qFatal("Unknown option type %d", type); } } return option; } FileOption *CommandLineOptionPool::fileOption() const { return static_cast(getOption(CommandLineOption::FileOptionType)); } BuildDirectoryOption *CommandLineOptionPool::buildDirectoryOption() const { return static_cast(getOption(CommandLineOption::BuildDirectoryOptionType)); } LogLevelOption *CommandLineOptionPool::logLevelOption() const { return static_cast(getOption(CommandLineOption::LogLevelOptionType)); } VerboseOption *CommandLineOptionPool::verboseOption() const { return static_cast(getOption(CommandLineOption::VerboseOptionType)); } QuietOption *CommandLineOptionPool::quietOption() const { return static_cast(getOption(CommandLineOption::QuietOptionType)); } ShowProgressOption *CommandLineOptionPool::showProgressOption() const { return static_cast(getOption(CommandLineOption::ShowProgressOptionType)); } DryRunOption *CommandLineOptionPool::dryRunOption() const { return static_cast(getOption(CommandLineOption::DryRunOptionType)); } ChangedFilesOption *CommandLineOptionPool::changedFilesOption() const { return static_cast(getOption(CommandLineOption::ChangedFilesOptionType)); } KeepGoingOption *CommandLineOptionPool::keepGoingOption() const { return static_cast(getOption(CommandLineOption::KeepGoingOptionType)); } JobsOption *CommandLineOptionPool::jobsOption() const { return static_cast(getOption(CommandLineOption::JobsOptionType)); } ProductsOption *CommandLineOptionPool::productsOption() const { return static_cast(getOption(CommandLineOption::ProductsOptionType)); } AllArtifactsOption *CommandLineOptionPool::allArtifactsOption() const { return static_cast(getOption(CommandLineOption::AllArtifactsOptionType)); } NoInstallOption *CommandLineOptionPool::noInstallOption() const { return static_cast(getOption(CommandLineOption::NoInstallOptionType)); } InstallRootOption *CommandLineOptionPool::installRootOption() const { return static_cast(getOption(CommandLineOption::InstallRootOptionType)); } RemoveFirstOption *CommandLineOptionPool::removeFirstoption() const { return static_cast(getOption(CommandLineOption::RemoveFirstOptionType)); } NoBuildOption *CommandLineOptionPool::noBuildOption() const { return static_cast(getOption(CommandLineOption::NoBuildOptionType)); } ForceOption *CommandLineOptionPool::forceOption() const { return static_cast(getOption(CommandLineOption::ForceOptionType)); } ForceTimeStampCheckOption *CommandLineOptionPool::forceTimestampCheckOption() const { return static_cast( getOption(CommandLineOption::ForceTimestampCheckOptionType)); } BuildNonDefaultOption *CommandLineOptionPool::buildNonDefaultOption() const { return static_cast( getOption(CommandLineOption::BuildNonDefaultOptionType)); } VersionOption *CommandLineOptionPool::versionOption() const { return static_cast( getOption(CommandLineOption::VersionOptionType)); } LogTimeOption *CommandLineOptionPool::logTimeOption() const { return static_cast(getOption(CommandLineOption::LogTimeOptionType)); } CommandEchoModeOption *CommandLineOptionPool::commandEchoModeOption() const { return static_cast( getOption(CommandLineOption::CommandEchoModeOptionType)); } SettingsDirOption *CommandLineOptionPool::settingsDirOption() const { return static_cast(getOption(CommandLineOption::SettingsDirOptionType)); } GeneratorOption *CommandLineOptionPool::generatorOption() const { return static_cast(getOption(CommandLineOption::GeneratorOptionType)); } } // namespace qbs qbs-src-1.4.5/src/app/qbs/parser/commandlineoptionpool.h000066400000000000000000000060051266132464200233140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_COMMANDLINEOPTIONPOOL_H #define QBS_COMMANDLINEOPTIONPOOL_H #include "commandlineoption.h" #include namespace qbs { class CommandLineOptionPool { public: ~CommandLineOptionPool(); CommandLineOption *getOption(CommandLineOption::Type type) const; FileOption *fileOption() const; BuildDirectoryOption *buildDirectoryOption() const; LogLevelOption *logLevelOption() const; VerboseOption *verboseOption() const; QuietOption *quietOption() const; ShowProgressOption *showProgressOption() const; DryRunOption *dryRunOption() const; ChangedFilesOption *changedFilesOption() const; KeepGoingOption *keepGoingOption() const; JobsOption *jobsOption() const; ProductsOption *productsOption() const; AllArtifactsOption *allArtifactsOption() const; NoInstallOption *noInstallOption() const; InstallRootOption *installRootOption() const; RemoveFirstOption *removeFirstoption() const; NoBuildOption *noBuildOption() const; ForceOption *forceOption() const; ForceTimeStampCheckOption *forceTimestampCheckOption() const; BuildNonDefaultOption *buildNonDefaultOption() const; VersionOption *versionOption() const; LogTimeOption *logTimeOption() const; CommandEchoModeOption *commandEchoModeOption() const; SettingsDirOption *settingsDirOption() const; GeneratorOption *generatorOption() const; private: mutable QHash m_options; }; } // namespace qbs #endif // QBS_COMMANDLINEOPTIONPOOL_H qbs-src-1.4.5/src/app/qbs/parser/commandlineparser.cpp000066400000000000000000000541301266132464200227430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "commandlineparser.h" #include "command.h" #include "commandlineoption.h" #include "commandlineoptionpool.h" #include "commandpool.h" #include "../qbstool.h" #include "../../shared/logging/consolelogger.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_UNIX #include #endif namespace qbs { using Internal::Tr; class CommandLineParser::CommandLineParserPrivate { public: CommandLineParserPrivate(); void doParse(); Command *commandFromString(const QString &commandString) const; QList allCommands() const; QString generalHelp() const; void setupProjectFile(); void setupBuildDirectory(); void setupProgress(); void setupLogLevel(); void setupBuildOptions(); bool checkForExistingBuildConfiguration(const QList &buildConfigs, const QString &buildVariant, const QString &profile); bool isSameProfile(const QString &profile1, const QString &profile2) const; bool withNonDefaultProducts() const; bool dryRun() const; QString settingsDir() const { return optionPool.settingsDirOption()->settingsDir(); } CommandEchoMode echoMode() const; QString propertyName(const QString &aCommandLineName) const; QStringList commandLine; Command *command; QString projectFilePath; QString projectBuildDirectory; BuildOptions buildOptions; CommandLineOptionPool optionPool; CommandPool commandPool; bool showProgress; bool logTime; }; CommandLineParser::CommandLineParser() : d(0) { } CommandLineParser::~CommandLineParser() { delete d; } void CommandLineParser::printHelp() const { QTextStream stream(stdout); Q_ASSERT(d->command == d->commandPool.getCommand(HelpCommandType)); const HelpCommand * const helpCommand = static_cast(d->command); if (helpCommand->commandToDescribe().isEmpty()) { stream << "qbs " QBS_VERSION "\n"; stream << d->generalHelp(); } else { const Command * const commandToDescribe = d->commandFromString(helpCommand->commandToDescribe()); if (commandToDescribe) { stream << commandToDescribe->longDescription(); } else if (!QbsTool::tryToRunTool(helpCommand->commandToDescribe(), QStringList(QLatin1String("--help")))) { throw ErrorInfo(Tr::tr("No such command '%1'.\n%2") .arg(helpCommand->commandToDescribe(), d->generalHelp())); } } } CommandType CommandLineParser::command() const { return d->command->type(); } QString CommandLineParser::projectFilePath() const { return d->projectFilePath; } QString CommandLineParser::projectBuildDirectory() const { return d->projectBuildDirectory; } BuildOptions CommandLineParser::buildOptions(const QString &profile) const { Settings settings(settingsDir()); Preferences preferences(&settings, profile); if (d->buildOptions.maxJobCount() <= 0) { d->buildOptions.setMaxJobCount(preferences.jobs()); } if (d->buildOptions.echoMode() < 0) { d->buildOptions.setEchoMode(preferences.defaultEchoMode()); } return d->buildOptions; } CleanOptions CommandLineParser::cleanOptions(const QString &profile) const { Q_ASSERT(command() == CleanCommandType); CleanOptions options; options.setCleanType(d->optionPool.allArtifactsOption()->enabled() ? CleanOptions::CleanupAll : CleanOptions::CleanupTemporaries); options.setDryRun(buildOptions(profile).dryRun()); options.setKeepGoing(buildOptions(profile).keepGoing()); options.setLogElapsedTime(logTime()); return options; } GenerateOptions CommandLineParser::generateOptions() const { Q_ASSERT(command() == GenerateCommandType); GenerateOptions options; options.setGeneratorName(d->optionPool.generatorOption()->generatorName()); return options; } InstallOptions CommandLineParser::installOptions(const QString &profile) const { Q_ASSERT(command() == InstallCommandType || command() == RunCommandType || command() == GenerateCommandType); InstallOptions options; options.setRemoveExistingInstallation(d->optionPool.removeFirstoption()->enabled()); options.setInstallRoot(d->optionPool.installRootOption()->installRoot()); options.setInstallIntoSysroot(d->optionPool.installRootOption()->useSysroot()); if (!options.installRoot().isEmpty()) { QFileInfo fi(options.installRoot()); if (!fi.isAbsolute()) options.setInstallRoot(fi.absoluteFilePath()); } options.setDryRun(buildOptions(profile).dryRun()); options.setKeepGoing(buildOptions(profile).keepGoing()); options.setLogElapsedTime(logTime()); return options; } bool CommandLineParser::force() const { return d->optionPool.forceOption()->enabled(); } bool CommandLineParser::forceTimestampCheck() const { return d->optionPool.forceTimestampCheckOption()->enabled(); } bool CommandLineParser::dryRun() const { return d->dryRun(); } bool CommandLineParser::logTime() const { return d->logTime; } bool CommandLineParser::withNonDefaultProducts() const { return d->withNonDefaultProducts(); } bool CommandLineParser::buildBeforeInstalling() const { return !d->optionPool.noBuildOption()->enabled(); } QStringList CommandLineParser::runArgs() const { Q_ASSERT(d->command->type() == RunCommandType); return static_cast(d->command)->targetParameters(); } QStringList CommandLineParser::products() const { return d->optionPool.productsOption()->arguments(); } bool CommandLineParser::showProgress() const { return d->showProgress; } bool CommandLineParser::showVersion() const { return d->optionPool.versionOption()->enabled(); } QString CommandLineParser::settingsDir() const { return d->settingsDir(); } QString CommandLineParser::commandName() const { return d->command->representation(); } QString CommandLineParser::commandDescription() const { return d->command->longDescription(); } static QString getBuildVariant(const QVariantMap &buildConfig) { return buildConfig.value(QLatin1String("qbs.buildVariant")).toString(); } static QString getProfile(const QVariantMap &buildConfig) { return buildConfig.value(QLatin1String("qbs.profile")).toString(); } QList CommandLineParser::buildConfigurations() const { // first: build variant, second: properties. Empty variant name used for global properties. typedef QPair PropertyListItem; QList propertiesPerBuildVariant; const QString buildVariantKey = QLatin1String("qbs.buildVariant"); QString currentBuildVariant; QVariantMap currentProperties; foreach (const QString &arg, d->command->additionalArguments()) { const int sepPos = arg.indexOf(QLatin1Char(':')); if (sepPos == -1) { // New build variant found. propertiesPerBuildVariant << qMakePair(currentBuildVariant, currentProperties); currentBuildVariant = arg; currentProperties.clear(); continue; } const QString property = d->propertyName(arg.left(sepPos)); if (property.isEmpty()) qbsWarning() << Tr::tr("Ignoring empty property."); else if (property == buildVariantKey) qbsWarning() << Tr::tr("Refusing to overwrite special property '%1'.").arg(buildVariantKey); else currentProperties.insert(property, arg.mid(sepPos + 1)); } propertiesPerBuildVariant << qMakePair(currentBuildVariant, currentProperties); if (propertiesPerBuildVariant.count() == 1) // No build variant specified on command line. propertiesPerBuildVariant << PropertyListItem(QLatin1String("debug"), QVariantMap()); const QVariantMap globalProperties = propertiesPerBuildVariant.takeFirst().second; QList buildConfigs; foreach (const PropertyListItem &item, propertiesPerBuildVariant) { QVariantMap properties = item.second; for (QVariantMap::ConstIterator globalPropIt = globalProperties.constBegin(); globalPropIt != globalProperties.constEnd(); ++globalPropIt) { if (!properties.contains(globalPropIt.key())) properties.insert(globalPropIt.key(), globalPropIt.value()); } const QString buildVariant = item.first; const QString profile = getProfile(properties); if (d->checkForExistingBuildConfiguration(buildConfigs, buildVariant, profile)) { qbsWarning() << Tr::tr("Ignoring redundant request to build for variant '%1' and " "profile '%2'.").arg(buildVariant, profile); continue; } properties.insert(buildVariantKey, buildVariant); buildConfigs << properties; } return buildConfigs; } bool CommandLineParser::parseCommandLine(const QStringList &args) { delete d; d = new CommandLineParserPrivate; d->commandLine = args; try { d->doParse(); return true; } catch (const ErrorInfo &error) { qbsError() << error.toString(); return false; } } CommandLineParser::CommandLineParserPrivate::CommandLineParserPrivate() : command(0), commandPool(optionPool), showProgress(false), logTime(false) { } void CommandLineParser::CommandLineParserPrivate::doParse() { if (commandLine.isEmpty()) { // No command given, use default. command = commandPool.getCommand(BuildCommandType); } else { command = commandFromString(commandLine.first()); if (command) { commandLine.removeFirst(); } else { // No command given. // As an exception to the command-based syntax, we allow -h or --help as the // sole contents of the command line, because people are used to this working. if (commandLine.count() == 1 && (commandLine.first() == QLatin1String("-h") || commandLine.first() == QLatin1String("--help"))) { command = commandPool.getCommand(HelpCommandType); commandLine.clear(); } else { command = commandPool.getCommand(BuildCommandType); } } } command->parse(commandLine); if (command->type() == HelpCommandType) return; if (command->type() == BuildCommandType && optionPool.versionOption()->enabled()) return; setupProjectFile(); setupBuildDirectory(); setupProgress(); setupLogLevel(); setupBuildOptions(); } Command *CommandLineParser::CommandLineParserPrivate::commandFromString(const QString &commandString) const { foreach (Command * const command, allCommands()) { if (command->representation() == commandString) return command; } return 0; } QList CommandLineParser::CommandLineParserPrivate::allCommands() const { return QList() << commandPool.getCommand(GenerateCommandType) << commandPool.getCommand(ResolveCommandType) << commandPool.getCommand(BuildCommandType) << commandPool.getCommand(CleanCommandType) << commandPool.getCommand(RunCommandType) << commandPool.getCommand(ShellCommandType) << commandPool.getCommand(StatusCommandType) << commandPool.getCommand(UpdateTimestampsCommandType) << commandPool.getCommand(InstallCommandType) << commandPool.getCommand(DumpNodesTreeCommandType) << commandPool.getCommand(HelpCommandType); } QString CommandLineParser::CommandLineParserPrivate::generalHelp() const { QString help = Tr::tr("Usage: qbs [command] [command parameters]\n"); help += Tr::tr("Internal commands:\n"); const int rhsIndentation = 30; // Sorting the commands by name is nicer for the user. QMap commandMap; foreach (const Command * command, allCommands()) commandMap.insert(command->representation(), command); foreach (const Command * command, commandMap) { help.append(QLatin1String(" ")).append(command->representation()); const QString whitespace = QString(rhsIndentation - 2 - command->representation().count(), QLatin1Char(' ')); help.append(whitespace).append(command->shortDescription()).append(QLatin1Char('\n')); } QStringList toolNames = QbsTool::allToolNames(); toolNames.sort(); if (!toolNames.isEmpty()) { help.append(QLatin1Char('\n')).append(Tr::tr("Auxiliary commands:\n")); foreach (const QString &toolName, toolNames) { help.append(QLatin1String(" ")).append(toolName); const QString whitespace = QString(rhsIndentation - 2 - toolName.count(), QLatin1Char(' ')); QbsTool tool; tool.runTool(toolName, QStringList(QLatin1String("--help"))); if (tool.exitCode() != 0) continue; const QString shortDescription = tool.stdOut().left(tool.stdOut().indexOf(QLatin1Char('\n'))); help.append(whitespace).append(shortDescription).append(QLatin1Char('\n')); } } return help; } void CommandLineParser::CommandLineParserPrivate::setupProjectFile() { projectFilePath = optionPool.fileOption()->projectFilePath(); if (projectFilePath.isEmpty()) { qbsDebug() << "No project file given; looking in current directory."; projectFilePath = QDir::currentPath(); } const QFileInfo projectFileInfo(projectFilePath); if (!projectFileInfo.exists()) throw ErrorInfo(Tr::tr("Project file '%1' cannot be found.").arg(projectFilePath)); if (projectFileInfo.isRelative()) projectFilePath = projectFileInfo.absoluteFilePath(); if (projectFileInfo.isFile()) return; if (!projectFileInfo.isDir()) throw ErrorInfo(Tr::tr("Project file '%1' has invalid type.").arg(projectFilePath)); const QStringList namePatterns = QStringList() << QLatin1String("*.qbs"); const QStringList &actualFileNames = QDir(projectFilePath).entryList(namePatterns, QDir::Files); if (actualFileNames.isEmpty()) { QString error; if (optionPool.fileOption()->projectFilePath().isEmpty()) error = Tr::tr("No project file given and none found in current directory.\n"); else error = Tr::tr("No project file found in directory '%1'.").arg(projectFilePath); throw ErrorInfo(error); } if (actualFileNames.count() > 1) { throw ErrorInfo(Tr::tr("More than one project file found in directory '%1'.") .arg(projectFilePath)); } projectFilePath.append(QLatin1Char('/')).append(actualFileNames.first()); projectFilePath = QDir::current().filePath(projectFilePath); projectFilePath = QDir::cleanPath(projectFilePath); qbsDebug() << "Using project file '" << QDir::toNativeSeparators(projectFilePath) << "'."; } void CommandLineParser::CommandLineParserPrivate::setupBuildDirectory() { projectBuildDirectory = optionPool.buildDirectoryOption()->projectBuildDirectory(); } void CommandLineParser::CommandLineParserPrivate::setupBuildOptions() { buildOptions.setDryRun(dryRun()); QStringList changedFiles = optionPool.changedFilesOption()->arguments(); QDir currentDir; for (int i = 0; i < changedFiles.count(); ++i) { QString &file = changedFiles[i]; file = QDir::fromNativeSeparators(currentDir.absoluteFilePath(file)); } buildOptions.setChangedFiles(changedFiles); buildOptions.setKeepGoing(optionPool.keepGoingOption()->enabled()); buildOptions.setForceTimestampCheck(optionPool.forceTimestampCheckOption()->enabled()); const JobsOption * jobsOption = optionPool.jobsOption(); buildOptions.setMaxJobCount(jobsOption->jobCount()); buildOptions.setLogElapsedTime(logTime); buildOptions.setEchoMode(echoMode()); buildOptions.setInstall(!optionPool.noInstallOption()->enabled()); buildOptions.setRemoveExistingInstallation(optionPool.removeFirstoption()->enabled()); } void CommandLineParser::CommandLineParserPrivate::setupProgress() { const ShowProgressOption * const option = optionPool.showProgressOption(); showProgress = option->enabled(); #ifdef Q_OS_UNIX if (showProgress && !isatty(STDOUT_FILENO)) { showProgress = false; qbsWarning() << Tr::tr("Ignoring option '%1', because standard output is " "not connected to a terminal.").arg(option->longRepresentation()); } #endif } void CommandLineParser::CommandLineParserPrivate::setupLogLevel() { const LogLevelOption * const logLevelOption = optionPool.logLevelOption(); const VerboseOption * const verboseOption = optionPool.verboseOption(); const QuietOption * const quietOption = optionPool.quietOption(); int logLevel = logLevelOption->logLevel(); logLevel += verboseOption->count(); logLevel -= quietOption->count(); if (showProgress && logLevel != LoggerMinLevel) { const bool logLevelWasSetByUser = logLevelOption->logLevel() != defaultLogLevel() || verboseOption->count() > 0 || quietOption->count() > 0; if (logLevelWasSetByUser) { qbsInfo() << Tr::tr("Setting log level to '%1', because option '%2'" " has been given.").arg(logLevelName(LoggerMinLevel), optionPool.showProgressOption()->longRepresentation()); } logLevel = LoggerMinLevel; } if (logLevel < LoggerMinLevel) { qbsWarning() << Tr::tr("Cannot decrease log level as much as specified; using '%1'.") .arg(logLevelName(LoggerMinLevel)); logLevel = LoggerMinLevel; } else if (logLevel > LoggerMaxLevel) { qbsWarning() << Tr::tr("Cannot increase log level as much as specified; using '%1'.") .arg(logLevelName(LoggerMaxLevel)); logLevel = LoggerMaxLevel; } logTime = optionPool.logTimeOption()->enabled(); if (showProgress && logTime) { qbsWarning() << Tr::tr("Options '%1' and '%2' are incompatible. Ignoring '%2'.") .arg(optionPool.showProgressOption()->longRepresentation(), optionPool.logTimeOption()->longRepresentation()); logTime = false; } ConsoleLogger::instance().logSink()->setLogLevel(static_cast(logLevel)); } QString CommandLineParser::CommandLineParserPrivate::propertyName(const QString &aCommandLineName) const { // Make fully-qualified, ie "platform" -> "qbs.platform" if (aCommandLineName.contains(QLatin1Char('.'))) return aCommandLineName; else return QLatin1String("qbs.") + aCommandLineName; } bool CommandLineParser::CommandLineParserPrivate::checkForExistingBuildConfiguration( const QList &buildConfigs, const QString &buildVariant, const QString &profile) { foreach (const QVariantMap &buildConfig, buildConfigs) { if (buildVariant == getBuildVariant(buildConfig) && isSameProfile(profile, getProfile(buildConfig))) { return true; } } return false; } bool CommandLineParser::CommandLineParserPrivate::isSameProfile(const QString &profile1, const QString &profile2) const { if (profile1 == profile2) return true; Settings settings(settingsDir()); if (profile1.isEmpty()) return profile2.isEmpty() || profile2 == settings.defaultProfile(); if (profile2.isEmpty()) return profile1 == settings.defaultProfile(); return false; } bool CommandLineParser::CommandLineParserPrivate::withNonDefaultProducts() const { if (command->type() == GenerateCommandType) return true; return optionPool.buildNonDefaultOption()->enabled(); } bool CommandLineParser::CommandLineParserPrivate::dryRun() const { if (command->type() == GenerateCommandType) return true; return optionPool.dryRunOption()->enabled(); } CommandEchoMode CommandLineParser::CommandLineParserPrivate::echoMode() const { if (command->type() == GenerateCommandType) return CommandEchoModeSilent; if (optionPool.commandEchoModeOption()->commandEchoMode() >= 0) return optionPool.commandEchoModeOption()->commandEchoMode(); return defaultCommandEchoMode(); } } // namespace qbs qbs-src-1.4.5/src/app/qbs/parser/commandlineparser.h000066400000000000000000000056011266132464200224070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_COMMANDLINEPARSER_H #define QBS_COMMANDLINEPARSER_H #include "commandtype.h" #include #include namespace qbs { class BuildOptions; class CleanOptions; class GenerateOptions; class InstallOptions; class Settings; class CommandLineParser { Q_DISABLE_COPY(CommandLineParser) public: CommandLineParser(); ~CommandLineParser(); bool parseCommandLine(const QStringList &args); void printHelp() const; CommandType command() const; QString commandName() const; QString commandDescription() const; QString projectFilePath() const; QString projectBuildDirectory() const; BuildOptions buildOptions(const QString &profile) const; CleanOptions cleanOptions(const QString &profile) const; GenerateOptions generateOptions() const; InstallOptions installOptions(const QString &profile) const; bool force() const; bool forceTimestampCheck() const; bool dryRun() const; bool logTime() const; bool withNonDefaultProducts() const; bool buildBeforeInstalling() const; QStringList runArgs() const; QStringList products() const; QList buildConfigurations() const; bool showProgress() const; bool showVersion() const; QString settingsDir() const; private: class CommandLineParserPrivate; CommandLineParserPrivate *d; }; } // namespace qbs #endif // QBS_COMMANDLINEPARSER_H qbs-src-1.4.5/src/app/qbs/parser/commandpool.cpp000066400000000000000000000061101266132464200215430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "commandpool.h" #include "command.h" namespace qbs { CommandPool::CommandPool(CommandLineOptionPool &optionPool) : m_optionPool(optionPool) { } CommandPool::~CommandPool() { qDeleteAll(m_commands); } qbs::Command *CommandPool::getCommand(CommandType type) const { Command *& command = m_commands[type]; if (!command) { switch (type) { case ResolveCommandType: command = new ResolveCommand(m_optionPool); break; case GenerateCommandType: command = new GenerateCommand(m_optionPool); break; case BuildCommandType: command = new BuildCommand(m_optionPool); break; case CleanCommandType: command = new CleanCommand(m_optionPool); break; case RunCommandType: command = new RunCommand(m_optionPool); break; case ShellCommandType: command = new ShellCommand(m_optionPool); break; case StatusCommandType: command = new StatusCommand(m_optionPool); break; case UpdateTimestampsCommandType: command = new UpdateTimestampsCommand(m_optionPool); break; case InstallCommandType: command = new InstallCommand(m_optionPool); break; case DumpNodesTreeCommandType: command = new DumpNodesTreeCommand(m_optionPool); break; case HelpCommandType: command = new HelpCommand(m_optionPool); break; } } return command; } } // namespace qbs qbs-src-1.4.5/src/app/qbs/parser/commandpool.h000066400000000000000000000037461266132464200212240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_COMMANDPOOL_H #define QBS_COMMANDPOOL_H #include "commandtype.h" #include namespace qbs { class Command; class CommandLineOptionPool; class CommandPool { Q_DISABLE_COPY(CommandPool) public: CommandPool(CommandLineOptionPool &optionPool); ~CommandPool(); Command *getCommand(CommandType type) const; private: CommandLineOptionPool &m_optionPool; mutable QHash m_commands; }; } // namespace qbs #endif // QBS_COMMANDPOOL_H qbs-src-1.4.5/src/app/qbs/parser/commandtype.h000066400000000000000000000035371266132464200212320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef COMMANDTYPE_H #define COMMANDTYPE_H namespace qbs { enum CommandType { ResolveCommandType, BuildCommandType, CleanCommandType, RunCommandType, ShellCommandType, StatusCommandType, UpdateTimestampsCommandType, DumpNodesTreeCommandType, InstallCommandType, HelpCommandType, GenerateCommandType }; } // namespace qbs #endif // COMMANDTYPE_H qbs-src-1.4.5/src/app/qbs/parser/parser.pri000066400000000000000000000006111266132464200205370ustar00rootroot00000000000000SOURCES += \ $$PWD/commandlineparser.cpp \ $$PWD/command.cpp \ $$PWD/commandpool.cpp \ $$PWD/commandlineoption.cpp \ $$PWD/commandlineoptionpool.cpp HEADERS += \ $$PWD/commandlineparser.h \ $$PWD/command.h \ $$PWD/commandpool.h \ $$PWD/commandlineoption.h \ $$PWD/commandlineoptionpool.h \ $$PWD/commandtype.h include(../../../../qbs_version.pri) qbs-src-1.4.5/src/app/qbs/qbs.pro000066400000000000000000000015271266132464200165510ustar00rootroot00000000000000include(../app.pri) include(parser/parser.pri) TARGET = qbs SOURCES += main.cpp \ ctrlchandler.cpp \ application.cpp \ status.cpp \ consoleprogressobserver.cpp \ commandlinefrontend.cpp \ qbstool.cpp HEADERS += \ ctrlchandler.h \ application.h \ status.h \ consoleprogressobserver.h \ commandlinefrontend.h \ qbstool.h include(../../library_dirname.pri) isEmpty(QBS_RELATIVE_LIBEXEC_PATH):QBS_RELATIVE_LIBEXEC_PATH=../libexec/qbs isEmpty(QBS_RELATIVE_PLUGINS_PATH):QBS_RELATIVE_PLUGINS_PATH=../$${QBS_LIBRARY_DIRNAME} isEmpty(QBS_RELATIVE_SEARCH_PATH):QBS_RELATIVE_SEARCH_PATH=.. DEFINES += QBS_RELATIVE_LIBEXEC_PATH=\\\"$${QBS_RELATIVE_LIBEXEC_PATH}\\\" DEFINES += QBS_RELATIVE_PLUGINS_PATH=\\\"$${QBS_RELATIVE_PLUGINS_PATH}\\\" DEFINES += QBS_RELATIVE_SEARCH_PATH=\\\"$${QBS_RELATIVE_SEARCH_PATH}\\\" qbs-src-1.4.5/src/app/qbs/qbs.qbs000066400000000000000000000024021266132464200165270ustar00rootroot00000000000000import qbs 1.0 import QbsFunctions QbsApp { name: "qbs_app" Depends { name: "qbs resources" } targetName: "qbs" cpp.defines: base.concat([ 'QBS_VERSION="' + QbsFunctions.qbsVersion() + '"', 'QBS_RELATIVE_LIBEXEC_PATH="' + project.relativeLibexecPath + '"', 'QBS_RELATIVE_SEARCH_PATH="' + project.relativeSearchPath + '"', 'QBS_RELATIVE_PLUGINS_PATH="' + project.relativePluginsPath + '"' ]) files: [ "application.cpp", "application.h", "commandlinefrontend.cpp", "commandlinefrontend.h", "consoleprogressobserver.cpp", "consoleprogressobserver.h", "ctrlchandler.cpp", "ctrlchandler.h", "main.cpp", "qbstool.cpp", "qbstool.h", "status.cpp", "status.h", ] Group { name: "parser" prefix: name + '/' files: [ "command.cpp", "command.h", "commandlineoption.cpp", "commandlineoption.h", "commandlineoptionpool.cpp", "commandlineoptionpool.h", "commandlineparser.cpp", "commandlineparser.h", "commandpool.cpp", "commandpool.h", "commandtype.h", ] } } qbs-src-1.4.5/src/app/qbs/qbstool.cpp000066400000000000000000000071131266132464200174260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "qbstool.h" #include #include #include #include #include #include static QString toolPrefix() { return QLatin1String("qbs-"); } static QString qbsBinDir() { return QCoreApplication::applicationDirPath(); } static QString qbsToolFilePath(const QString &toolName) { return qbsBinDir() + QLatin1Char('/') + toolPrefix() + qbs::Internal::HostOsInfo::appendExecutableSuffix(toolName); } void QbsTool::runTool(const QString &toolName, const QStringList &arguments) { m_failedToStart = false; m_exitCode = -1; const QString filePath = qbsToolFilePath(toolName); const QFileInfo fi(filePath); if (!fi.exists() || !fi.isFile() || !fi.isExecutable()) { m_failedToStart = true; return; } QProcess toolProc; toolProc.start(filePath, arguments); if (!toolProc.waitForStarted()) m_failedToStart = true; toolProc.waitForFinished(-1); m_exitCode = toolProc.exitCode(); m_stdout = QString::fromLocal8Bit(toolProc.readAllStandardOutput()); m_stderr = QString::fromLocal8Bit(toolProc.readAllStandardError()); } bool QbsTool::tryToRunTool(const QString &toolName, const QStringList &arguments, int *exitCode) { QbsTool tool; tool.runTool(toolName, arguments); if (exitCode) *exitCode = tool.exitCode(); if (tool.failedToStart()) return false; std::cout << qPrintable(tool.stdOut()); std::cerr << qPrintable(tool.stdErr()); return true; } QStringList QbsTool::allToolNames() { const QString suffix = QLatin1String(QBS_HOST_EXE_SUFFIX); QStringList toolFileNames = QDir(qbsBinDir()).entryList(QStringList(toolPrefix() + QString::fromLocal8Bit("*%1").arg(suffix)), QDir::Files, QDir::Name); QStringList toolNames; const int prefixLength = toolPrefix().count(); foreach (const QString &toolFileName, toolFileNames) { toolNames << toolFileName.mid(prefixLength, toolFileName.count() - prefixLength - suffix.count()); } return toolNames; } qbs-src-1.4.5/src/app/qbs/qbstool.h000066400000000000000000000041171266132464200170740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include class QbsTool { public: void runTool(const QString &toolName, const QStringList &arguments); bool failedToStart() const { return m_failedToStart; } int exitCode() const { return m_exitCode; } QString stdOut() const { return m_stdout; } QString stdErr() const { return m_stderr; } static QStringList allToolNames(); static bool tryToRunTool(const QString &toolName, const QStringList &arguments, int *exitCode = 0); private: bool m_failedToStart; int m_exitCode; QString m_stdout; QString m_stderr; }; qbs-src-1.4.5/src/app/qbs/status.cpp000066400000000000000000000147761266132464200173030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "status.h" #include "../shared/logging/consolelogger.h" #include #include #include #include #include #include namespace qbs { static QList createIgnoreList(const QString &projectRootPath) { QList ignoreRegularExpressionList; ignoreRegularExpressionList.append(QRegExp(projectRootPath + QLatin1String("/build.*"))); ignoreRegularExpressionList.append(QRegExp(QLatin1String("*.qbs"), Qt::CaseSensitive, QRegExp::Wildcard)); ignoreRegularExpressionList.append(QRegExp(QLatin1String("*.pro"), Qt::CaseSensitive, QRegExp::Wildcard)); ignoreRegularExpressionList.append(QRegExp(QLatin1String("*Makefile"), Qt::CaseSensitive, QRegExp::Wildcard)); ignoreRegularExpressionList.append(QRegExp(QLatin1String("*.so*"), Qt::CaseSensitive, QRegExp::Wildcard)); ignoreRegularExpressionList.append(QRegExp(QLatin1String("*.o"), Qt::CaseSensitive, QRegExp::Wildcard)); QString ignoreFilePath = projectRootPath + QLatin1String("/.qbsignore"); QFile ignoreFile(ignoreFilePath); if (ignoreFile.open(QFile::ReadOnly)) { QList ignoreTokenList = ignoreFile.readAll().split('\n'); foreach (const QByteArray &btoken, ignoreTokenList) { const QString token = QString::fromLatin1(btoken); if (token.left(1) == QLatin1String("/")) ignoreRegularExpressionList.append(QRegExp(projectRootPath + token + QLatin1String(".*"), Qt::CaseSensitive, QRegExp::RegExp2)); else if (!token.isEmpty()) ignoreRegularExpressionList.append(QRegExp(token, Qt::CaseSensitive, QRegExp::RegExp2)); } } return ignoreRegularExpressionList; } static QStringList allFilesInDirectoryRecursive(const QDir &rootDirecory, const QList &ignoreRegularExpressionList) { QStringList fileList; foreach (const QFileInfo &fileInfo, rootDirecory.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot, QDir::Name)) { QString absoluteFilePath = fileInfo.absoluteFilePath(); bool inIgnoreList = false; foreach (const QRegExp &ignoreRegularExpression, ignoreRegularExpressionList) { if (ignoreRegularExpression.exactMatch(absoluteFilePath)) { inIgnoreList = true; break; } } if (!inIgnoreList) { if (fileInfo.isFile()) fileList.append(absoluteFilePath); else if (fileInfo.isDir()) fileList.append(allFilesInDirectoryRecursive(QDir(absoluteFilePath), ignoreRegularExpressionList)); } } return fileList; } static QStringList allFilesInProject(const QString &projectRootPath) { QList ignoreRegularExpressionList = createIgnoreList(projectRootPath); return allFilesInDirectoryRecursive(QDir(projectRootPath), ignoreRegularExpressionList); } QStringList allFiles(const ProductData &product) { QStringList files; foreach (const GroupData &group, product.groups()) files += group.allFilePaths(); return files; } int printStatus(const ProjectData &project) { const QString projectFilePath = project.location().filePath(); QString projectDirectory = QFileInfo(projectFilePath).dir().path(); int projectDirectoryPathLength = projectDirectory.length(); QStringList untrackedFilesInProject = allFilesInProject(projectDirectory); QStringList missingFiles; foreach (const ProductData &product, project.allProducts()) { qbsInfo() << "\nProduct: " << product.name() << " (" << product.location().filePath() << ":" << product.location().line() << ")"; foreach (const GroupData &group, product.groups()) { qbsInfo() << " Group: " << group.name() << " (" << group.location().filePath() << ":" << group.location().line() << ")"; QStringList sourceFiles = group.allFilePaths(); qSort(sourceFiles); foreach (const QString &sourceFile, sourceFiles) { if (!QFileInfo(sourceFile).exists()) missingFiles.append(sourceFile); qbsInfo() << " " << sourceFile.mid(projectDirectoryPathLength + 1); untrackedFilesInProject.removeOne(sourceFile); } } } qbsInfo() << "\nMissing files:"; foreach (const QString &untrackedFile, missingFiles) qbsInfo() << untrackedFile.mid(projectDirectoryPathLength + 1); qbsInfo() << "\nUntracked files:"; foreach (const QString &missingFile, untrackedFilesInProject) qbsInfo() << missingFile.mid(projectDirectoryPathLength + 1); return 0; } } // namespace qbs qbs-src-1.4.5/src/app/qbs/status.h000066400000000000000000000032221266132464200167300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef STATUS_H #define STATUS_H namespace qbs { class ProjectData; int printStatus(const ProjectData &project); } // namespace qbs #endif // STATUS_H qbs-src-1.4.5/src/app/shared/000077500000000000000000000000001266132464200157165ustar00rootroot00000000000000qbs-src-1.4.5/src/app/shared/logging/000077500000000000000000000000001266132464200173445ustar00rootroot00000000000000qbs-src-1.4.5/src/app/shared/logging/coloredoutput.cpp000066400000000000000000000062601266132464200227640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "coloredoutput.h" #include #ifdef Q_OS_WIN32 # include #endif #include #ifdef Q_OS_UNIX #include #endif void printfColored(TextColor color, const char *str, va_list vl) { fprintfColored(color, stdout, str, vl); } void printfColored(TextColor color, const char *str, ...) { va_list vl; va_start(vl, str); printfColored(color, str, vl); va_end(vl); } void fprintfColored(TextColor color, FILE *file, const char *str, va_list vl) { #if defined(Q_OS_UNIX) if (color != TextColorDefault && isatty(fileno(file))) { unsigned char bright = (color & TextColorBright) >> 3; fprintf(file, "\033[%d;%dm", bright, 30 + (color & ~TextColorBright)); vfprintf(file, str, vl); fprintf(stdout, "\033[0m"); fprintf(stderr, "\033[0m"); } else #elif defined(Q_OS_WIN32) HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO csbiInfo; if (color != TextColorDefault && hStdout != INVALID_HANDLE_VALUE && GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) { WORD bgrColor = ((color & 1) << 2) | (color & 2) | ((color & 4) >> 2); // BGR instead of RGB. if (color & TextColorBright) bgrColor += FOREGROUND_INTENSITY; SetConsoleTextAttribute(hStdout, (csbiInfo.wAttributes & 0xf0) | bgrColor); vfprintf(file, str, vl); SetConsoleTextAttribute(hStdout, csbiInfo.wAttributes); } else #endif { vfprintf(file, str, vl); } } void fprintfColored(TextColor color, FILE *file, const char *str, ...) { va_list vl; va_start(vl, str); fprintfColored(color, file, str, vl); va_end(vl); } qbs-src-1.4.5/src/app/shared/logging/coloredoutput.h000066400000000000000000000053401266132464200224270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_COLOREDOUTPUT_H #define QBS_COLOREDOUTPUT_H #include #include // http://en.wikipedia.org/wiki/ANSI_escape_code#Colors enum TextColor { TextColorDefault = -1, TextColorBlack = 0, TextColorDarkRed = 1, TextColorDarkGreen = 2, TextColorDarkBlue = 4, TextColorDarkCyan = TextColorDarkGreen | TextColorDarkBlue, TextColorDarkMagenta = TextColorDarkRed | TextColorDarkBlue, TextColorDarkYellow = TextColorDarkRed | TextColorDarkGreen, TextColorGray = 7, TextColorBright = 8, TextColorRed = TextColorDarkRed | TextColorBright, TextColorGreen = TextColorDarkGreen | TextColorBright, TextColorBlue = TextColorDarkBlue | TextColorBright, TextColorCyan = TextColorDarkCyan | TextColorBright, TextColorMagenta = TextColorDarkMagenta | TextColorBright, TextColorYellow = TextColorDarkYellow | TextColorBright, TextColorWhite = TextColorGray | TextColorBright }; void printfColored(TextColor color, const char *str, va_list vl); void printfColored(TextColor color, const char *str, ...); void fprintfColored(TextColor color, FILE *file, const char *str, va_list vl); void fprintfColored(TextColor color, FILE *file, const char *str, ...); #endif // QBS_COLOREDOUTPUT_H qbs-src-1.4.5/src/app/shared/logging/consolelogger.cpp000066400000000000000000000070151266132464200227150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "consolelogger.h" #include #include #include static QHash setupColorTable() { QHash colorTable; colorTable[QLatin1String("compiler")] = TextColorDefault; colorTable[QLatin1String("linker")] = TextColorDarkGreen; colorTable[QLatin1String("codegen")] = TextColorDarkYellow; colorTable[QLatin1String("filegen")] = TextColorDarkYellow; return colorTable; } ConsoleLogSink::ConsoleLogSink() : m_coloredOutputEnabled(true), m_enabled(true) { } void ConsoleLogSink::doPrintMessage(qbs::LoggerLevel level, const QString &message, const QString &tag) { if (!m_enabled) return; FILE * const file = level == qbs::LoggerInfo ? stdout : stderr; const QString levelTag = logLevelTag(level); TextColor color = TextColorDefault; switch (level) { case qbs::LoggerError: color = TextColorRed; break; case qbs::LoggerWarning: color = TextColorYellow; break; default: break; } fprintfWrapper(color, file, levelTag.toLocal8Bit().constData()); static QHash colorTable = setupColorTable(); fprintfWrapper(colorTable.value(tag, TextColorDefault), file, "%s\n", message.toLocal8Bit().constData()); fflush(file); } void ConsoleLogSink::fprintfWrapper(TextColor color, FILE *file, const char *str, ...) { va_list vl; va_start(vl, str); if (m_coloredOutputEnabled) fprintfColored(color, file, str, vl); else vfprintf(file, str, vl); va_end(vl); } ConsoleLogger &ConsoleLogger::instance(qbs::Settings *settings) { static ConsoleLogger logger(settings); return logger; } void ConsoleLogger::setSettings(qbs::Settings *settings) { if (settings) m_logSink.setColoredOutputEnabled(qbs::Preferences(settings).useColoredOutput()); } ConsoleLogger::ConsoleLogger(qbs::Settings *settings) : Logger(&m_logSink) { setSettings(settings); } qbs-src-1.4.5/src/app/shared/logging/consolelogger.h000066400000000000000000000056071266132464200223670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_LOGSINK_H #define QBS_LOGSINK_H #include "coloredoutput.h" #include namespace qbs { class Settings; } class ConsoleLogSink : public qbs::ILogSink { public: ConsoleLogSink(); void setColoredOutputEnabled(bool enabled) { m_coloredOutputEnabled = enabled; } void setEnabled(bool enabled) { m_enabled = enabled; } private: void doPrintMessage(qbs::LoggerLevel level, const QString &message, const QString &tag); void fprintfWrapper(TextColor color, FILE *file, const char *str, ...); private: bool m_coloredOutputEnabled; bool m_enabled; }; class ConsoleLogger : public qbs::Internal::Logger { public: static ConsoleLogger &instance(qbs::Settings *settings = 0); ConsoleLogSink *logSink() { return &m_logSink; } void setSettings(qbs::Settings *settings); private: ConsoleLogger(qbs::Settings *settings); ConsoleLogSink m_logSink; }; inline qbs::Internal::LogWriter qbsError() { return ConsoleLogger::instance().qbsLog(qbs::LoggerError); } inline qbs::Internal::LogWriter qbsWarning() { return ConsoleLogger::instance().qbsWarning(); } inline qbs::Internal::LogWriter qbsInfo() { return ConsoleLogger::instance().qbsInfo(); } inline qbs::Internal::LogWriter qbsDebug() { return ConsoleLogger::instance().qbsDebug(); } inline qbs::Internal::LogWriter qbsTrace() { return ConsoleLogger::instance().qbsTrace(); } #endif // QBS_LOGSINK_H qbs-src-1.4.5/src/app/shared/logging/logging.pri000066400000000000000000000001621266132464200215050ustar00rootroot00000000000000HEADERS += $$PWD/consolelogger.h $$PWD/coloredoutput.h SOURCES += $$PWD/consolelogger.cpp $$PWD/coloredoutput.cpp qbs-src-1.4.5/src/install_prefix.pri000066400000000000000000000000751266132464200174310ustar00rootroot00000000000000isEmpty(QBS_INSTALL_PREFIX): QBS_INSTALL_PREFIX = /usr/local qbs-src-1.4.5/src/lib/000077500000000000000000000000001266132464200144365ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/000077500000000000000000000000001266132464200160555ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/api/000077500000000000000000000000001266132464200166265ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/api/api.pri000066400000000000000000000022121266132464200201100ustar00rootroot00000000000000include(../../../install_prefix.pri) HEADERS += \ $$PWD/internaljobs.h \ $$PWD/projectdata.h \ $$PWD/runenvironment.h \ $$PWD/jobs.h \ $$PWD/languageinfo.h \ $$PWD/project.h \ $$PWD/project_p.h \ $$PWD/propertymap_p.h \ $$PWD/projectdata_p.h \ $$PWD/rulecommand.h \ $$PWD/rulecommand_p.h SOURCES += \ $$PWD/internaljobs.cpp \ $$PWD/runenvironment.cpp \ $$PWD/projectdata.cpp \ $$PWD/jobs.cpp \ $$PWD/languageinfo.cpp \ $$PWD/project.cpp \ $$PWD/rulecommand.cpp !qbs_no_dev_install { api_headers.files = \ $$PWD/jobs.h \ $$PWD/languageinfo.h \ $$PWD/project.h \ $$PWD/projectdata.h \ $$PWD/rulecommand.h \ $$PWD/runenvironment.h api_headers.path = $${QBS_INSTALL_PREFIX}/include/qbs/api INSTALLS += api_headers } qbs_enable_project_file_updates { HEADERS += \ $$PWD/changeset.h \ $$PWD/projectfileupdater.h \ $$PWD/qmljsrewriter.h SOURCES += \ $$PWD/changeset.cpp \ $$PWD/projectfileupdater.cpp \ $$PWD/qmljsrewriter.cpp DEFINES += QBS_ENABLE_PROJECT_FILE_UPDATES } qbs-src-1.4.5/src/lib/corelib/api/changeset.cpp000066400000000000000000000242541266132464200213020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "changeset.h" #include namespace QbsQmlJS { ChangeSet::ChangeSet() : m_string(0), m_cursor(0), m_error(false) { } ChangeSet::ChangeSet(const QList &operations) : m_string(0), m_cursor(0), m_operationList(operations), m_error(false) { } static bool overlaps(int posA, int lengthA, int posB, int lengthB) { if (lengthB > 0) { return // right edge of B contained in A (posA < posB + lengthB && posA + lengthA >= posB + lengthB) // left edge of B contained in A || (posA <= posB && posA + lengthA > posB) // A contained in B || (posB < posA && posB + lengthB > posA + lengthA); } else { return (posB > posA && posB < posA + lengthA); } } bool ChangeSet::hasOverlap(int pos, int length) { QListIterator i(m_operationList); while (i.hasNext()) { const EditOp &cmd = i.next(); switch (cmd.type) { case EditOp::Replace: if (overlaps(pos, length, cmd.pos1, cmd.length1)) return true; break; case EditOp::Move: if (overlaps(pos, length, cmd.pos1, cmd.length1)) return true; if (cmd.pos2 > pos && cmd.pos2 < pos + length) return true; break; case EditOp::Insert: if (cmd.pos1 > pos && cmd.pos1 < pos + length) return true; break; case EditOp::Remove: if (overlaps(pos, length, cmd.pos1, cmd.length1)) return true; break; case EditOp::Flip: if (overlaps(pos, length, cmd.pos1, cmd.length1)) return true; if (overlaps(pos, length, cmd.pos2, cmd.length2)) return true; break; case EditOp::Copy: if (overlaps(pos, length, cmd.pos1, cmd.length1)) return true; if (cmd.pos2 > pos && cmd.pos2 < pos + length) return true; break; case EditOp::Unset: break; } } return false; } bool ChangeSet::isEmpty() const { return m_operationList.isEmpty(); } QList ChangeSet::operationList() const { return m_operationList; } void ChangeSet::clear() { m_string = 0; m_cursor = 0; m_operationList.clear(); m_error = false; } bool ChangeSet::replace_helper(int pos, int length, const QString &replacement) { if (hasOverlap(pos, length)) m_error = true; EditOp cmd(EditOp::Replace); cmd.pos1 = pos; cmd.length1 = length; cmd.text = replacement; m_operationList += cmd; return !m_error; } bool ChangeSet::move_helper(int pos, int length, int to) { if (hasOverlap(pos, length) || hasOverlap(to, 0) || overlaps(pos, length, to, 0)) m_error = true; EditOp cmd(EditOp::Move); cmd.pos1 = pos; cmd.length1 = length; cmd.pos2 = to; m_operationList += cmd; return !m_error; } bool ChangeSet::insert(int pos, const QString &text) { Q_ASSERT(pos >= 0); if (hasOverlap(pos, 0)) m_error = true; EditOp cmd(EditOp::Insert); cmd.pos1 = pos; cmd.text = text; m_operationList += cmd; return !m_error; } bool ChangeSet::replace(const Range &range, const QString &replacement) { return replace(range.start, range.end, replacement); } bool ChangeSet::remove(const Range &range) { return remove(range.start, range.end); } bool ChangeSet::move(const Range &range, int to) { return move(range.start, range.end, to); } bool ChangeSet::flip(const Range &range1, const Range &range2) { return flip(range1.start, range1.end, range2.start, range2.end); } bool ChangeSet::copy(const Range &range, int to) { return copy(range.start, range.end, to); } bool ChangeSet::replace(int start, int end, const QString &replacement) { return replace_helper(start, end - start, replacement); } bool ChangeSet::remove(int start, int end) { return remove_helper(start, end - start); } bool ChangeSet::move(int start, int end, int to) { return move_helper(start, end - start, to); } bool ChangeSet::flip(int start1, int end1, int start2, int end2) { return flip_helper(start1, end1 - start1, start2, end2 - start2); } bool ChangeSet::copy(int start, int end, int to) { return copy_helper(start, end - start, to); } bool ChangeSet::remove_helper(int pos, int length) { if (hasOverlap(pos, length)) m_error = true; EditOp cmd(EditOp::Remove); cmd.pos1 = pos; cmd.length1 = length; m_operationList += cmd; return !m_error; } bool ChangeSet::flip_helper(int pos1, int length1, int pos2, int length2) { if (hasOverlap(pos1, length1) || hasOverlap(pos2, length2) || overlaps(pos1, length1, pos2, length2)) m_error = true; EditOp cmd(EditOp::Flip); cmd.pos1 = pos1; cmd.length1 = length1; cmd.pos2 = pos2; cmd.length2 = length2; m_operationList += cmd; return !m_error; } bool ChangeSet::copy_helper(int pos, int length, int to) { if (hasOverlap(pos, length) || hasOverlap(to, 0) || overlaps(pos, length, to, 0)) m_error = true; EditOp cmd(EditOp::Copy); cmd.pos1 = pos; cmd.length1 = length; cmd.pos2 = to; m_operationList += cmd; return !m_error; } void ChangeSet::doReplace(const EditOp &replace_helper, QList *replaceList) { Q_ASSERT(replace_helper.type == EditOp::Replace); { QMutableListIterator i(*replaceList); while (i.hasNext()) { EditOp &c = i.next(); if (replace_helper.pos1 <= c.pos1) c.pos1 += replace_helper.text.size(); if (replace_helper.pos1 < c.pos1) c.pos1 -= replace_helper.length1; } } if (m_string) { m_string->replace(replace_helper.pos1, replace_helper.length1, replace_helper.text); } else if (m_cursor) { m_cursor->setPosition(replace_helper.pos1); m_cursor->setPosition(replace_helper.pos1 + replace_helper.length1, QTextCursor::KeepAnchor); m_cursor->insertText(replace_helper.text); } } void ChangeSet::convertToReplace(const EditOp &op, QList *replaceList) { EditOp replace1(EditOp::Replace); EditOp replace2(EditOp::Replace); switch (op.type) { case EditOp::Replace: replaceList->append(op); break; case EditOp::Move: replace1.pos1 = op.pos1; replace1.length1 = op.length1; replaceList->append(replace1); replace2.pos1 = op.pos2; replace2.text = textAt(op.pos1, op.length1); replaceList->append(replace2); break; case EditOp::Insert: replace1.pos1 = op.pos1; replace1.text = op.text; replaceList->append(replace1); break; case EditOp::Remove: replace1.pos1 = op.pos1; replace1.length1 = op.length1; replaceList->append(replace1); break; case EditOp::Flip: replace1.pos1 = op.pos1; replace1.length1 = op.length1; replace1.text = textAt(op.pos2, op.length2); replaceList->append(replace1); replace2.pos1 = op.pos2; replace2.length1 = op.length2; replace2.text = textAt(op.pos1, op.length1); replaceList->append(replace2); break; case EditOp::Copy: replace1.pos1 = op.pos2; replace1.text = textAt(op.pos1, op.length1); replaceList->append(replace1); break; case EditOp::Unset: break; } } bool ChangeSet::hadErrors() { return m_error; } void ChangeSet::apply(QString *s) { m_string = s; apply_helper(); m_string = 0; } void ChangeSet::apply(QTextCursor *textCursor) { m_cursor = textCursor; apply_helper(); m_cursor = 0; } QString ChangeSet::textAt(int pos, int length) { if (m_string) { return m_string->mid(pos, length); } else if (m_cursor) { m_cursor->setPosition(pos); m_cursor->setPosition(pos + length, QTextCursor::KeepAnchor); return m_cursor->selectedText(); } return QString(); } void ChangeSet::apply_helper() { // convert all ops to replace QList replaceList; { while (!m_operationList.isEmpty()) { const EditOp cmd(m_operationList.first()); m_operationList.removeFirst(); convertToReplace(cmd, &replaceList); } } // execute replaces if (m_cursor) m_cursor->beginEditBlock(); while (!replaceList.isEmpty()) { const EditOp cmd(replaceList.first()); replaceList.removeFirst(); doReplace(cmd, &replaceList); } if (m_cursor) m_cursor->endEditBlock(); } } // namespace Internal { qbs-src-1.4.5/src/lib/corelib/api/changeset.h000066400000000000000000000075001266132464200207420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_CHANGESET_H #define QBS_CHANGESET_H #include #include QT_FORWARD_DECLARE_CLASS(QTextCursor) namespace QbsQmlJS { class ChangeSet { public: struct EditOp { enum Type { Unset, Replace, Move, Insert, Remove, Flip, Copy }; EditOp(): type(Unset), pos1(0), pos2(0), length1(0), length2(0) {} EditOp(Type t): type(t), pos1(0), pos2(0), length1(0), length2(0) {} Type type; int pos1; int pos2; int length1; int length2; QString text; }; struct Range { Range() : start(0), end(0) {} Range(int start, int end) : start(start), end(end) {} int start; int end; }; public: ChangeSet(); ChangeSet(const QList &operations); bool isEmpty() const; QList operationList() const; void clear(); bool replace(const Range &range, const QString &replacement); bool remove(const Range &range); bool move(const Range &range, int to); bool flip(const Range &range1, const Range &range2); bool copy(const Range &range, int to); bool replace(int start, int end, const QString &replacement); bool remove(int start, int end); bool move(int start, int end, int to); bool flip(int start1, int end1, int start2, int end2); bool copy(int start, int end, int to); bool insert(int pos, const QString &text); bool hadErrors(); void apply(QString *s); void apply(QTextCursor *textCursor); private: // length-based API. bool replace_helper(int pos, int length, const QString &replacement); bool move_helper(int pos, int length, int to); bool remove_helper(int pos, int length); bool flip_helper(int pos1, int length1, int pos2, int length2); bool copy_helper(int pos, int length, int to); bool hasOverlap(int pos, int length); QString textAt(int pos, int length); void doReplace(const EditOp &replace, QList *replaceList); void convertToReplace(const EditOp &op, QList *replaceList); void apply_helper(); private: QString *m_string; QTextCursor *m_cursor; QList m_operationList; bool m_error; }; } // namespace QbsQmlJS #endif // Include guard. qbs-src-1.4.5/src/lib/corelib/api/internaljobs.cpp000066400000000000000000000326231266132464200220320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "internaljobs.h" #include "jobs.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class JobObserver : public ProgressObserver { public: JobObserver(InternalJob *job) : m_canceled(false), m_job(job), m_timedLogger(0) { } ~JobObserver() { delete m_timedLogger; } void cancel() { m_canceled = true; } private: void initialize(const QString &task, int maximum) { QBS_ASSERT(!m_timedLogger, delete m_timedLogger); m_timedLogger = new TimedActivityLogger(m_job->logger(), task, QString(), m_job->timed() ? LoggerInfo : LoggerDebug, m_job->timed()); m_value = 0; m_maximum = maximum; m_canceled = false; emit m_job->newTaskStarted(task, maximum, m_job); } void setMaximum(int maximum) { m_maximum = maximum; emit m_job->totalEffortChanged(maximum, m_job); } void setProgressValue(int value) { //QBS_ASSERT(value >= m_value, qDebug("old value = %d, new value = %d", m_value, value)); //QBS_ASSERT(value <= m_maximum, qDebug("value = %d, maximum = %d", value, m_maximum)); m_value = value; if (value == m_maximum) { delete m_timedLogger; m_timedLogger = 0; } emit m_job->taskProgress(value, m_job); } int progressValue() { return m_value; } int maximum() const { return m_maximum; } bool canceled() const { return m_canceled; } int m_value; int m_maximum; bool m_canceled; InternalJob * const m_job; TimedActivityLogger *m_timedLogger; }; InternalJob::InternalJob(const Logger &logger, QObject *parent) : QObject(parent) , m_observer(new JobObserver(this)) , m_ownsObserver(true) , m_logger(logger) , m_timed(false) { } InternalJob::~InternalJob() { if (m_ownsObserver) delete m_observer; } void InternalJob::cancel() { m_observer->cancel(); } void InternalJob::shareObserverWith(InternalJob *otherJob) { if (m_ownsObserver) { delete m_observer; m_ownsObserver = false; } m_observer = otherJob->m_observer; } void InternalJob::storeBuildGraph(const TopLevelProjectPtr &project) { try { doSanityChecks(project, logger()); project->store(logger()); } catch (const ErrorInfo &error) { logger().printWarning(error); } } /** * Construct a new thread wrapper for a synchronous job. * This object takes over ownership of the synchronous job. */ InternalJobThreadWrapper::InternalJobThreadWrapper(InternalJob *synchronousJob, QObject *parent) : InternalJob(synchronousJob->logger(), parent) , m_job(synchronousJob) , m_running(false) { synchronousJob->shareObserverWith(this); m_job->moveToThread(&m_thread); connect(m_job, SIGNAL(finished(Internal::InternalJob*)), SLOT(handleFinished())); connect(m_job, SIGNAL(newTaskStarted(QString,int,Internal::InternalJob*)), SIGNAL(newTaskStarted(QString,int,Internal::InternalJob*))); connect(m_job, SIGNAL(taskProgress(int,Internal::InternalJob*)), SIGNAL(taskProgress(int,Internal::InternalJob*))); connect(m_job, SIGNAL(totalEffortChanged(int,Internal::InternalJob*)), SIGNAL(totalEffortChanged(int,Internal::InternalJob*))); m_job->connect(this, SIGNAL(startRequested()), SLOT(start())); } InternalJobThreadWrapper::~InternalJobThreadWrapper() { if (m_running) { QEventLoop loop; loop.connect(m_job, SIGNAL(finished(Internal::InternalJob*)), SLOT(quit())); cancel(); loop.exec(); } m_thread.quit(); m_thread.wait(); delete m_job; } void InternalJobThreadWrapper::start() { setTimed(m_job->timed()); m_thread.start(); m_running = true; emit startRequested(); } void InternalJobThreadWrapper::handleFinished() { m_running = false; setError(m_job->error()); emit finished(this); } InternalSetupProjectJob::InternalSetupProjectJob(const Logger &logger) : InternalJob(logger) { } InternalSetupProjectJob::~InternalSetupProjectJob() { } void InternalSetupProjectJob::init(const TopLevelProjectPtr &existingProject, const SetupProjectParameters ¶meters) { m_existingProject = existingProject; m_parameters = parameters; setTimed(parameters.logElapsedTime()); } void InternalSetupProjectJob::reportError(const ErrorInfo &error) { setError(error); emit finished(this); } TopLevelProjectPtr InternalSetupProjectJob::project() const { return m_newProject; } void InternalSetupProjectJob::start() { BuildGraphLocker *bgLocker = m_existingProject ? m_existingProject->bgLocker : 0; try { const ErrorInfo err = m_parameters.expandBuildConfiguration(); if (err.hasError()) throw err; const QString projectId = TopLevelProject::deriveId(m_parameters.topLevelProfile(), m_parameters.finalBuildConfigurationTree()); const QString buildDir = TopLevelProject::deriveBuildDirectory(m_parameters.buildRoot(), projectId); if (m_existingProject && m_existingProject->buildDirectory != buildDir) m_existingProject.clear(); if (!m_existingProject) { bgLocker = new BuildGraphLocker(ProjectBuildData::deriveBuildGraphFilePath(buildDir, projectId), logger()); } execute(); if (m_existingProject) m_existingProject->bgLocker = 0; m_newProject->bgLocker = bgLocker; } catch (const ErrorInfo &error) { m_newProject.clear(); setError(error); if (!m_existingProject) delete bgLocker; } emit finished(this); } void InternalSetupProjectJob::execute() { RulesEvaluationContextPtr evalContext(new RulesEvaluationContext(logger())); evalContext->setObserver(observer()); switch (m_parameters.restoreBehavior()) { case SetupProjectParameters::ResolveOnly: resolveProjectFromScratch(evalContext->engine()); resolveBuildDataFromScratch(evalContext); break; case SetupProjectParameters::RestoreOnly: m_newProject = restoreProject(evalContext).loadedProject; break; case SetupProjectParameters::RestoreAndTrackChanges: { const BuildGraphLoadResult loadResult = restoreProject(evalContext); m_newProject = loadResult.newlyResolvedProject; if (!m_newProject) m_newProject = loadResult.loadedProject; if (!m_newProject) { resolveProjectFromScratch(evalContext->engine()); resolveBuildDataFromScratch(evalContext); } else { QBS_CHECK(m_newProject->buildData); } break; } } if (!m_parameters.dryRun()) storeBuildGraph(m_newProject); // The evalutation context cannot be re-used for building, which runs in a different thread. m_newProject->buildData->evaluationContext.clear(); } void InternalSetupProjectJob::resolveProjectFromScratch(ScriptEngine *engine) { Loader loader(engine, logger()); loader.setSearchPaths(m_parameters.searchPaths()); loader.setProgressObserver(observer()); m_newProject = loader.loadProject(m_parameters); QBS_CHECK(m_newProject); } void InternalSetupProjectJob::resolveBuildDataFromScratch(const RulesEvaluationContextPtr &evalContext) { TimedActivityLogger resolveLogger(logger(), QLatin1String("Resolving build project")); BuildDataResolver(logger()).resolveBuildData(m_newProject, evalContext); } BuildGraphLoadResult InternalSetupProjectJob::restoreProject(const RulesEvaluationContextPtr &evalContext) { BuildGraphLoader bgLoader(m_parameters.adjustedEnvironment(), logger()); const BuildGraphLoadResult loadResult = bgLoader.load(m_existingProject, m_parameters, evalContext); return loadResult; } BuildGraphTouchingJob::BuildGraphTouchingJob(const Logger &logger, QObject *parent) : InternalJob(logger, parent), m_dryRun(false) { } BuildGraphTouchingJob::~BuildGraphTouchingJob() { } void BuildGraphTouchingJob::setup(const TopLevelProjectPtr &project, const QList &products, bool dryRun) { m_project = project; m_products = products; m_dryRun = dryRun; } void BuildGraphTouchingJob::storeBuildGraph() { if (!m_dryRun && !error().isInternalError()) InternalJob::storeBuildGraph(m_project); } InternalBuildJob::InternalBuildJob(const Logger &logger, QObject *parent) : BuildGraphTouchingJob(logger, parent), m_executor(0) { } void InternalBuildJob::build(const TopLevelProjectPtr &project, const QList &products, const BuildOptions &buildOptions) { setup(project, products, buildOptions.dryRun()); setTimed(buildOptions.logElapsedTime()); m_executor = new Executor(logger()); m_executor->setProject(project); m_executor->setProducts(products); m_executor->setBuildOptions(buildOptions); m_executor->setProgressObserver(observer()); QThread * const executorThread = new QThread(this); m_executor->moveToThread(executorThread); connect(m_executor, SIGNAL(reportCommandDescription(QString,QString)), this, SIGNAL(reportCommandDescription(QString,QString))); connect(m_executor, SIGNAL(reportProcessResult(qbs::ProcessResult)), this, SIGNAL(reportProcessResult(qbs::ProcessResult))); connect(executorThread, SIGNAL(started()), m_executor, SLOT(build())); connect(m_executor, SIGNAL(finished()), SLOT(handleFinished())); connect(m_executor, SIGNAL(destroyed()), executorThread, SLOT(quit())); connect(executorThread, SIGNAL(finished()), this, SLOT(emitFinished())); executorThread->start(); } void InternalBuildJob::handleFinished() { setError(m_executor->error()); project()->buildData->evaluationContext.clear(); storeBuildGraph(); m_executor->deleteLater(); } void InternalBuildJob::emitFinished() { emit finished(this); } InternalCleanJob::InternalCleanJob(const Logger &logger, QObject *parent) : BuildGraphTouchingJob(logger, parent) { } void InternalCleanJob::init(const TopLevelProjectPtr &project, const QList &products, const CleanOptions &options) { setup(project, products, options.dryRun()); setTimed(options.logElapsedTime()); m_options = options; } void InternalCleanJob::start() { try { ArtifactCleaner cleaner(logger(), observer()); cleaner.cleanup(project(), products(), m_options); } catch (const ErrorInfo &error) { setError(error); } storeBuildGraph(); emit finished(this); } InternalInstallJob::InternalInstallJob(const Logger &logger) : InternalJob(logger) { } InternalInstallJob::~InternalInstallJob() { } void InternalInstallJob::init(const TopLevelProjectPtr &project, const QList &products, const InstallOptions &options) { m_project = project; m_products = products; m_options = options; setTimed(options.logElapsedTime()); } void InternalInstallJob::start() { try { ProductInstaller(m_project, m_products, m_options, observer(), logger()).install(); } catch (const ErrorInfo &error) { setError(error); } emit finished(this); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/api/internaljobs.h000066400000000000000000000143101266132464200214700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_INTERNALJOBS_H #define QBS_INTERNALJOBS_H #include #include #include #include #include #include #include #include #include #include #include namespace qbs { class ProcessResult; class Settings; namespace Internal { class BuildGraphLoadResult; class BuildGraphLocker; class Executor; class JobObserver; class ScriptEngine; class InternalJob : public QObject { Q_OBJECT friend class JobObserver; public: ~InternalJob(); void cancel(); ErrorInfo error() const { return m_error; } void setError(const ErrorInfo &error) { m_error = error; } Logger logger() const { return m_logger; } bool timed() const { return m_timed; } void shareObserverWith(InternalJob *otherJob); protected: explicit InternalJob(const Logger &logger, QObject *parent = 0); JobObserver *observer() const { return m_observer; } void setTimed(bool timed) { m_timed = timed; } void storeBuildGraph(const TopLevelProjectPtr &project); signals: void finished(Internal::InternalJob *job); void newTaskStarted(const QString &description, int totalEffort, Internal::InternalJob *job); void totalEffortChanged(int totalEffort, Internal::InternalJob *job); void taskProgress(int value, Internal::InternalJob *job); private: ErrorInfo m_error; JobObserver *m_observer; bool m_ownsObserver; Logger m_logger; bool m_timed; }; class InternalJobThreadWrapper : public InternalJob { Q_OBJECT public: InternalJobThreadWrapper(InternalJob *synchronousJob, QObject *parent = 0); ~InternalJobThreadWrapper(); void start(); InternalJob *synchronousJob() const { return m_job; } signals: void startRequested(); private slots: void handleFinished(); private: QThread m_thread; InternalJob *m_job; bool m_running; }; class InternalSetupProjectJob : public InternalJob { Q_OBJECT public: InternalSetupProjectJob(const Logger &logger); ~InternalSetupProjectJob(); void init(const TopLevelProjectPtr &existingProject, const SetupProjectParameters ¶meters); void reportError(const ErrorInfo &error); TopLevelProjectPtr project() const; private slots: void start(); private: void resolveProjectFromScratch(Internal::ScriptEngine *engine); void resolveBuildDataFromScratch(const RulesEvaluationContextPtr &evalContext); BuildGraphLoadResult restoreProject(const RulesEvaluationContextPtr &evalContext); void execute(); TopLevelProjectPtr m_existingProject; TopLevelProjectPtr m_newProject; SetupProjectParameters m_parameters; }; class BuildGraphTouchingJob : public InternalJob { Q_OBJECT public: const QList &products() const { return m_products; } const TopLevelProjectPtr &project() const { return m_project; } signals: void reportCommandDescription(const QString &highlight, const QString &message); void reportProcessResult(const qbs::ProcessResult &result); protected: BuildGraphTouchingJob(const Logger &logger, QObject *parent = 0); ~BuildGraphTouchingJob(); void setup(const TopLevelProjectPtr &project, const QList &products, bool dryRun); void storeBuildGraph(); private: TopLevelProjectPtr m_project; QList m_products; bool m_dryRun; }; class InternalBuildJob : public BuildGraphTouchingJob { Q_OBJECT public: InternalBuildJob(const Logger &logger, QObject *parent = 0); void build(const TopLevelProjectPtr &project, const QList &products, const BuildOptions &buildOptions); private slots: void handleFinished(); void emitFinished(); private: Executor *m_executor; }; class InternalCleanJob : public BuildGraphTouchingJob { Q_OBJECT public: InternalCleanJob(const Logger &logger, QObject *parent = 0); void init(const TopLevelProjectPtr &project, const QList &products, const CleanOptions &options); private slots: void start(); private: CleanOptions m_options; }; class InternalInstallJob : public InternalJob { Q_OBJECT public: InternalInstallJob(const Logger &logger); ~InternalInstallJob(); void init(const TopLevelProjectPtr &project, const QList &products, const InstallOptions &options); private slots: void start(); private: TopLevelProjectPtr m_project; QList m_products; InstallOptions m_options; }; } // namespace Internal } // namespace qbs #endif // QBS_INTERNALJOBS_H qbs-src-1.4.5/src/lib/corelib/api/jobs.cpp000066400000000000000000000316161266132464200202760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "jobs.h" #include "internaljobs.h" #include "project_p.h" #include #include #include namespace qbs { using namespace Internal; /*! * \class AbstractJob * \brief The \c AbstractJob class represents an operation relating to a \c Project. * Concrete child classes of \c AbstractJob are created by factory functions in the \c Project * class. The respective objects represent an operation that is started automatically * and is considered "running" until the \c finished() signal has been emitted. Afterwards, * callers can find out whether the operation was successful by calling \c hasError(). While * the operation is going on, progress information is being provided via \c taskStarted() and * \c taskProgress. * Note that though a job is being started automatically by its factory function, you are guaranteed * to recevieve all signals it emits if you connect to it right after getting the object from the * creating function. * \sa Project */ /*! * \enum AbstractJob::State * This enum type specifies which states a job can be in. * \value StateRunning The respective operation is ongoing. * \value StateCanceling The job has been requested to cancel via \c AbstractJob::cancel(), * but the \c AbstractJob::finished() signal has not been emitted yet. * \value StateFinished The operation has finished and the \c AbstractJob::finished() signal * has been emitted. */ /*! * \fn AbstractJob::State AbstractJob::state() const * \brief Returns the current state of the operation. */ /*! * \fn bool AbstractJob::hasError() const * \brief Returns true if the operation has finished with an error, otherwise returns false. * This function should not be called before the \c finished() signal has been emitted. */ /*! * \fn void AbstractJob::taskStarted(const QString &description, int maximumProgressValue, qbs::AbstractJob *job) * \brief Indicates that a new task has been started. * The \a description parameter is a string intended for presentation to a user. * The \a maximumProgressValue parameter indicates the maximum value to which subsequent values of * \c taskProgress() will go. * This signal is typically emitted exactly once for a job that finishes successfully. However, * operations might emit it several times if they are made up of subtasks whose overall effort * cannot be determined in advance. * \sa AbstractJob::taskProgress() */ /*! * \fn void taskProgress(int newProgressValue, qbs::AbstractJob *job) * \brief Indicates progress in executing the operation. * The \a newProgressValue parameter represents the current progress. It is always greater than * zero, strictly increasing and goes up to the \c maximumProgressValue argument of the last * call to \c taskStarted(). * \sa AbstractJob::taskStarted() */ /*! * \fn void finished(bool success, qbs::AbstractJob *job) * \brief Indicates that the operation has finished. * Check the \a success parameter to find out whether everything went fine or an error occurred. */ AbstractJob::AbstractJob(InternalJob *internalJob, QObject *parent) : QObject(parent), m_internalJob(internalJob) { m_internalJob->setParent(this); connect(m_internalJob, SIGNAL(newTaskStarted(QString,int,Internal::InternalJob*)), SLOT(handleTaskStarted(QString,int)), Qt::QueuedConnection); connect(m_internalJob, SIGNAL(totalEffortChanged(int,Internal::InternalJob*)), SLOT(handleTotalEffortChanged(int))); connect(m_internalJob, SIGNAL(taskProgress(int,Internal::InternalJob*)), SLOT(handleTaskProgress(int)), Qt::QueuedConnection); connect(m_internalJob, SIGNAL(finished(Internal::InternalJob*)), SLOT(handleFinished())); m_state = StateRunning; } bool AbstractJob::lockProject(const TopLevelProjectPtr &project) { // The API is not thread-safe, so we don't need a mutex here, as the API requests come in // synchronously. if (project->locked) { internalJob()->setError(tr("Cannot start a job while another one is in progress.")); QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection, Q_ARG(bool, false), Q_ARG(qbs::AbstractJob *, this)); return false; } project->locked = true; m_project = project; return true; } void AbstractJob::unlockProject() { if (!m_project) return; QBS_ASSERT(m_project->locked, return); m_project->locked = false; } /*! * \brief Destroys the object, canceling the operation if necessary. */ AbstractJob::~AbstractJob() { m_internalJob->disconnect(this); cancel(); } /*! * \brief Returns the error which caused this operation to fail, if it did fail. */ ErrorInfo AbstractJob::error() const { return internalJob()->error(); } /*! * \brief Cancels this job. * Note that the job might not finish immediately. If you need to make sure it has actually * finished, wait for the \c finished() signal. * \sa AbstractJob::finished(AbstractJob *); */ void AbstractJob::cancel() { if (m_state != StateRunning) return; m_state = StateCanceling; internalJob()->cancel(); } void AbstractJob::handleTaskStarted(const QString &description, int maximumProgressValue) { emit taskStarted(description, maximumProgressValue, this); } void AbstractJob::handleTotalEffortChanged(int totalEffort) { emit totalEffortChanged(totalEffort, this); } void AbstractJob::handleTaskProgress(int newProgressValue) { emit taskProgress(newProgressValue, this); } void AbstractJob::handleFinished() { QBS_ASSERT(m_state != StateFinished, return); finish(); m_state = StateFinished; unlockProject(); emit finished(!error().hasError(), this); } /*! * \class SetupProjectJob * \brief The \c SetupProjectJob class represents an operation that reads a qbs project file and * creates a \c Project object from it. * Note that this job can emit the \c taskStarted() signal more than once. * \sa AbstractJob::taskStarted() */ SetupProjectJob::SetupProjectJob(const Logger &logger, QObject *parent) : AbstractJob(new InternalJobThreadWrapper(new InternalSetupProjectJob(logger)), parent) { } /*! * \brief Returns the project resulting from this operation. * Note that the result is undefined if the job did not finish successfully. * \sa AbstractJob::hasError() */ Project SetupProjectJob::project() const { const InternalJobThreadWrapper * const wrapper = qobject_cast(internalJob()); const InternalSetupProjectJob * const job = qobject_cast(wrapper->synchronousJob()); return Project(job->project(), job->logger()); } void SetupProjectJob::resolve(const Project &existingProject, const SetupProjectParameters ¶meters) { m_existingProject = existingProject; const TopLevelProjectPtr &existingInternalProject = existingProject.d ? existingProject.d->internalProject : TopLevelProjectPtr(); if (existingInternalProject && !lockProject(existingInternalProject)) return; InternalJobThreadWrapper * const wrapper = qobject_cast(internalJob()); InternalSetupProjectJob * const job = qobject_cast(wrapper->synchronousJob()); job->init(existingInternalProject, parameters); wrapper->start(); } void SetupProjectJob::reportError(const ErrorInfo &error) { InternalJobThreadWrapper * const wrapper = qobject_cast(internalJob()); InternalSetupProjectJob * const job = qobject_cast(wrapper->synchronousJob()); job->reportError(error); } void SetupProjectJob::finish() { // If the new project was successfully created, invalidate the existing one. // The invariant is that there must always be at most one valid Project object // for the same build directory, so that exclusive ownership of the build graph lock // is ensured. // We also need to invalidate the project if an error has occurred after the build data was // already transferred. if (m_existingProject.isValid() && (!error().hasError() || !m_existingProject.d->internalProject->buildData)) { m_existingProject.d->internalProject.clear(); } } /*! * \class ProcessResult * \brief The \c ProcessResult class represents the result of one external program run by Qbs. * * The \c ProcessResult class represents all the information on one external program that was * run by Qbs. It includes the command line used to start the program, the working directory * as well as output and exit codes. */ /*! * \class BuildJob * \brief The \c BuildJob class represents a build operation. */ /*! * \fn void BuildJob::reportCommandDescription(const QString &highlight, const QString &message) * \brief Signals that a new command is being worked on. * The \a highlight parameter is used to decide on the colors and font styles to be used to * print the message. * The \a message parameter is the localized message to print. */ /*! * \fn void BuildJob::reportProcessResult(const qbs::ProcessResult &result) * \brief Signals that an external command has finished. * The \a result parameter contains all details on the process that was run by Qbs. */ BuildJob::BuildJob(const Logger &logger, QObject *parent) : AbstractJob(new InternalBuildJob(logger), parent) { InternalBuildJob *job = static_cast(internalJob()); connect(job, SIGNAL(reportCommandDescription(QString,QString)), this, SIGNAL(reportCommandDescription(QString,QString))); connect(job, SIGNAL(reportProcessResult(qbs::ProcessResult)), this, SIGNAL(reportProcessResult(qbs::ProcessResult))); } void BuildJob::build(const TopLevelProjectPtr &project, const QList &products, const BuildOptions &options) { if (!lockProject(project)) return; qobject_cast(internalJob())->build(project, products, options); } /*! * \class CleanJob * \brief The \c CleanJob class represents an operation removing build artifacts. */ CleanJob::CleanJob(const Logger &logger, QObject *parent) : AbstractJob(new InternalJobThreadWrapper(new InternalCleanJob(logger)), parent) { } void CleanJob::clean(const TopLevelProjectPtr &project, const QList &products, const qbs::CleanOptions &options) { if (!lockProject(project)) return; InternalJobThreadWrapper * wrapper = qobject_cast(internalJob()); qobject_cast(wrapper->synchronousJob())->init(project, products, options); wrapper->start(); } /*! * \class InstallJob * \brief The \c InstallJob class represents an operation installing files. */ InstallJob::InstallJob(const Logger &logger, QObject *parent) : AbstractJob(new InternalJobThreadWrapper(new InternalInstallJob(logger)), parent) { } void InstallJob::install(const TopLevelProjectPtr &project, const QList &products, const InstallOptions &options) { if (!lockProject(project)) return; InternalJobThreadWrapper *wrapper = qobject_cast(internalJob()); InternalInstallJob *installJob = qobject_cast(wrapper->synchronousJob()); installJob->init(project, products, options); wrapper->start(); } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/api/jobs.h000066400000000000000000000113661266132464200177430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_JOBS_H #define QBS_JOBS_H #include "project.h" #include "../language/forward_decls.h" #include "../tools/error.h" #include "../tools/qbs_export.h" #include #include #include namespace qbs { class BuildOptions; class CleanOptions; class InstallOptions; class ProcessResult; class SetupProjectParameters; namespace Internal { class InternalJob; class Logger; class ProjectPrivate; } // namespace Internal class Project; class QBS_EXPORT AbstractJob : public QObject { Q_OBJECT public: ~AbstractJob(); enum State { StateRunning, StateCanceling, StateFinished }; State state() const { return m_state; } ErrorInfo error() const; public slots: void cancel(); protected: AbstractJob(Internal::InternalJob *internalJob, QObject *parent); Internal::InternalJob *internalJob() const { return m_internalJob; } bool lockProject(const Internal::TopLevelProjectPtr &project); signals: void taskStarted(const QString &description, int maximumProgressValue, qbs::AbstractJob *job); void totalEffortChanged(int totalEffort, qbs::AbstractJob *job); void taskProgress(int newProgressValue, qbs::AbstractJob *job); void finished(bool success, qbs::AbstractJob *job); private slots: void handleTaskStarted(const QString &description, int maximumProgressValue); void handleTotalEffortChanged(int totalEffort); void handleTaskProgress(int newProgressValue); void handleFinished(); private: void unlockProject(); virtual void finish() { } Internal::InternalJob * const m_internalJob; Internal::TopLevelProjectPtr m_project; State m_state; }; class QBS_EXPORT SetupProjectJob : public AbstractJob { Q_OBJECT friend class Project; public: Project project() const; private: SetupProjectJob(const Internal::Logger &logger, QObject *parent); void resolve(const Project &existingProject, const SetupProjectParameters ¶meters); void reportError(const ErrorInfo &error); void finish(); Project m_existingProject; }; class QBS_EXPORT BuildJob : public AbstractJob { Q_OBJECT friend class Internal::ProjectPrivate; signals: void reportCommandDescription(const QString &highlight, const QString &message); void reportProcessResult(const qbs::ProcessResult &result); private: BuildJob(const Internal::Logger &logger, QObject *parent); void build(const Internal::TopLevelProjectPtr &project, const QList &products, const BuildOptions &options); }; class QBS_EXPORT CleanJob : public AbstractJob { Q_OBJECT friend class Internal::ProjectPrivate; private: CleanJob(const Internal::Logger &logger, QObject *parent); void clean(const Internal::TopLevelProjectPtr &project, const QList &products, const CleanOptions &options); }; class QBS_EXPORT InstallJob : public AbstractJob { Q_OBJECT friend class Internal::ProjectPrivate; private: InstallJob(const Internal::Logger &logger, QObject *parent); void install(const Internal::TopLevelProjectPtr &project, const QList &products, const InstallOptions &options); }; } // namespace qbs #endif // QBS_JOBS_H qbs-src-1.4.5/src/lib/corelib/api/languageinfo.cpp000066400000000000000000000106261266132464200217760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "languageinfo.h" #include #include namespace qbs { LanguageInfo::LanguageInfo() { } QByteArray LanguageInfo::qmlTypeInfo() { const Internal::BuiltinDeclarations &builtins = Internal::BuiltinDeclarations::instance(); // Header: QByteArray result; result.append("import QtQuick.tooling 1.0\n\n"); result.append("// This file describes the plugin-supplied types contained in the library.\n"); result.append("// It is used for QML tooling purposes only.\n\n"); result.append("Module {\n"); // Individual Components: foreach (const QString &typeName, builtins.allTypeNames()) { QByteArray utf8TypeName = typeName.toUtf8(); result.append(" Component {\n"); result.append(QByteArray(" name: \"") + utf8TypeName + QByteArray("\"\n")); result.append(" exports: [ \"qbs/"); result.append(utf8TypeName); result.append(" "); result.append(builtins.languageVersion().toString().toUtf8()); result.append("\" ]\n"); result.append(" prototype: \"QQuickItem\"\n"); Internal::ItemDeclaration itemDecl = builtins.declarationsForType(typeName); foreach (const Internal::PropertyDeclaration &property, itemDecl.properties()) { result.append(" Property { name: \""); result.append(property.name().toUtf8()); result.append("\"; "); switch (property.type()) { case qbs::Internal::PropertyDeclaration::UnknownType: result.append("type: \"unknown\""); break; case qbs::Internal::PropertyDeclaration::Boolean: result.append("type: \"bool\""); break; case qbs::Internal::PropertyDeclaration::Integer: result.append("type: \"int\""); break; case qbs::Internal::PropertyDeclaration::Path: result.append("type: \"string\""); break; case qbs::Internal::PropertyDeclaration::PathList: result.append("type: \"string\"; isList: true"); break; case qbs::Internal::PropertyDeclaration::String: result.append("type: \"string\""); break; case qbs::Internal::PropertyDeclaration::StringList: result.append("type: \"string\"; isList: true"); break; case qbs::Internal::PropertyDeclaration::Variant: result.append("type: \"QVariant\""); break; case qbs::Internal::PropertyDeclaration::Verbatim: result.append("type: \"string\""); break; } result.append(" }\n"); // Property } result.append(" }\n"); // Component } // Footer: result.append("}\n"); // Module return result; } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/api/languageinfo.h000066400000000000000000000034071266132464200214420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_LANGUAGEINFO_H #define QBS_LANGUAGEINFO_H #include "../tools/qbs_export.h" #include namespace qbs { class QBS_EXPORT LanguageInfo { public: LanguageInfo(); QByteArray qmlTypeInfo(); }; } // namespace qbs #endif // QBS_LANGUAGEINFO_H qbs-src-1.4.5/src/lib/corelib/api/project.cpp000066400000000000000000001447211266132464200210110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "project.h" #include "project_p.h" #ifdef QBS_ENABLE_PROJECT_FILE_UPDATES #include "projectfileupdater.h" #endif #include "internaljobs.h" #include "jobs.h" #include "projectdata_p.h" #include "propertymap_p.h" #include "rulecommand_p.h" #include "runenvironment.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { static bool pluginsLoaded = false; static QMutex pluginsLoadedMutex; static void loadPlugins(const QStringList &_pluginPaths, const Logger &logger) { QMutexLocker locker(&pluginsLoadedMutex); if (pluginsLoaded) return; QStringList pluginPaths; foreach (const QString &pluginPath, _pluginPaths) { if (!FileInfo::exists(pluginPath)) { logger.qbsWarning() << Tr::tr("Plugin path '%1' does not exist.") .arg(QDir::toNativeSeparators(pluginPath)); } else { pluginPaths << pluginPath; } } ScannerPluginManager::instance()->loadPlugins(pluginPaths, logger); qRegisterMetaType("qbs::ErrorInfo"); qRegisterMetaType("qbs::ProcessResult"); qRegisterMetaType("Internal::InternalJob *"); qRegisterMetaType("qbs::AbstractJob *"); pluginsLoaded = true; } ProjectData ProjectPrivate::projectData() { m_projectData = ProjectData(); retrieveProjectData(m_projectData, internalProject); m_projectData.d->buildDir = internalProject->buildDirectory; return m_projectData; } static void addDependencies(QList &products) { for (int i = 0; i < products.count(); ++i) { const ResolvedProductPtr &product = products.at(i); foreach (const ResolvedProductPtr &dependency, product->dependencies) { if (!products.contains(dependency)) products << dependency; } } } BuildJob *ProjectPrivate::buildProducts(const QList &products, const BuildOptions &options, bool needsDepencencyResolving, QObject *jobOwner) { QList productsToBuild = products; if (needsDepencencyResolving) addDependencies(productsToBuild); BuildJob * const job = new BuildJob(logger, jobOwner); job->build(internalProject, productsToBuild, options); return job; } CleanJob *ProjectPrivate::cleanProducts(const QList &products, const CleanOptions &options, QObject *jobOwner) { CleanJob * const job = new CleanJob(logger, jobOwner); job->clean(internalProject, products, options); return job; } InstallJob *ProjectPrivate::installProducts(const QList &products, const InstallOptions &options, bool needsDepencencyResolving, QObject *jobOwner) { QList productsToInstall = products; if (needsDepencencyResolving) addDependencies(productsToInstall); InstallJob * const job = new InstallJob(logger, jobOwner); job->install(internalProject, productsToInstall, options); return job; } QList ProjectPrivate::internalProducts(const QList &products) const { QList internalProducts; foreach (const ProductData &product, products) { if (product.isEnabled()) internalProducts << internalProduct(product); } return internalProducts; } static QList enabledInternalProducts(const ResolvedProjectConstPtr &project, bool includingNonDefault) { QList products; foreach (const ResolvedProductPtr &p, project->products) { if (p->enabled && (includingNonDefault || p->builtByDefault())) products << p; } foreach (const ResolvedProjectConstPtr &subProject, project->subProjects) products << enabledInternalProducts(subProject, includingNonDefault); return products; } QList ProjectPrivate::allEnabledInternalProducts(bool includingNonDefault) const { return enabledInternalProducts(internalProject, includingNonDefault); } static ResolvedProductPtr internalProductForProject(const ResolvedProjectConstPtr &project, const ProductData &product) { foreach (const ResolvedProductPtr &resolvedProduct, project->products) { if (product.name() == resolvedProduct->name && product.profile() == resolvedProduct->profile) { return resolvedProduct; } } foreach (const ResolvedProjectConstPtr &subProject, project->subProjects) { const ResolvedProductPtr &p = internalProductForProject(subProject, product); if (p) return p; } return ResolvedProductPtr(); } ResolvedProductPtr ProjectPrivate::internalProduct(const ProductData &product) const { return internalProductForProject(internalProject, product); } ProductData ProjectPrivate::findProductData(const ProductData &product) const { foreach (const ProductData &p, m_projectData.allProducts()) { if (p.name() == product.name() && p.profile() == product.profile()) return p; } return ProductData(); } QList ProjectPrivate::findProductsByName(const QString &name) const { QList list; foreach (const ProductData &p, m_projectData.allProducts()) { if (p.name() == name) list << p; } return list; } GroupData ProjectPrivate::findGroupData(const ProductData &product, const QString &groupName) const { foreach (const GroupData &g, product.groups()) { if (g.name() == groupName) return g; } return GroupData(); } GroupData ProjectPrivate::createGroupDataFromGroup(const GroupPtr &resolvedGroup) { GroupData group; group.d->name = resolvedGroup->name; group.d->location = resolvedGroup->location; foreach (const SourceArtifactConstPtr &sa, resolvedGroup->files) group.d->sourceArtifacts << createApiSourceArtifact(sa); if (resolvedGroup->wildcards) { foreach (const SourceArtifactConstPtr &sa, resolvedGroup->wildcards->files) group.d->sourceArtifactsFromWildcards << createApiSourceArtifact(sa); } qSort(group.d->sourceArtifacts); qSort(group.d->sourceArtifactsFromWildcards); group.d->properties.d->m_map = resolvedGroup->properties; group.d->isEnabled = resolvedGroup->enabled; group.d->isValid = true; return group; } SourceArtifact ProjectPrivate::createApiSourceArtifact(const SourceArtifactConstPtr &sa) { SourceArtifact saApi; saApi.d->isValid = true; saApi.d->filePath = sa->absoluteFilePath; saApi.d->fileTags = sa->fileTags.toStringList(); return saApi; } #ifdef QBS_ENABLE_PROJECT_FILE_UPDATES void ProjectPrivate::addGroup(const ProductData &product, const QString &groupName) { if (groupName.isEmpty()) throw ErrorInfo(Tr::tr("Group has an empty name.")); if (!product.isValid()) throw ErrorInfo(Tr::tr("Product is invalid.")); QList products = findProductsByName(product.name()); if (products.isEmpty()) throw ErrorInfo(Tr::tr("Product '%1' does not exist.").arg(product.name())); const QList resolvedProducts = internalProducts(products); QBS_CHECK(products.count() == resolvedProducts.count()); foreach (const GroupPtr &resolvedGroup, resolvedProducts.first()->groups) { if (resolvedGroup->name == groupName) { throw ErrorInfo(Tr::tr("Group '%1' already exists in product '%2'.") .arg(groupName, product.name()), resolvedGroup->location); } } ProjectFileGroupInserter groupInserter(products.first(), groupName); groupInserter.apply(); m_projectData.d.detach(); // The data we already gave out must stay as it is. updateInternalCodeLocations(internalProject, groupInserter.itemPosition(), groupInserter.lineOffset()); updateExternalCodeLocations(m_projectData, groupInserter.itemPosition(), groupInserter.lineOffset()); products = findProductsByName(products.first().name()); // These are new objects. QBS_CHECK(products.count() == resolvedProducts.count()); for (int i = 0; i < products.count(); ++i) { const GroupPtr resolvedGroup = ResolvedGroup::create(); resolvedGroup->location = groupInserter.itemPosition(); resolvedGroup->enabled = true; resolvedGroup->name = groupName; resolvedGroup->properties = resolvedProducts[i]->moduleProperties; resolvedGroup->overrideTags = false; resolvedProducts.at(i)->groups << resolvedGroup; products.at(i).d->groups << createGroupDataFromGroup(resolvedGroup); qSort(products.at(i).d->groups); } } ProjectPrivate::GroupUpdateContext ProjectPrivate::getGroupContext(const ProductData &product, const GroupData &group) { GroupUpdateContext context; if (!product.isValid()) throw ErrorInfo(Tr::tr("Product is invalid.")); context.products = findProductsByName(product.name()); if (context.products.isEmpty()) throw ErrorInfo(Tr::tr("Product '%1' does not exist.").arg(product.name())); context.resolvedProducts = internalProducts(context.products); const QString groupName = group.isValid() ? group.name() : product.name(); foreach (const ResolvedProductPtr &p, context.resolvedProducts) { foreach (const GroupPtr &g, p->groups) { if (g->name == groupName) { context.resolvedGroups << g; break; } } } if (context.resolvedGroups.isEmpty()) throw ErrorInfo(Tr::tr("Group '%1' does not exist.").arg(groupName)); foreach (const ProductData &p, context.products) { const GroupData &g = findGroupData(p, groupName); QBS_CHECK(p.isValid()); context.groups << g; } QBS_CHECK(context.resolvedProducts.count() == context.products.count()); QBS_CHECK(context.resolvedProducts.count() == context.resolvedGroups.count()); QBS_CHECK(context.products.count() == context.groups.count()); return context; } static bool matchesWildcard(const QString &filePath, const GroupConstPtr &group) { if (!group->wildcards) return false; foreach (const QString &pattern, group->wildcards->patterns) { QString fullPattern; if (QFileInfo(group->prefix).isAbsolute()) { fullPattern = group->prefix; } else { fullPattern = QFileInfo(group->location.filePath()).absolutePath() + QLatin1Char('/') + group->prefix; } fullPattern.append(QLatin1Char('/')).append(pattern); fullPattern = QDir::cleanPath(fullPattern); if (QRegExp(fullPattern, Qt::CaseSensitive, QRegExp::Wildcard).exactMatch(filePath)) return true; } return false; } ProjectPrivate::FileListUpdateContext ProjectPrivate::getFileListContext(const ProductData &product, const GroupData &group, const QStringList &filePaths, bool forAdding) { FileListUpdateContext filesContext; GroupUpdateContext &groupContext = filesContext.groupContext; groupContext = getGroupContext(product, group); if (filePaths.isEmpty()) throw ErrorInfo(Tr::tr("No files supplied.")); QString prefix; for (int i = 0; i < groupContext.resolvedGroups.count(); ++i) { const GroupPtr &g = groupContext.resolvedGroups.at(i); if (!g->prefix.isEmpty() && !g->prefix.endsWith(QLatin1Char('/'))) throw ErrorInfo(Tr::tr("Group has non-directory prefix.")); if (i == 0) prefix = g->prefix; else if (prefix != g->prefix) throw ErrorInfo(Tr::tr("Cannot update: Group prefix depends on properties.")); } QString baseDirPath = QFileInfo(product.location().filePath()).dir().absolutePath() + QLatin1Char('/') + prefix; QDir baseDir(baseDirPath); foreach (const QString &filePath, filePaths) { const QString absPath = QDir::cleanPath(FileInfo::resolvePath(baseDirPath, filePath)); if (filesContext.absoluteFilePaths.contains(absPath)) throw ErrorInfo(Tr::tr("File '%1' appears more than once.").arg(absPath)); if (forAdding && !FileInfo(absPath).exists()) throw ErrorInfo(Tr::tr("File '%1' does not exist.").arg(absPath)); if (matchesWildcard(absPath, groupContext.resolvedGroups.first())) { filesContext.absoluteFilePathsFromWildcards << absPath; } else { filesContext.absoluteFilePaths << absPath; filesContext.relativeFilePaths << baseDir.relativeFilePath(absPath); } } return filesContext; } static SourceArtifactPtr createSourceArtifact(const QString &filePath, const ResolvedProductPtr &product, const GroupConstPtr &group, QList &artifactList, Logger &logger) { const SourceArtifactPtr artifact = ProjectResolver::createSourceArtifact(product, group->properties, filePath, group->fileTags, group->overrideTags, artifactList); ProjectResolver::applyFileTaggers(artifact, product, logger); return artifact; } void ProjectPrivate::addFiles(const ProductData &product, const GroupData &group, const QStringList &filePaths) { FileListUpdateContext filesContext = getFileListContext(product, group, filePaths, true); GroupUpdateContext &groupContext = filesContext.groupContext; // We do not check for entries in other groups, because such doublettes might be legitimate // due to conditions. foreach (const GroupPtr &group, groupContext.resolvedGroups) { foreach (const QString &filePath, filesContext.absoluteFilePaths) { foreach (const SourceArtifactConstPtr &sa, group->files) { if (sa->absoluteFilePath == filePath) { throw ErrorInfo(Tr::tr("File '%1' already exists in group '%2'.") .arg(filePath, group->name)); } } } } ProjectFileFilesAdder adder(groupContext.products.first(), group.isValid() ? groupContext.groups.first() : GroupData(), filesContext.relativeFilePaths); adder.apply(); m_projectData.d.detach(); updateInternalCodeLocations(internalProject, adder.itemPosition(), adder.lineOffset()); updateExternalCodeLocations(m_projectData, adder.itemPosition(), adder.lineOffset()); QHash addedSourceArtifacts; for (int i = 0; i < groupContext.resolvedGroups.count(); ++i) { const ResolvedProductPtr &resolvedProduct = groupContext.resolvedProducts.at(i); const GroupPtr &resolvedGroup = groupContext.resolvedGroups.at(i); foreach (const QString &file, filesContext.absoluteFilePaths) { addedSourceArtifacts.insert(file, createSourceArtifact(file, resolvedProduct, resolvedGroup, resolvedGroup->files, logger)); } foreach (const QString &file, filesContext.absoluteFilePathsFromWildcards) { QBS_CHECK(resolvedGroup->wildcards); addedSourceArtifacts.insert(file, createSourceArtifact(file, resolvedProduct, resolvedGroup, resolvedGroup->wildcards->files, logger)); } if (resolvedProduct->enabled) { foreach (const SourceArtifactConstPtr &sa, addedSourceArtifacts) createArtifact(resolvedProduct, sa, logger); } } doSanityChecks(internalProject, logger); QList sourceArtifacts; QList sourceArtifactsFromWildcards; foreach (const QString &fp, filesContext.absoluteFilePaths) { const SourceArtifactConstPtr sa = addedSourceArtifacts.value(fp); QBS_CHECK(sa); sourceArtifacts << createApiSourceArtifact(sa); } foreach (const QString &fp, filesContext.absoluteFilePathsFromWildcards) { const SourceArtifactConstPtr sa = addedSourceArtifacts.value(fp); QBS_CHECK(sa); sourceArtifactsFromWildcards << createApiSourceArtifact(sa); } foreach (const GroupData &g, groupContext.groups) { g.d->sourceArtifacts << sourceArtifacts; qSort(g.d->sourceArtifacts); g.d->sourceArtifactsFromWildcards << sourceArtifactsFromWildcards; qSort(g.d->sourceArtifactsFromWildcards); } } void ProjectPrivate::removeFiles(const ProductData &product, const GroupData &group, const QStringList &filePaths) { FileListUpdateContext filesContext = getFileListContext(product, group, filePaths, false); GroupUpdateContext &groupContext = filesContext.groupContext; if (!filesContext.absoluteFilePathsFromWildcards.isEmpty()) { throw ErrorInfo(Tr::tr("The following files cannot be removed from the project file, " "because they match wildcard patterns: %1") .arg(filesContext.absoluteFilePathsFromWildcards.join(QLatin1String(", ")))); } QStringList filesNotFound = filesContext.absoluteFilePaths; QList sourceArtifacts; foreach (const SourceArtifactPtr &sa, groupContext.resolvedGroups.first()->files) { if (filesNotFound.removeOne(sa->absoluteFilePath)) sourceArtifacts << sa; } if (!filesNotFound.isEmpty()) { throw ErrorInfo(Tr::tr("The following files are not known to qbs: %1") .arg(filesNotFound.join(QLatin1String(", ")))); } ProjectFileFilesRemover remover(groupContext.products.first(), group.isValid() ? groupContext.groups.first() : GroupData(), filesContext.relativeFilePaths); remover.apply(); for (int i = 0; i < groupContext.resolvedProducts.count(); ++i) { removeFilesFromBuildGraph(groupContext.resolvedProducts.at(i), sourceArtifacts); foreach (const SourceArtifactPtr &sa, sourceArtifacts) groupContext.resolvedGroups.at(i)->files.removeOne(sa); } doSanityChecks(internalProject, logger); m_projectData.d.detach(); updateInternalCodeLocations(internalProject, remover.itemPosition(), remover.lineOffset()); updateExternalCodeLocations(m_projectData, remover.itemPosition(), remover.lineOffset()); foreach (const GroupData &g, groupContext.groups) { for (int i = g.d->sourceArtifacts.count() - 1; i >= 0; --i) { if (filesContext.absoluteFilePaths.contains(g.d->sourceArtifacts.at(i).filePath())) g.d->sourceArtifacts.removeAt(i); } } } void ProjectPrivate::removeGroup(const ProductData &product, const GroupData &group) { GroupUpdateContext context = getGroupContext(product, group); ProjectFileGroupRemover remover(context.products.first(), context.groups.first()); remover.apply(); for (int i = 0; i < context.resolvedProducts.count(); ++i) { const ResolvedProductPtr &product = context.resolvedProducts.at(i); const GroupPtr &group = context.resolvedGroups.at(i); removeFilesFromBuildGraph(product, group->allFiles()); const bool removed = product->groups.removeOne(group); QBS_CHECK(removed); } doSanityChecks(internalProject, logger); m_projectData.d.detach(); updateInternalCodeLocations(internalProject, remover.itemPosition(), remover.lineOffset()); updateExternalCodeLocations(m_projectData, remover.itemPosition(), remover.lineOffset()); for (int i = 0; i < context.products.count(); ++i) { const bool removed = context.products.at(i).d->groups.removeOne(context.groups.at(i)); QBS_CHECK(removed); } } #endif // QBS_ENABLE_PROJECT_FILE_UPDATES void ProjectPrivate::removeFilesFromBuildGraph(const ResolvedProductConstPtr &product, const QList &files) { if (!product->enabled) return; QBS_CHECK(internalProject->buildData); ArtifactSet allRemovedArtifacts; foreach (const SourceArtifactPtr &sa, files) { ArtifactSet removedArtifacts; Artifact * const artifact = lookupArtifact(product, sa->absoluteFilePath); if (artifact) { // Can be null if the executor has not yet applied the respective rule. internalProject->buildData->removeArtifactAndExclusiveDependents(artifact, logger, true, &removedArtifacts); } allRemovedArtifacts.unite(removedArtifacts); } EmptyDirectoriesRemover(product->topLevelProject(), logger) .removeEmptyParentDirectories(allRemovedArtifacts); qDeleteAll(allRemovedArtifacts); } static void updateLocationIfNecessary(CodeLocation &location, const CodeLocation &changeLocation, int lineOffset) { if (location.filePath() == changeLocation.filePath() && location.line() >= changeLocation.line()) { location = CodeLocation(location.filePath(), location.line() + lineOffset, location.column()); } } void ProjectPrivate::updateInternalCodeLocations(const ResolvedProjectPtr &project, const CodeLocation &changeLocation, int lineOffset) { if (lineOffset == 0) return; updateLocationIfNecessary(project->location, changeLocation, lineOffset); foreach (const ResolvedProjectPtr &subProject, project->subProjects) updateInternalCodeLocations(subProject, changeLocation, lineOffset); foreach (const ResolvedProductPtr &product, project->products) { updateLocationIfNecessary(product->location, changeLocation, lineOffset); foreach (const GroupPtr &group, product->groups) updateLocationIfNecessary(group->location, changeLocation, lineOffset); foreach (const RulePtr &rule, product->rules) { updateLocationIfNecessary(rule->prepareScript->location, changeLocation, lineOffset); foreach (const RuleArtifactPtr &artifact, rule->artifacts) { for (int i = 0; i < artifact->bindings.count(); ++i) { updateLocationIfNecessary(artifact->bindings[i].location, changeLocation, lineOffset); } } } foreach (const ResolvedTransformerConstPtr &transformer, product->transformers) updateLocationIfNecessary(transformer->transform->location, changeLocation, lineOffset); foreach (const ResolvedScannerConstPtr &scanner, product->scanners) { updateLocationIfNecessary(scanner->searchPathsScript->location, changeLocation, lineOffset); updateLocationIfNecessary(scanner->scanScript->location, changeLocation, lineOffset); } foreach (const ResolvedModuleConstPtr &module, product->modules) { updateLocationIfNecessary(module->setupBuildEnvironmentScript->location, changeLocation, lineOffset); updateLocationIfNecessary(module->setupRunEnvironmentScript->location, changeLocation, lineOffset); } } } void ProjectPrivate::updateExternalCodeLocations(const ProjectData &project, const CodeLocation &changeLocation, int lineOffset) { if (lineOffset == 0) return; updateLocationIfNecessary(project.d->location, changeLocation, lineOffset); foreach (const ProjectData &subProject, project.subProjects()) updateExternalCodeLocations(subProject, changeLocation, lineOffset); foreach (const ProductData &product, project.products()) { updateLocationIfNecessary(product.d->location, changeLocation, lineOffset); foreach (const GroupData &group, product.groups()) updateLocationIfNecessary(group.d->location, changeLocation, lineOffset); } } void ProjectPrivate::prepareChangeToProject() { if (internalProject->locked) throw ErrorInfo(Tr::tr("A job is currently in process.")); if (!m_projectData.isValid()) retrieveProjectData(m_projectData, internalProject); } RuleCommandList ProjectPrivate::ruleCommands(const ProductData &product, const QString &inputFilePath, const QString &outputFileTag) const { if (internalProject->locked) throw ErrorInfo(Tr::tr("A job is currently in process.")); const ResolvedProductConstPtr resolvedProduct = internalProduct(product); if (!resolvedProduct) throw ErrorInfo(Tr::tr("No such product '%1'.").arg(product.name())); if (!resolvedProduct->enabled) throw ErrorInfo(Tr::tr("Product '%1' is disabled.").arg(product.name())); QBS_CHECK(resolvedProduct->buildData); const ArtifactSet &outputArtifacts = resolvedProduct->buildData->artifactsByFileTag .value(FileTag(outputFileTag.toLocal8Bit())); foreach (const Artifact * const outputArtifact, outputArtifacts) { const TransformerConstPtr transformer = outputArtifact->transformer; if (!transformer) continue; foreach (const Artifact * const inputArtifact, transformer->inputs) { if (inputArtifact->filePath() == inputFilePath) { RuleCommandList list; foreach (const AbstractCommandPtr &internalCommand, transformer->commands) { RuleCommand externalCommand; externalCommand.d->description = internalCommand->description(); switch (internalCommand->type()) { case AbstractCommand::JavaScriptCommandType: { externalCommand.d->type = RuleCommand::JavaScriptCommandType; const JavaScriptCommandPtr &jsCmd = internalCommand.staticCast(); externalCommand.d->sourceCode = jsCmd->sourceCode(); break; } case AbstractCommand::ProcessCommandType: { externalCommand.d->type = RuleCommand::ProcessCommandType; const ProcessCommandPtr &procCmd = internalCommand.staticCast(); externalCommand.d->executable = procCmd->program(); externalCommand.d->arguments = procCmd->arguments(); externalCommand.d->workingDir = procCmd->workingDir(); externalCommand.d->environment = procCmd->environment(); break; } } list << externalCommand; } return list; } } } throw ErrorInfo(Tr::tr("No rule was found that produces an artifact tagged '%1' " "from input file '%2'.").arg(outputFileTag, inputFilePath)); } static bool productIsRunnable(const ResolvedProductConstPtr &product) { return product->fileTags.contains("application"); } void ProjectPrivate::retrieveProjectData(ProjectData &projectData, const ResolvedProjectConstPtr &internalProject) { projectData.d->name = internalProject->name; projectData.d->location = internalProject->location; projectData.d->enabled = internalProject->enabled; foreach (const ResolvedProductConstPtr &resolvedProduct, internalProject->products) { ProductData product; product.d->type = resolvedProduct->fileTags.toStringList(); product.d->name = resolvedProduct->name; product.d->targetName = resolvedProduct->targetName; product.d->version = resolvedProduct->productProperties .value(QLatin1String("version")).toString(); product.d->profile = resolvedProduct->profile; product.d->location = resolvedProduct->location; product.d->isEnabled = resolvedProduct->enabled; product.d->isRunnable = productIsRunnable(resolvedProduct); product.d->properties = resolvedProduct->productProperties; product.d->moduleProperties.d->m_map = resolvedProduct->moduleProperties; foreach (const GroupPtr &resolvedGroup, resolvedProduct->groups) product.d->groups << createGroupDataFromGroup(resolvedGroup); if (resolvedProduct->enabled) { QBS_CHECK(resolvedProduct->buildData); foreach (const Artifact * const a, resolvedProduct->targetArtifacts()) { TargetArtifact ta; ta.d->filePath = a->filePath(); ta.d->fileTags = a->fileTags().toStringList(); ta.d->properties.d->m_map = a->properties; ta.d->isValid = true; product.d->targetArtifacts << ta; } } foreach (const ResolvedProductPtr &resolvedDependentProduct, resolvedProduct->dependencies) product.d->dependencies << resolvedDependentProduct->name; qSort(product.d->type); qSort(product.d->groups); qSort(product.d->targetArtifacts); qSort(product.d->dependencies); product.d->isValid = true; projectData.d->products << product; } foreach (const ResolvedProjectConstPtr &internalSubProject, internalProject->subProjects) { if (!internalSubProject->enabled) continue; ProjectData subProject; retrieveProjectData(subProject, internalSubProject); projectData.d->subProjects << subProject; } projectData.d->isValid = true; qSort(projectData.d->products); qSort(projectData.d->subProjects); } } // namespace Internal using namespace Internal; /*! * \class Project * \brief The \c Project class provides services related to a qbs project. */ Project::Project(const TopLevelProjectPtr &internalProject, const Logger &logger) : d(new ProjectPrivate(internalProject, logger)) { } Project::Project(const Project &other) : d(other.d) { } Project::~Project() { } /*! * \brief Returns true if and only if this object was retrieved from a successful \c SetupProjectJob. * \sa SetupProjectJob */ bool Project::isValid() const { return d && d->internalProject; } /*! * \brief The top-level profile for building this project. */ QString Project::profile() const { QBS_ASSERT(isValid(), return QString()); return d->internalProject->profile(); } Project &Project::operator=(const Project &other) { d = other.d; return *this; } /*! * \brief Sets up a \c Project from a source file, possibly re-using previously stored information. * The function will finish immediately, returning a \c SetupProjectJob which can be used to * track the results of the operation. * If the function is called on a valid \c Project object, the build graph will not be loaded * from a file, but will be taken from the existing project. In that case, if resolving * finishes successfully, the existing project will be invalidated. If resolving fails, qbs will * try to keep the existing project valid. However, under certain circumstances, resolving the new * project will fail at a time where existing project data has already been touched, in which case * the existing project has to be invalidated (this could be avoided, but it would hurt performance). * So after an unsuccessful re-resolve job, the existing project may or may not be valid anymore. * \note The qbs plugins will only be loaded once. As a result, the value of * \c parameters.pluginPaths will only have an effect the first time this function is called. * Similarly, the value of \c parameters.searchPaths will not have an effect if * a stored build graph is available. */ SetupProjectJob *Project::setupProject(const SetupProjectParameters ¶meters, ILogSink *logSink, QObject *jobOwner) { Logger logger(logSink); SetupProjectJob * const job = new SetupProjectJob(logger, jobOwner); try { loadPlugins(parameters.pluginPaths(), logger); job->resolve(*this, parameters); } catch (const ErrorInfo &error) { // Throwing from here would complicate the API, so let's report the error the same way // as all others, via AbstractJob::error(). job->reportError(error); } return job; } Project::Project() { } /*! * \brief Retrieves information for this project. * Call this function if you need insight into the project structure, e.g. because you want to know * which products or files are in it. */ ProjectData Project::projectData() const { QBS_ASSERT(isValid(), return ProjectData()); return d->projectData(); } /*! * \brief Returns the file path of the executable associated with the given product. * If the product is not an application, an empty string is returned. * The \a installOptions parameter is used to look up the executable in case it is installable; * otherwise the parameter is ignored and the returned path will point to where the file is built. */ QString Project::targetExecutable(const ProductData &product, const InstallOptions &installOptions) const { QBS_ASSERT(isValid(), return QString()); if (!product.isEnabled()) return QString(); foreach (const TargetArtifact &ta, product.targetArtifacts()) { if (ta.isExecutable()) { const QList &installables = installableFilesForProduct(product, installOptions); foreach (const InstallableFile &file, installables) { if (file.sourceFilePath() == ta.filePath()) return file.targetFilePath(); } return ta.filePath(); } } return QString(); } RunEnvironment Project::getRunEnvironment(const ProductData &product, const InstallOptions &installOptions, const QProcessEnvironment &environment, Settings *settings) const { const ResolvedProductPtr resolvedProduct = d->internalProduct(product); return RunEnvironment(resolvedProduct, installOptions, environment, settings, d->logger); } /*! * \enum Project::ProductSelection * This enum type specifies which products to include if "all" products are to be built. * \value Project::ProdProductSelectionDefaultOnly Indicates that only those products should be * built whose \c builtByDefault property * is \c true. * \value Project::ProdProductSelectionWithNonDefault Indicates that products whose * \c builtByDefault property is \c false should * also be built. */ /*! * \brief Causes all products of this project to be built, if necessary. * If and only if \c producSelection is \c Project::ProductSelectionWithNonDefault, products with * the \c builtByDefault property set to \c false will be built too. * The function will finish immediately, returning a \c BuildJob identifiying the operation. */ BuildJob *Project::buildAllProducts(const BuildOptions &options, ProductSelection productSelection, QObject *jobOwner) const { QBS_ASSERT(isValid(), return 0); const bool includingNonDefault = productSelection == ProductSelectionWithNonDefault; return d->buildProducts(d->allEnabledInternalProducts(includingNonDefault), options, !includingNonDefault, jobOwner); } /*! * \brief Causes the specified list of products to be built. * Use this function if you only want to build some products, not the whole project. If any of * the products in \a products depend on other products, those will also be built. * The function will finish immediately, returning a \c BuildJob identifiying the operation. */ BuildJob *Project::buildSomeProducts(const QList &products, const BuildOptions &options, QObject *jobOwner) const { QBS_ASSERT(isValid(), return 0); return d->buildProducts(d->internalProducts(products), options, true, jobOwner); } /*! * \brief Convenience function for \c buildSomeProducts(). * \sa Project::buildSomeProducts(). */ BuildJob *Project::buildOneProduct(const ProductData &product, const BuildOptions &options, QObject *jobOwner) const { return buildSomeProducts(QList() << product, options, jobOwner); } /*! * \brief Removes the build artifacts of all products in the project. * The function will finish immediately, returning a \c CleanJob identifiying this operation. * \sa Project::cleanSomeProducts() */ CleanJob *Project::cleanAllProducts(const CleanOptions &options, QObject *jobOwner) const { QBS_ASSERT(isValid(), return 0); return d->cleanProducts(d->allEnabledInternalProducts(true), options, jobOwner); } /*! * \brief Removes the build artifacts of the given products. * The function will finish immediately, returning a \c CleanJob identifiying this operation. */ CleanJob *Project::cleanSomeProducts(const QList &products, const CleanOptions &options, QObject *jobOwner) const { QBS_ASSERT(isValid(), return 0); return d->cleanProducts(d->internalProducts(products), options, jobOwner); } /*! * \brief Convenience function for \c cleanSomeProducts(). * \sa Project::cleanSomeProducts(). */ CleanJob *Project::cleanOneProduct(const ProductData &product, const CleanOptions &options, QObject *jobOwner) const { return cleanSomeProducts(QList() << product, options, jobOwner); } /*! * \brief Installs the installable files of all products in the project. * If and only if \c producSelection is \c Project::ProductSelectionWithNonDefault, products with * the \c builtByDefault property set to \c false will be installed too. * The function will finish immediately, returning an \c InstallJob identifiying this operation. */ InstallJob *Project::installAllProducts(const InstallOptions &options, ProductSelection productSelection, QObject *jobOwner) const { QBS_ASSERT(isValid(), return 0); const bool includingNonDefault = productSelection == ProductSelectionWithNonDefault; return d->installProducts(d->allEnabledInternalProducts(includingNonDefault), options, !includingNonDefault, jobOwner); } /*! * \brief Installs the installable files of the given products. * The function will finish immediately, returning an \c InstallJob identifiying this operation. */ InstallJob *Project::installSomeProducts(const QList &products, const InstallOptions &options, QObject *jobOwner) const { QBS_ASSERT(isValid(), return 0); return d->installProducts(d->internalProducts(products), options, true, jobOwner); } /*! * \brief Convenience function for \c installSomeProducts(). * \sa Project::installSomeProducts(). */ InstallJob *Project::installOneProduct(const ProductData &product, const InstallOptions &options, QObject *jobOwner) const { return installSomeProducts(QList() << product, options, jobOwner); } /*! * \brief All files in the product for which "qbs.install" is true. * This includes source files as well as generated files. */ QList Project::installableFilesForProduct(const ProductData &product, const InstallOptions &options) const { QList installableFiles; QBS_ASSERT(isValid(), return installableFiles); const ResolvedProductConstPtr internalProduct = d->internalProduct(product); if (!internalProduct) return installableFiles; InstallOptions mutableOptions = options; foreach (const GroupConstPtr &group, internalProduct->groups) { foreach (const SourceArtifactConstPtr &artifact, group->allFiles()) { InstallableFile f; const QString &targetFilePath = ProductInstaller::targetFilePath(internalProduct->topLevelProject(), internalProduct->sourceDirectory, artifact->absoluteFilePath, artifact->properties, mutableOptions); if (targetFilePath.isEmpty()) continue; f.d->sourceFilePath = artifact->absoluteFilePath; f.d->fileTags = artifact->fileTags.toStringList(); f.d->targetFilePath = targetFilePath; f.d->isValid = true; installableFiles << f; } } if (internalProduct->enabled) { QBS_CHECK(internalProduct->buildData); foreach (const Artifact * const artifact, ArtifactSet::fromNodeSet(internalProduct->buildData->nodes)) { if (artifact->artifactType == Artifact::SourceFile) continue; InstallableFile f; const QString &targetFilePath = ProductInstaller::targetFilePath(internalProduct->topLevelProject(), internalProduct->sourceDirectory, artifact->filePath(), artifact->properties, mutableOptions); if (targetFilePath.isEmpty()) continue; f.d->sourceFilePath = artifact->filePath(); f.d->fileTags = artifact->fileTags().toStringList(); f.d->targetFilePath = targetFilePath; f.d->isValid = true; installableFiles << f; } } qSort(installableFiles); return installableFiles; } /*! * \brief All files in the project for which "qbs.install" is true. * This includes all sub-projects. * \sa Project::installableFilesForProduct() */ QList Project::installableFilesForProject(const ProjectData &project, const InstallOptions &options) const { QList installableFiles; QBS_ASSERT(isValid(), return installableFiles); foreach (const ProductData &p, project.allProducts()) installableFiles << installableFilesForProduct(p, options); qSort(installableFiles); return installableFiles; } /*! * \brief Updates the timestamps of all build artifacts in the given products. * Afterwards, the build graph will have the same state as if a successful build had been done. */ void Project::updateTimestamps(const QList &products) { QBS_ASSERT(isValid(), return); TimestampsUpdater().updateTimestamps(d->internalProject, d->internalProducts(products), d->logger); } /*! * \brief Finds files generated from the given file in the given product. * The function returns files generated from the given file and the given product. To do so it will * traverse the graph of generated files and the files generated from those files. * * If an empty list of tags is given, then all directly and indirectly generated files will be * returned. If there are tags, then processing will stop once matching files were found. */ QStringList Project::generatedFiles(const ProductData &product, const QString &file, const QStringList &tags) const { QBS_ASSERT(isValid(), return QStringList()); const ResolvedProductConstPtr internalProduct = d->internalProduct(product); return internalProduct->generatedFiles(file, FileTags::fromStringList(tags)); } QVariantMap Project::projectConfiguration() const { QBS_ASSERT(isValid(), return QVariantMap()); return d->internalProject->buildConfiguration(); } QHash Project::usedEnvironment() const { typedef QHash EnvType; QBS_ASSERT(isValid(), return EnvType()); return d->internalProject->usedEnvironment; } QSet Project::buildSystemFiles() const { QBS_ASSERT(isValid(), return QSet()); return d->internalProject->buildSystemFiles; } RuleCommandList Project::ruleCommands(const ProductData &product, const QString &inputFilePath, const QString &outputFileTag, ErrorInfo *error) const { QBS_ASSERT(isValid(), return RuleCommandList()); QBS_ASSERT(product.isValid(), return RuleCommandList()); try { return d->ruleCommands(product, inputFilePath, outputFileTag); } catch (const ErrorInfo &e) { if (error) *error = e; return RuleCommandList(); } } ErrorInfo Project::dumpNodesTree(QIODevice &outDevice, const QList &products) { try { NodeTreeDumper(outDevice).start(d->internalProducts(products)); } catch (const ErrorInfo &e) { return e; } return ErrorInfo(); } #ifdef QBS_ENABLE_PROJECT_FILE_UPDATES /*! * \brief Adds a new empty group to the given product. * Returns an \c ErrorInfo object for which \c hasError() is false in case of a success * and true otherwise. In the latter case, the object will have a sensible description. * After calling this function, it is recommended to re-fetch the project data, as other * items can be affected. * \sa qbs::Project::projectData() */ ErrorInfo Project::addGroup(const ProductData &product, const QString &groupName) { try { QBS_CHECK(isValid()); d->prepareChangeToProject(); d->addGroup(product, groupName); d->internalProject->lastResolveTime = FileTime::currentTime(); d->internalProject->store(d->logger); return ErrorInfo(); } catch (ErrorInfo errorInfo) { errorInfo.prepend(Tr::tr("Failure adding group '%1' to product '%2'.") .arg(groupName, product.name())); return errorInfo; } } /*! * \brief Adds the given files to the given product. * If \c group is a default-constructed object, the files will be added to the product's * "files" property, otherwise to the one of \c group. * The file paths can be absolute or relative to the location of \c product (including a possible * prefix in the group). The project file will always contain relative paths. * After calling this function, it is recommended to re-fetch the project data, as other * items can be affected. * \sa qbs::Project::projectData() */ ErrorInfo Project::addFiles(const ProductData &product, const GroupData &group, const QStringList &filePaths) { try { QBS_CHECK(isValid()); d->prepareChangeToProject(); d->addFiles(product, group, filePaths); d->internalProject->lastResolveTime = FileTime::currentTime(); d->internalProject->store(d->logger); return ErrorInfo(); } catch (ErrorInfo errorInfo) { errorInfo.prepend(Tr::tr("Failure adding files to product.")); return errorInfo; } } /*! * \brief Removes the given files from the given product. * If \c group is a default-constructed object, the files will be removed from the product's * "files" property, otherwise from the one of \c group. * The file paths can be absolute or relative to the location of \c product (including a possible * prefix in the group). * After calling this function, it is recommended to re-fetch the project data, as other * items can be affected. * \sa qbs::Project::projectData() */ ErrorInfo Project::removeFiles(const ProductData &product, const GroupData &group, const QStringList &filePaths) { try { QBS_CHECK(isValid()); d->prepareChangeToProject(); d->removeFiles(product, group, filePaths); d->internalProject->lastResolveTime = FileTime::currentTime(); d->internalProject->store(d->logger); return ErrorInfo(); } catch (ErrorInfo errorInfo) { errorInfo.prepend(Tr::tr("Failure removing files from product '%1'.").arg(product.name())); return errorInfo; } } /*! * \brief Removes the given group from the given product. * After calling this function, it is recommended to re-fetch the project data, as other * items can be affected. * \sa qbs::Project::projectData() */ ErrorInfo Project::removeGroup(const ProductData &product, const GroupData &group) { try { QBS_CHECK(isValid()); d->prepareChangeToProject(); d->removeGroup(product, group); d->internalProject->lastResolveTime = FileTime::currentTime(); d->internalProject->store(d->logger); return ErrorInfo(); } catch (ErrorInfo errorInfo) { errorInfo.prepend(Tr::tr("Failure removing group '%1' from product '%2'.") .arg(group.name(), product.name())); return errorInfo; } } #endif // QBS_ENABLE_PROJECT_FILE_UPDATES } // namespace qbs qbs-src-1.4.5/src/lib/corelib/api/project.h000066400000000000000000000147711266132464200204570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROJECT_H #define QBS_PROJECT_H #include "rulecommand.h" #include "../language/forward_decls.h" #include "../tools/qbs_export.h" #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QIODevice; class QObject; class QProcessEnvironment; QT_END_NAMESPACE namespace qbs { class BuildJob; class BuildOptions; class CleanJob; class CleanOptions; class ErrorInfo; class GroupData; class ILogSink; class InstallableFile; class InstallJob; class InstallOptions; class ProductData; class ProjectData; class RunEnvironment; class Settings; class SetupProjectJob; class SetupProjectParameters; namespace Internal { class Logger; class ProjectPrivate; } // namespace Internal; class QBS_EXPORT Project { friend class SetupProjectJob; friend uint qHash(const Project &p); public: SetupProjectJob *setupProject(const SetupProjectParameters ¶meters, ILogSink *logSink, QObject *jobOwner); Project(); Project(const Project &other); Project &operator=(const Project &other); ~Project(); bool isValid() const; QString profile() const; ProjectData projectData() const; QString targetExecutable(const ProductData &product, const InstallOptions &installoptions) const; RunEnvironment getRunEnvironment(const ProductData &product, const InstallOptions &installOptions, const QProcessEnvironment &environment, Settings *settings) const; enum ProductSelection { ProductSelectionDefaultOnly, ProductSelectionWithNonDefault }; BuildJob *buildAllProducts(const BuildOptions &options, ProductSelection productSelection = ProductSelectionDefaultOnly, QObject *jobOwner = 0) const; BuildJob *buildSomeProducts(const QList &products, const BuildOptions &options, QObject *jobOwner = 0) const; BuildJob *buildOneProduct(const ProductData &product, const BuildOptions &options, QObject *jobOwner = 0) const; CleanJob *cleanAllProducts(const CleanOptions &options, QObject *jobOwner = 0) const; CleanJob *cleanSomeProducts(const QList &products, const CleanOptions &options, QObject *jobOwner = 0) const; CleanJob *cleanOneProduct(const ProductData &product, const CleanOptions &options, QObject *jobOwner = 0) const; InstallJob *installAllProducts(const InstallOptions &options, ProductSelection productSelection = ProductSelectionDefaultOnly, QObject *jobOwner = 0) const; InstallJob *installSomeProducts(const QList &products, const InstallOptions &options, QObject *jobOwner = 0) const; InstallJob *installOneProduct(const ProductData &product, const InstallOptions &options, QObject *jobOwner = 0) const; QList installableFilesForProduct(const ProductData &product, const InstallOptions &options) const; QList installableFilesForProject(const ProjectData &project, const InstallOptions &options) const; void updateTimestamps(const QList &products); bool operator==(const Project &other) const { return d.data() == other.d.data(); } QStringList generatedFiles(const ProductData &product, const QString &file, const QStringList &tags = QStringList()) const; QVariantMap projectConfiguration() const; QHash usedEnvironment() const; QSet buildSystemFiles() const; RuleCommandList ruleCommands(const ProductData &product, const QString &inputFilePath, const QString &outputFileTag, ErrorInfo *error = 0) const; ErrorInfo dumpNodesTree(QIODevice &outDevice, const QList &products); #ifdef QBS_ENABLE_PROJECT_FILE_UPDATES ErrorInfo addGroup(const ProductData &product, const QString &groupName); ErrorInfo addFiles(const ProductData &product, const GroupData &group, const QStringList &filePaths); ErrorInfo removeFiles(const ProductData &product, const GroupData &group, const QStringList &filePaths); ErrorInfo removeGroup(const ProductData &product, const GroupData &group); #endif // QBS_ENABLE_PROJECT_FILE_UPDATES private: Project(const Internal::TopLevelProjectPtr &internalProject, const Internal::Logger &logger); QExplicitlySharedDataPointer d; }; inline bool operator!=(const Project &p1, const Project &p2) { return !(p1 == p2); } inline uint qHash(const Project &p) { return QT_PREPEND_NAMESPACE(qHash)(p.d.data()); } } // namespace qbs #endif // QBS_PROJECT_H qbs-src-1.4.5/src/lib/corelib/api/project_p.h000066400000000000000000000124121266132464200207640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROJECT_P_H #define QBS_PROJECT_P_H #include "projectdata.h" #include "rulecommand.h" #include #include #include #include namespace qbs { class BuildJob; class BuildOptions; class CleanJob; class CleanOptions; class InstallJob; class InstallOptions; namespace Internal { class ProjectPrivate : public QSharedData { public: ProjectPrivate(const TopLevelProjectPtr &internalProject, const Logger &logger) : internalProject(internalProject), logger(logger) { } ProjectData projectData(); BuildJob *buildProducts(const QList &products, const BuildOptions &options, bool needsDepencencyResolving, QObject *jobOwner); CleanJob *cleanProducts(const QList &products, const CleanOptions &options, QObject *jobOwner); InstallJob *installProducts(const QList &products, const InstallOptions &options, bool needsDepencencyResolving, QObject *jobOwner); QList internalProducts(const QList &products) const; QList allEnabledInternalProducts(bool includingNonDefault) const; ResolvedProductPtr internalProduct(const ProductData &product) const; ProductData findProductData(const ProductData &product) const; QList findProductsByName(const QString &name) const; GroupData findGroupData(const ProductData &product, const QString &groupName) const; GroupData createGroupDataFromGroup(const GroupPtr &resolvedGroup); SourceArtifact createApiSourceArtifact(const SourceArtifactConstPtr &sa); struct GroupUpdateContext { QList resolvedProducts; QList resolvedGroups; QList products; QList groups; }; struct FileListUpdateContext { GroupUpdateContext groupContext; QStringList absoluteFilePaths; QStringList relativeFilePaths; QStringList absoluteFilePathsFromWildcards; // Not included in the other two lists. }; GroupUpdateContext getGroupContext(const ProductData &product, const GroupData &group); FileListUpdateContext getFileListContext(const ProductData &product, const GroupData &group, const QStringList &filePaths, bool forAdding); void addGroup(const ProductData &product, const QString &groupName); void addFiles(const ProductData &product, const GroupData &group, const QStringList &filePaths); void removeFiles(const ProductData &product, const GroupData &group, const QStringList &filePaths); void removeGroup(const ProductData &product, const GroupData &group); void removeFilesFromBuildGraph(const ResolvedProductConstPtr &product, const QList &files); void updateInternalCodeLocations(const ResolvedProjectPtr &project, const CodeLocation &changeLocation, int lineOffset); void updateExternalCodeLocations(const ProjectData &project, const CodeLocation &changeLocation, int lineOffset); void prepareChangeToProject(); RuleCommandList ruleCommands(const ProductData &product, const QString &inputFilePath, const QString &outputFileTag) const; TopLevelProjectPtr internalProject; Logger logger; private: void retrieveProjectData(ProjectData &projectData, const ResolvedProjectConstPtr &internalProject); ProjectData m_projectData; }; } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-1.4.5/src/lib/corelib/api/projectdata.cpp000066400000000000000000000472631266132464200216460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "projectdata.h" #include "projectdata_p.h" #include "propertymap_p.h" #include #include #include #include #include #include namespace qbs { /*! * \class GroupData * \brief The \c GroupData class corresponds to the Group item in a qbs source file. */ GroupData::GroupData() : d(new Internal::GroupDataPrivate) { } GroupData::GroupData(const GroupData &other) : d(other.d) { } GroupData &GroupData::operator=(const GroupData &other) { d = other.d; return *this; } GroupData::~GroupData() { } /*! * \brief Returns true if and only if the Group holds data that was initialized by Qbs. */ bool GroupData::isValid() const { return d->isValid; } /*! * \brief The location at which the group is defined in the respective source file. */ CodeLocation GroupData::location() const { return d->location; } /*! * \brief The name of the group. */ QString GroupData::name() const { return d->name; } /*! * \brief The files listed in the group item's "files" binding. * \note These do not include expanded wildcards. * \sa GroupData::sourceArtifactsFromWildcards */ QList GroupData::sourceArtifacts() const { return d->sourceArtifacts; } /*! * \brief The list of files resulting from expanding all wildcard patterns in the group. */ QList GroupData::sourceArtifactsFromWildcards() const { return d->sourceArtifactsFromWildcards; } /*! * \brief All files in this group, regardless of how whether they were given explicitly * or via wildcards. * \sa GroupData::sourceArtifacts * \sa GroupData::sourceArtifactsFromWildcards */ QList GroupData::allSourceArtifacts() const { return sourceArtifacts() + sourceArtifactsFromWildcards(); } /*! * \brief The set of properties valid in this group. * Typically, most of them are inherited from the respective \c Product. */ PropertyMap GroupData::properties() const { return d->properties; } /*! * \brief Returns true if this group is enabled in Qbs * This method returns the "condition" property of the \c Group definition. If the group is enabled * then the files in this group will be processed, provided the product it belongs to is also * enabled. * * Note that a group can be enabled, even if the product it belongs to is not. In this case * the files in the group will not be processed. * \sa ProductData::isEnabled() */ bool GroupData::isEnabled() const { QBS_ASSERT(isValid(), return false); return d->isEnabled; } /*! * \brief The paths of all files in this group. * \sa GroupData::allSourceArtifacts */ QStringList GroupData::allFilePaths() const { const QList &artifacts = allSourceArtifacts(); QStringList paths; paths.reserve(artifacts.count()); std::transform(artifacts.constBegin(), artifacts.constEnd(), std::back_inserter(paths), [](const SourceArtifact &sa) { return sa.filePath(); }); return paths; } bool operator!=(const GroupData &lhs, const GroupData &rhs) { return !(lhs == rhs); } bool operator==(const GroupData &lhs, const GroupData &rhs) { if (!lhs.isValid() && !rhs.isValid()) return true; return lhs.isValid() == rhs.isValid() && lhs.name() == rhs.name() && lhs.location() == rhs.location() && lhs.sourceArtifactsFromWildcards() == rhs.sourceArtifactsFromWildcards() && lhs.sourceArtifacts() == rhs.sourceArtifacts() && lhs.properties() == rhs.properties() && lhs.isEnabled() == rhs.isEnabled(); } bool operator<(const GroupData &lhs, const GroupData &rhs) { return lhs.name() < rhs.name(); } /*! * \class SourceArtifact * \brief The \c SourceArtifact class describes a source file in a product. */ SourceArtifact::SourceArtifact() : d(new Internal::SourceArtifactPrivate) { } SourceArtifact::SourceArtifact(const SourceArtifact &other) : d(other.d) { } SourceArtifact &SourceArtifact::operator=(const SourceArtifact &other) { d = other.d; return *this; } SourceArtifact::~SourceArtifact() { } /*! * \brief Returns true if and only if this object holds data that was initialized by Qbs. */ bool SourceArtifact::isValid() const { return d->isValid; } /*! * \brief The full path of this file. */ QString SourceArtifact::filePath() const { return d->filePath; } /*! * \brief The tags of this file. * Typically, this list will contain just one element. */ QStringList SourceArtifact::fileTags() const { return d->fileTags; } bool operator==(const SourceArtifact &sa1, const SourceArtifact &sa2) { return sa1.filePath() == sa2.filePath() && sa1.fileTags() == sa2.fileTags(); } bool operator!=(const SourceArtifact &sa1, const SourceArtifact &sa2) { return !(sa1 == sa2); } bool operator<(const SourceArtifact &sa1, const SourceArtifact &sa2) { return sa1.filePath() < sa2.filePath(); } /*! * \class TargetArtifact * \brief The \c TargetArtifact class describes a top-level build result of a product. * For instance, the target artifact of a product with type "application" is an executable file. */ TargetArtifact::TargetArtifact() : d(new Internal::TargetArtifactPrivate) { } TargetArtifact::TargetArtifact(const TargetArtifact &other) : d(other.d) { } TargetArtifact &TargetArtifact::operator=(const TargetArtifact &other) { d = other.d; return *this; } TargetArtifact::~TargetArtifact() { } /*! * \brief Returns true if and only if this object holds data that was initialized by Qbs. */ bool TargetArtifact::isValid() const { return d->isValid; } /*! * \brief The full path of this file. */ QString TargetArtifact::filePath() const { return d->filePath; } /*! * \brief The tags of this file. * Typically, this list will contain just one element. */ QStringList TargetArtifact::fileTags() const { return d->fileTags; } /*! * \brief True if and only if this file is executable, * either natively or through an interpreter or shell. */ bool TargetArtifact::isExecutable() const { return d->fileTags.contains(QLatin1String("application")) || d->fileTags.contains(QLatin1String("msi")); } /*! * \brief The properties of this file. */ PropertyMap TargetArtifact::properties() const { return d->properties; } bool operator==(const TargetArtifact &ta1, const TargetArtifact &ta2) { return ta1.filePath() == ta2.filePath() && ta1.fileTags() == ta2.fileTags() && ta1.properties() == ta2.properties(); } bool operator!=(const TargetArtifact &ta1, const TargetArtifact &ta2) { return !(ta1 == ta2); } bool operator<(const TargetArtifact &ta1, const TargetArtifact &ta2) { return ta1.filePath() < ta2.filePath(); } /*! * \class InstallableFile * \brief Describes a file that is marked for installation. */ InstallableFile::InstallableFile() : d(new Internal::InstallableFilePrivate) { } InstallableFile::InstallableFile(const InstallableFile &other) : d(other.d) { } InstallableFile &InstallableFile::operator=(const InstallableFile &other) { d = other.d; return *this; } InstallableFile::~InstallableFile() { } /*! * \brief Returns true if and only if this object holds data that was initialized by Qbs. */ bool InstallableFile::isValid() const { return d->isValid; } /*! * \brief The location of the file from which it will be copied to \c targetFilePath() * on installation. */ QString InstallableFile::sourceFilePath() const { return d->sourceFilePath; } /*! * \brief The file path that this file will be copied to on installation. */ QString InstallableFile::targetFilePath() const { return d->targetFilePath; } /*! * \brief The file's tags. */ QStringList InstallableFile::fileTags() const { return d->fileTags; } /*! * \brief True if and only if the file is an executable. */ bool InstallableFile::isExecutable() const { return d->fileTags.contains(QLatin1String("application")); } bool operator==(const InstallableFile &file1, const InstallableFile &file2) { return file1.sourceFilePath() == file2.sourceFilePath() && file1.targetFilePath() == file2.targetFilePath() && file1.fileTags() == file2.fileTags(); } bool operator!=(const InstallableFile &file1, const InstallableFile &file2) { return !(file1 == file2); } bool operator<(const InstallableFile &file1, const InstallableFile &file2) { return file1.sourceFilePath() < file2.sourceFilePath(); } /*! * \class ProductData * \brief The \c ProductData class corresponds to the Product item in a qbs source file. */ ProductData::ProductData() : d(new Internal::ProductDataPrivate) { } ProductData::ProductData(const ProductData &other) : d(other.d) { } ProductData &ProductData::operator=(const ProductData &other) { d = other.d; return *this; } ProductData::~ProductData() { } /*! * \brief Returns true if and only if the Product holds data that was initialized by Qbs. */ bool ProductData::isValid() const { return d->isValid; } /*! * \brief The product type, which is the list of file tags matching the product's target artifacts. */ QStringList ProductData::type() const { return d->type; } /*! * \brief The names of dependent products. */ QStringList ProductData::dependencies() const { return d->dependencies; } /*! * \brief The name of the product as given in the qbs source file. */ QString ProductData::name() const { return d->name; } /*! * \brief The base name of the product's target file as given in the qbs source file. */ QString ProductData::targetName() const { return d->targetName; } /*! * \brief The version number of the product. */ QString ProductData::version() const { return d->version; } /*! * \brief The profile this product will be built for. */ QString ProductData::profile() const { return d->profile; } /*! * \brief The location at which the product is defined in the source file. */ CodeLocation ProductData::location() const { return d->location; } /*! * \brief This product's target artifacts. */ QList ProductData::targetArtifacts() const { return d->targetArtifacts; } /*! * \brief The list of \c GroupData in this product. */ QList ProductData::groups() const { return d->groups; } /*! * \brief The product properties. */ QVariantMap ProductData::properties() const { return d->properties; } /*! * \brief The set of properties inherited from dependent products and modules. */ PropertyMap ProductData::moduleProperties() const { return d->moduleProperties; } /*! * \brief Returns true if this Product is enabled in Qbs. * This method returns the \c condition property of the \c Product definition. If a product is * enabled, then it will be built in the current configuration. * \sa GroupData::isEnabled() */ bool ProductData::isEnabled() const { QBS_ASSERT(isValid(), return false); return d->isEnabled; } bool ProductData::isRunnable() const { QBS_ASSERT(isValid(), return false); return d->isRunnable; } bool operator==(const ProductData &lhs, const ProductData &rhs) { if (!lhs.isValid() && !rhs.isValid()) return true; return lhs.isValid() == rhs.isValid() && lhs.name() == rhs.name() && lhs.targetName() == rhs.targetName() && lhs.type() == rhs.type() && lhs.version() == rhs.version() && lhs.dependencies() == rhs.dependencies() && lhs.profile() == rhs.profile() && lhs.location() == rhs.location() && lhs.groups() == rhs.groups() && lhs.targetArtifacts() == rhs.targetArtifacts() && lhs.properties() == rhs.properties() && lhs.isEnabled() == rhs.isEnabled(); } bool operator!=(const ProductData &lhs, const ProductData &rhs) { return !(lhs == rhs); } bool operator<(const ProductData &lhs, const ProductData &rhs) { const int nameCmp = lhs.name().compare(rhs.name()); if (nameCmp < 0) return true; if (nameCmp > 0) return false; return lhs.profile() < rhs.profile(); } /*! * \class ProjectData * \brief The \c ProjectData class corresponds to the \c Project item in a qbs source file. */ /*! * \fn QList ProjectData::products() const * \brief The products in this project. */ ProjectData::ProjectData() : d(new Internal::ProjectDataPrivate) { } ProjectData::ProjectData(const ProjectData &other) : d(other.d) { } ProjectData &ProjectData::operator =(const ProjectData &other) { d = other.d; return *this; } ProjectData::~ProjectData() { } /*! * \brief Returns true if and only if the Project holds data that was initialized by Qbs. */ bool ProjectData::isValid() const { return d->isValid; } /*! * \brief The name of this project. */ QString ProjectData::name() const { return d->name; } /*! * \brief The location at which the project is defined in a qbs source file. */ CodeLocation ProjectData::location() const { return d->location; } /*! * \brief Whether the project is enabled. * \note Disabled projects never have any products or sub-projects. */ bool ProjectData::isEnabled() const { QBS_ASSERT(isValid(), return false); return d->enabled; } /*! * \brief The base directory under which the build artifacts of this project will be created. * This is only valid for the top-level project. */ QString ProjectData::buildDirectory() const { return d->buildDir; } /*! * The products in this project. * \note This also includes disabled products. */ QList ProjectData::products() const { return d->products; } /*! * The sub-projects of this project. */ QList ProjectData::subProjects() const { return d->subProjects; } /*! * All products in this projects and its direct and indirect sub-projects. */ QList ProjectData::allProducts() const { QList productList = products(); foreach (const ProjectData &pd, subProjects()) productList << pd.allProducts(); return productList; } bool operator==(const ProjectData &lhs, const ProjectData &rhs) { if (!lhs.isValid() && !rhs.isValid()) return true; return lhs.isValid() == rhs.isValid() && lhs.isEnabled() == rhs.isEnabled() && lhs.name() == rhs.name() && lhs.buildDirectory() == rhs.buildDirectory() && lhs.location() == rhs.location() && lhs.subProjects() == rhs.subProjects() && lhs.products() == rhs.products(); } bool operator!=(const ProjectData &lhs, const ProjectData &rhs) { return !(lhs == rhs); } bool operator<(const ProjectData &lhs, const ProjectData &rhs) { return lhs.name() < rhs.name(); } /*! * \class PropertyMap * \brief The \c PropertyMap class represents the properties of a group or a product. */ PropertyMap::PropertyMap() : d(new Internal::PropertyMapPrivate) { static Internal::PropertyMapPtr defaultInternalMap = Internal::PropertyMapInternal::create(); d->m_map = defaultInternalMap; } PropertyMap::PropertyMap(const PropertyMap &other) : d(new Internal::PropertyMapPrivate(*other.d)) { } PropertyMap::~PropertyMap() { delete d; } PropertyMap &PropertyMap::operator =(const PropertyMap &other) { delete d; d = new Internal::PropertyMapPrivate(*other.d); return *this; } /*! * \brief Returns the names of all properties. */ QStringList PropertyMap::allProperties() const { QStringList properties; for (QVariantMap::ConstIterator it = d->m_map->value().constBegin(); it != d->m_map->value().constEnd(); ++it) { if (!it.value().canConvert()) properties << it.key(); } return properties; } /*! * \brief Returns the value of the given property of a product or group. */ QVariant PropertyMap::getProperty(const QString &name) const { return d->m_map->value().value(name); } /*! * \brief Returns the values of the given module property. * This function is intended for properties of list type, such as "cpp.includes". * The values will be gathered both directly from the product/group as well as from the * product's module dependencies. */ QVariantList PropertyMap::getModuleProperties(const QString &moduleName, const QString &propertyName) const { return Internal::PropertyFinder().propertyValues(d->m_map->value(), moduleName, propertyName); } /*! * \brief Convenience function for \c PropertyMap::getModuleProperties. */ QStringList PropertyMap::getModulePropertiesAsStringList(const QString &moduleName, const QString &propertyName) const { const QVariantList &vl = getModuleProperties(moduleName, propertyName); QStringList sl; foreach (const QVariant &v, vl) { QBS_ASSERT(v.canConvert(), continue); sl << v.toString(); } return sl; } /*! * \brief Returns the value of the given module property. * This function is intended for properties of "integral" type, such as "qbs.targetOS". * The property will be looked up first at the product or group itself. If it is not found there, * the module dependencies are searched in undefined order. */ QVariant PropertyMap::getModuleProperty(const QString &moduleName, const QString &propertyName) const { return Internal::PropertyFinder().propertyValue(d->m_map->value(), moduleName, propertyName); } static QString mapToString(const QVariantMap &map, const QString &prefix) { QStringList keys(map.keys()); qSort(keys); QString stringRep; foreach (const QString &key, keys) { const QVariant &val = map.value(key); if (val.type() == QVariant::Map) { stringRep += mapToString(val.value(), prefix + key + QLatin1Char('.')); } else { stringRep += QString::fromLocal8Bit("%1%2: %3\n") .arg(prefix, key, toJSLiteral(val)); } } return stringRep; } QString PropertyMap::toString() const { return mapToString(d->m_map->value(), QString()); } bool operator==(const PropertyMap &pm1, const PropertyMap &pm2) { return pm1.d->m_map->value() == pm2.d->m_map->value(); } bool operator!=(const PropertyMap &pm1, const PropertyMap &pm2) { return !(pm1.d->m_map->value() == pm2.d->m_map->value()); } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/api/projectdata.h000066400000000000000000000174351266132464200213110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROJECTDATA_H #define QBS_PROJECTDATA_H #include "../tools/codelocation.h" #include "../tools/qbs_export.h" #include #include #include #include #include #include namespace qbs { namespace Internal { class GroupDataPrivate; class InstallableFilePrivate; class ProductDataPrivate; class ProjectPrivate; class ProjectDataPrivate; class PropertyMapPrivate; class SourceArtifactPrivate; class TargetArtifactPrivate; } // namespace Internal class PropertyMap; bool operator==(const PropertyMap &pm1, const PropertyMap &pm2); bool operator!=(const PropertyMap &pm1, const PropertyMap &pm2); class QBS_EXPORT PropertyMap { friend class Internal::ProjectPrivate; friend bool operator==(const PropertyMap &, const PropertyMap &); friend bool operator!=(const PropertyMap &, const PropertyMap &); public: PropertyMap(); PropertyMap(const PropertyMap &other); ~PropertyMap(); PropertyMap &operator =(const PropertyMap &other); QStringList allProperties() const; QVariant getProperty(const QString &name) const; QVariantList getModuleProperties(const QString &moduleName, const QString &propertyName) const; QStringList getModulePropertiesAsStringList(const QString &moduleName, const QString &propertyName) const; QVariant getModuleProperty(const QString &moduleName, const QString &propertyName) const; // For debugging. QString toString() const; private: Internal::PropertyMapPrivate *d; }; class QBS_EXPORT SourceArtifact { friend class Internal::ProjectPrivate; public: SourceArtifact(); SourceArtifact(const SourceArtifact &other); SourceArtifact &operator=(const SourceArtifact &other); ~SourceArtifact(); bool isValid() const; QString filePath() const; QStringList fileTags() const; private: QExplicitlySharedDataPointer d; }; QBS_EXPORT bool operator==(const SourceArtifact &ta1, const SourceArtifact &ta2); QBS_EXPORT bool operator!=(const SourceArtifact &ta1, const SourceArtifact &ta2); QBS_EXPORT bool operator<(const SourceArtifact &ta1, const SourceArtifact &ta2); class QBS_EXPORT GroupData { friend class Internal::ProjectPrivate; public: GroupData(); GroupData(const GroupData &other); GroupData &operator=(const GroupData &other); ~GroupData(); bool isValid() const; CodeLocation location() const; QString name() const; QList sourceArtifacts() const; QList sourceArtifactsFromWildcards() const; QList allSourceArtifacts() const; PropertyMap properties() const; bool isEnabled() const; QStringList allFilePaths() const; private: QExplicitlySharedDataPointer d; }; QBS_EXPORT bool operator==(const GroupData &lhs, const GroupData &rhs); QBS_EXPORT bool operator!=(const GroupData &lhs, const GroupData &rhs); QBS_EXPORT bool operator<(const GroupData &lhs, const GroupData &rhs); class QBS_EXPORT TargetArtifact { friend class Internal::ProjectPrivate; public: TargetArtifact(); TargetArtifact(const TargetArtifact &other); TargetArtifact &operator=(const TargetArtifact &other); ~TargetArtifact(); bool isValid() const; QString filePath() const; QStringList fileTags() const; bool isExecutable() const; PropertyMap properties() const; private: QExplicitlySharedDataPointer d; }; QBS_EXPORT bool operator==(const TargetArtifact &ta1, const TargetArtifact &ta2); QBS_EXPORT bool operator!=(const TargetArtifact &ta1, const TargetArtifact &ta2); QBS_EXPORT bool operator<(const TargetArtifact &ta1, const TargetArtifact &ta2); class QBS_EXPORT InstallableFile { friend class Project; public: InstallableFile(); InstallableFile(const InstallableFile &other); InstallableFile &operator=(const InstallableFile &other); ~InstallableFile(); bool isValid() const; QString sourceFilePath() const; QString targetFilePath() const; QStringList fileTags() const; bool isExecutable() const; private: QExplicitlySharedDataPointer d; }; QBS_EXPORT bool operator==(const InstallableFile &file1, const InstallableFile &file2); QBS_EXPORT bool operator!=(const InstallableFile &file1, const InstallableFile &file2); QBS_EXPORT bool operator<(const InstallableFile &file1, const InstallableFile &file2); class QBS_EXPORT ProductData { friend class Internal::ProjectPrivate; public: ProductData(); ProductData(const ProductData &other); ProductData &operator=(const ProductData &other); ~ProductData(); bool isValid() const; QStringList type() const; QStringList dependencies() const; QString name() const; QString targetName() const; QString version() const; QString profile() const; CodeLocation location() const; QList targetArtifacts() const; QList groups() const; QVariantMap properties() const; PropertyMap moduleProperties() const; bool isEnabled() const; bool isRunnable() const; private: QExplicitlySharedDataPointer d; }; QBS_EXPORT bool operator==(const ProductData &lhs, const ProductData &rhs); QBS_EXPORT bool operator!=(const ProductData &lhs, const ProductData &rhs); QBS_EXPORT bool operator<(const ProductData &lhs, const ProductData &rhs); class QBS_EXPORT ProjectData { friend class Internal::ProjectPrivate; public: ProjectData(); ProjectData(const ProjectData &other); ProjectData &operator=(const ProjectData &other); ~ProjectData(); bool isValid() const; QString name() const; CodeLocation location() const; bool isEnabled() const; QString buildDirectory() const; QList products() const; QList subProjects() const; QList allProducts() const; private: QExplicitlySharedDataPointer d; }; QBS_EXPORT bool operator==(const ProjectData &lhs, const ProjectData &rhs); QBS_EXPORT bool operator!=(const ProjectData &lhs, const ProjectData &rhs); QBS_EXPORT bool operator<(const ProjectData &lhs, const ProjectData &rhs); } // namespace qbs #endif // QBS_PROJECTDATA_H qbs-src-1.4.5/src/lib/corelib/api/projectdata_p.h000066400000000000000000000065131266132464200216230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROJECTDATA_P_H #define QBS_PROJECTDATA_P_H #include "projectdata.h" #include namespace qbs { namespace Internal { class GroupDataPrivate : public QSharedData { public: GroupDataPrivate() : isValid(false) { } QString name; CodeLocation location; QList sourceArtifacts; QList sourceArtifactsFromWildcards; PropertyMap properties; bool isEnabled; bool isValid; }; class SourceArtifactPrivate : public QSharedData { public: SourceArtifactPrivate() : isValid(false) {} QString filePath; QStringList fileTags; bool isValid; }; class TargetArtifactPrivate : public QSharedData { public: TargetArtifactPrivate() : isValid(false) {} QString filePath; QStringList fileTags; PropertyMap properties; bool isValid; }; class InstallableFilePrivate: public QSharedData { public: InstallableFilePrivate() : isValid(false) {} QString sourceFilePath; QString targetFilePath; QStringList fileTags; bool isValid; }; class ProductDataPrivate : public QSharedData { public: ProductDataPrivate() : isValid(false) { } QStringList type; QStringList dependencies; QString name; QString targetName; QString version; QString profile; CodeLocation location; QList groups; QVariantMap properties; PropertyMap moduleProperties; QList targetArtifacts; bool isEnabled; bool isRunnable; bool isValid; }; class ProjectDataPrivate : public QSharedData { public: ProjectDataPrivate() : isValid(false) { } QString name; CodeLocation location; bool enabled; bool isValid; QList products; QList subProjects; QString buildDir; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.4.5/src/lib/corelib/api/projectfileupdater.cpp000066400000000000000000000517551266132464200232420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "projectfileupdater.h" #include "projectdata.h" #include "qmljsrewriter.h" #include #include #include #include #include #include #include #include #include #include #include using namespace QbsQmlJS; using namespace AST; namespace qbs { namespace Internal { class ItemFinder : public Visitor { public: ItemFinder(const CodeLocation &cl) : m_cl(cl), m_item(0) { } UiObjectDefinition *item() const { return m_item; } private: bool visit(UiObjectDefinition *ast) { if (toCodeLocation(m_cl.filePath(), ast->firstSourceLocation()) == m_cl) { m_item = ast; return false; } return true; } const CodeLocation m_cl; UiObjectDefinition *m_item; }; class FilesBindingFinder : public Visitor { public: FilesBindingFinder(const UiObjectDefinition *startItem) : m_startItem(startItem), m_binding(0) { } UiScriptBinding *binding() const { return m_binding; } private: bool visit(UiObjectDefinition *ast) { // We start with the direct parent of the binding, so do not descend into any // other item. return ast == m_startItem; } bool visit(UiScriptBinding *ast) { if (ast->qualifiedId->name.toString() != QLatin1String("files")) return true; m_binding = ast; return false; } const UiObjectDefinition * const m_startItem; UiScriptBinding *m_binding; }; ProjectFileUpdater::ProjectFileUpdater(const QString &projectFile) : m_projectFile(projectFile) { } ProjectFileUpdater::LineEndingType ProjectFileUpdater::guessLineEndingType(const QByteArray &text) { char before = 0; int lfCount = 0; int crlfCount = 0; int i = text.indexOf('\n'); while (i != -1) { if (i > 0) before = text.at(i - 1); if (before == '\r') ++crlfCount; else ++lfCount; i = text.indexOf('\n', i + 1); } if (lfCount == 0 && crlfCount == 0) return UnknownLineEndings; if (crlfCount == 0) return UnixLineEndings; if (lfCount == 0) return WindowsLineEndings; return MixedLineEndings; } void ProjectFileUpdater::convertToUnixLineEndings(QByteArray *text, LineEndingType oldLineEndings) { if (oldLineEndings == UnixLineEndings) return; text->replace("\r\n", "\n"); } void ProjectFileUpdater::convertFromUnixLineEndings(QByteArray *text, LineEndingType newLineEndings) { if (newLineEndings == WindowsLineEndings || (newLineEndings != UnixLineEndings && HostOsInfo::isWindowsHost())) { text->replace('\n', "\r\n"); } } void ProjectFileUpdater::apply() { QFile file(m_projectFile); if (!file.open(QFile::ReadOnly)) { throw ErrorInfo(Tr::tr("File '%1' cannot be opened for reading: %2") .arg(m_projectFile, file.errorString())); } QByteArray rawContent = file.readAll(); const LineEndingType origLineEndingType = guessLineEndingType(rawContent); convertToUnixLineEndings(&rawContent, origLineEndingType); QString content = QString::fromLocal8Bit(rawContent); file.close(); Engine engine; Lexer lexer(&engine); lexer.setCode(content, 1); Parser parser(&engine); if (!parser.parse()) { QList parserMessages = parser.diagnosticMessages(); if (!parserMessages.isEmpty()) { ErrorInfo errorInfo; errorInfo.append(Tr::tr("Failure parsing project file.")); foreach (const DiagnosticMessage &msg, parserMessages) errorInfo.append(msg.message, toCodeLocation(file.fileName(), msg.loc)); throw errorInfo; } } doApply(content, parser.ast()); if (!file.open(QFile::WriteOnly)) { throw ErrorInfo(Tr::tr("File '%1' cannot be opened for writing: %2") .arg(m_projectFile, file.errorString())); } file.resize(0); rawContent = content.toLocal8Bit(); convertFromUnixLineEndings(&rawContent, origLineEndingType); file.write(rawContent); } ProjectFileGroupInserter::ProjectFileGroupInserter(const ProductData &product, const QString &groupName) : ProjectFileUpdater(product.location().filePath()) , m_product(product) , m_groupName(groupName) { } void ProjectFileGroupInserter::doApply(QString &fileContent, UiProgram *ast) { ItemFinder itemFinder(m_product.location()); ast->accept(&itemFinder); if (!itemFinder.item()) { throw ErrorInfo(Tr::tr("The project file parser failed to find the product item."), CodeLocation(projectFile())); } ChangeSet changeSet; Rewriter rewriter(fileContent, &changeSet, QStringList()); QString groupItemString; const int productItemIndentation = itemFinder.item()->qualifiedTypeNameId->firstSourceLocation().startColumn - 1; const int groupItemIndentation = productItemIndentation + 4; const QString groupItemIndentationString = QString(groupItemIndentation, QLatin1Char(' ')); groupItemString += groupItemIndentationString + QLatin1String("Group {\n"); groupItemString += groupItemIndentationString + groupItemIndentationString + QLatin1String("name: \"") + m_groupName + QLatin1String("\"\n"); groupItemString += groupItemIndentationString + groupItemIndentationString + QLatin1String("files: []\n"); groupItemString += groupItemIndentationString + QLatin1Char('}'); rewriter.addObject(itemFinder.item()->initializer, groupItemString); int lineOffset = 3 + 1; // Our text + a leading newline that is always added by the rewriter. const QList &editOps = changeSet.operationList(); QBS_CHECK(editOps.count() == 1); const ChangeSet::EditOp &insertOp = editOps.first(); setLineOffset(lineOffset); int insertionLine = fileContent.left(insertOp.pos1).count(QLatin1Char('\n')); for (int i = 0; i < insertOp.text.count() && insertOp.text.at(i) == QLatin1Char('\n'); ++i) ++insertionLine; // To account for newlines prepended by the rewriter. ++insertionLine; // To account for zero-based indexing. setItemPosition(CodeLocation(projectFile(), insertionLine, groupItemIndentation + 1)); changeSet.apply(&fileContent); } static QString getNodeRepresentation(const QString &fileContent, const Node *node) { const quint32 start = node->firstSourceLocation().offset; const quint32 end = node->lastSourceLocation().end(); return fileContent.mid(start, end - start); } static const ChangeSet::EditOp &getEditOp(const ChangeSet &changeSet) { const QList &editOps = changeSet.operationList(); QBS_CHECK(editOps.count() == 1); return editOps.first(); } static int getLineOffsetForChangedBinding(const ChangeSet &changeSet, const QString &oldRhs) { return getEditOp(changeSet).text.count(QLatin1Char('\n')) - oldRhs.count(QLatin1Char('\n')); } static int getBindingLine(const ChangeSet &changeSet, const QString &fileContent) { return fileContent.left(getEditOp(changeSet).pos1 + 1).count(QLatin1Char('\n')) + 1; } ProjectFileFilesAdder::ProjectFileFilesAdder(const ProductData &product, const GroupData &group, const QStringList &files) : ProjectFileUpdater(product.location().filePath()) , m_product(product) , m_group(group) , m_files(files) { } static QString &addToFilesRepr(QString &filesRepr, const QString &fileRepr, int indentation) { filesRepr += QString(indentation, QLatin1Char(' ')); filesRepr += fileRepr; filesRepr += QLatin1String(",\n"); return filesRepr; } static QString &addToFilesRepr(QString &filesRepr, const QStringList &filePaths, int indentation) { foreach (const QString &f, filePaths) addToFilesRepr(filesRepr, toJSLiteral(f), indentation); return filesRepr; } static QString &completeFilesRepr(QString &filesRepr, int indentation) { return filesRepr.prepend(QLatin1String("[\n")).append(QString(indentation, QLatin1Char(' '))) .append(QLatin1Char(']')); } void ProjectFileFilesAdder::doApply(QString &fileContent, UiProgram *ast) { if (m_files.isEmpty()) return; QStringList sortedFiles = m_files; sortedFiles.sort(); // Find the item containing the "files" binding. ItemFinder itemFinder(m_group.isValid() ? m_group.location() : m_product.location()); ast->accept(&itemFinder); if (!itemFinder.item()) { throw ErrorInfo(Tr::tr("The project file parser failed to find the item."), CodeLocation(projectFile())); } const int itemIndentation = itemFinder.item()->qualifiedTypeNameId->firstSourceLocation().startColumn - 1; const int bindingIndentation = itemIndentation + 4; const int arrayElemIndentation = bindingIndentation + 4; // Now get the binding itself. FilesBindingFinder bindingFinder(itemFinder.item()); itemFinder.item()->accept(&bindingFinder); ChangeSet changeSet; Rewriter rewriter(fileContent, &changeSet, QStringList()); UiScriptBinding * const filesBinding = bindingFinder.binding(); if (filesBinding) { QString filesRepresentation; if (filesBinding->statement->kind != Node::Kind_ExpressionStatement) throw ErrorInfo(Tr::tr("JavaScript construct in source file is too complex.")); // TODO: rename, add new and concat. const ExpressionStatement * const exprStatement = static_cast(filesBinding->statement); switch (exprStatement->expression->kind) { case Node::Kind_ArrayLiteral: { const ElementList *elem = static_cast(exprStatement->expression)->elements; QStringList oldFileReprs; while (elem) { oldFileReprs << getNodeRepresentation(fileContent, elem->expression); elem = elem->next; } // Insert new files "sorted", but do not change the order of existing files. const QString firstNewFileRepr = toJSLiteral(sortedFiles.first()); while (!oldFileReprs.isEmpty()) { if (oldFileReprs.first() > firstNewFileRepr) break; addToFilesRepr(filesRepresentation, oldFileReprs.takeFirst(), arrayElemIndentation); } addToFilesRepr(filesRepresentation, sortedFiles, arrayElemIndentation); while (!oldFileReprs.isEmpty()) addToFilesRepr(filesRepresentation, oldFileReprs.takeFirst(), arrayElemIndentation); completeFilesRepr(filesRepresentation, bindingIndentation); break; } case Node::Kind_StringLiteral: { const QString existingElement = static_cast(exprStatement->expression)->value.toString(); sortedFiles << existingElement; sortedFiles.sort(); addToFilesRepr(filesRepresentation, sortedFiles, arrayElemIndentation); completeFilesRepr(filesRepresentation, bindingIndentation); break; } default: { // Note that we can often do better than simply concatenating: For instance, // in the case where the existing list is of the form ["a", "b"].concat(myProperty), // we could keep on parsing until we find the array literal and then merge it with // the new files, preventing cascading concat() calls. // But this is not essential and can be implemented when we have some downtime. const QString rhsRepr = getNodeRepresentation(fileContent, exprStatement->expression); addToFilesRepr(filesRepresentation, sortedFiles, arrayElemIndentation); completeFilesRepr(filesRepresentation, bindingIndentation); // It cannot be the other way around, since the existing right-hand side could // have string type. filesRepresentation += QString::fromLatin1(".concat(%1)").arg(rhsRepr); } } rewriter.changeBinding(itemFinder.item()->initializer, QLatin1String("files"), filesRepresentation, Rewriter::ScriptBinding); } else { // Can happen for the product itself, for which the "files" binding is not mandatory. QString filesRepresentation; addToFilesRepr(filesRepresentation, sortedFiles, arrayElemIndentation); completeFilesRepr(filesRepresentation, bindingIndentation); const QString bindingString = QString(bindingIndentation, QLatin1Char(' ')) + QLatin1String("files"); rewriter.addBinding(itemFinder.item()->initializer, bindingString, filesRepresentation, Rewriter::ScriptBinding); } setLineOffset(getLineOffsetForChangedBinding(changeSet, filesBinding ? getNodeRepresentation(fileContent, filesBinding->statement) : QString())); const int insertionLine = getBindingLine(changeSet, fileContent); const int insertionColumn = (filesBinding ? arrayElemIndentation : bindingIndentation) + 1; setItemPosition(CodeLocation(projectFile(), insertionLine, insertionColumn)); changeSet.apply(&fileContent); } ProjectFileFilesRemover::ProjectFileFilesRemover(const ProductData &product, const GroupData &group, const QStringList &files) : ProjectFileUpdater(product.location().filePath()) , m_product(product) , m_group(group) , m_files(files) { } void ProjectFileFilesRemover::doApply(QString &fileContent, UiProgram *ast) { if (m_files.isEmpty()) return; // Find the item containing the "files" binding. ItemFinder itemFinder(m_group.isValid() ? m_group.location() : m_product.location()); ast->accept(&itemFinder); if (!itemFinder.item()) { throw ErrorInfo(Tr::tr("The project file parser failed to find the item."), CodeLocation(projectFile())); } // Now get the binding itself. FilesBindingFinder bindingFinder(itemFinder.item()); itemFinder.item()->accept(&bindingFinder); if (!bindingFinder.binding()) { throw ErrorInfo(Tr::tr("Could not find the 'files' binding in the project file."), m_product.location()); } if (bindingFinder.binding()->statement->kind != Node::Kind_ExpressionStatement) throw ErrorInfo(Tr::tr("JavaScript construct in source file is too complex.")); const CodeLocation bindingLocation = toCodeLocation(projectFile(), bindingFinder.binding()->firstSourceLocation()); ChangeSet changeSet; Rewriter rewriter(fileContent, &changeSet, QStringList()); const int itemIndentation = itemFinder.item()->qualifiedTypeNameId->firstSourceLocation().startColumn - 1; const int bindingIndentation = itemIndentation + 4; const int arrayElemIndentation = bindingIndentation + 4; const ExpressionStatement * const exprStatement = static_cast(bindingFinder.binding()->statement); switch (exprStatement->expression->kind) { case Node::Kind_ArrayLiteral: { QStringList filesToRemove = m_files; QStringList newFilesList; const ElementList *elem = static_cast(exprStatement->expression)->elements; while (elem) { if (elem->expression->kind != Node::Kind_StringLiteral) { throw ErrorInfo(Tr::tr("JavaScript construct in source file is too complex."), bindingLocation); } const QString existingFile = static_cast(elem->expression)->value.toString(); if (!filesToRemove.removeOne(existingFile)) newFilesList << existingFile; elem = elem->next; } if (!filesToRemove.isEmpty()) { throw ErrorInfo(Tr::tr("The following files were not found in the 'files' list: %1") .arg(filesToRemove.join(QLatin1String(", "))), bindingLocation); } QString filesString = QLatin1String("[\n"); foreach (const QString &file, newFilesList) { filesString += QString(arrayElemIndentation, QLatin1Char(' ')); filesString += QString::fromLocal8Bit("\"%1\",\n").arg(file); } filesString += QString(bindingIndentation, QLatin1Char(' ')); filesString += QLatin1Char(']'); rewriter.changeBinding(itemFinder.item()->initializer, QLatin1String("files"), filesString, Rewriter::ScriptBinding); break; } case Node::Kind_StringLiteral: { if (m_files.count() != 1) { throw ErrorInfo(Tr::tr("Was requested to remove %1 files, but there is only " "one in the list.").arg(m_files.count()), bindingLocation); } const QString existingFile = static_cast(exprStatement->expression)->value.toString(); if (existingFile != m_files.first()) { throw ErrorInfo(Tr::tr("File '%1' could not be found in the 'files' list.") .arg(m_files.first()), bindingLocation); } rewriter.changeBinding(itemFinder.item()->initializer, QLatin1String("files"), QLatin1String("[]"), Rewriter::ScriptBinding); break; } default: throw ErrorInfo(Tr::tr("JavaScript construct in source file is too complex."), bindingLocation); } setLineOffset(getLineOffsetForChangedBinding(changeSet, getNodeRepresentation(fileContent, exprStatement->expression))); const int bindingLine = getBindingLine(changeSet, fileContent); const int bindingColumn = (bindingFinder.binding() ? arrayElemIndentation : bindingIndentation) + 1; setItemPosition(CodeLocation(projectFile(), bindingLine, bindingColumn)); changeSet.apply(&fileContent); } ProjectFileGroupRemover::ProjectFileGroupRemover(const ProductData &product, const GroupData &group) : ProjectFileUpdater(product.location().filePath()) , m_product(product) , m_group(group) { } void ProjectFileGroupRemover::doApply(QString &fileContent, UiProgram *ast) { ItemFinder productFinder(m_product.location()); ast->accept(&productFinder); if (!productFinder.item()) { throw ErrorInfo(Tr::tr("The project file parser failed to find the product item."), CodeLocation(projectFile())); } ItemFinder groupFinder(m_group.location()); productFinder.item()->accept(&groupFinder); if (!groupFinder.item()) { throw ErrorInfo(Tr::tr("The project file parser failed to find the group item."), m_product.location()); } ChangeSet changeSet; Rewriter rewriter(fileContent, &changeSet, QStringList()); rewriter.removeObjectMember(groupFinder.item(), productFinder.item()); setItemPosition(m_group.location()); const QList &editOps = changeSet.operationList(); QBS_CHECK(editOps.count() == 1); const ChangeSet::EditOp &op = editOps.first(); const QString removedText = fileContent.mid(op.pos1, op.length1); setLineOffset(-removedText.count(QLatin1Char('\n'))); changeSet.apply(&fileContent); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/api/projectfileupdater.h000066400000000000000000000102231266132464200226700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROJECTFILEUPDATER_H #define QBS_PROJECTFILEUPDATER_H #include "projectdata.h" #include #include #include namespace QbsQmlJS { namespace AST { class UiProgram; } } namespace qbs { namespace Internal { class ProjectFileUpdater { public: void apply(); CodeLocation itemPosition() const { return m_itemPosition; } int lineOffset() const { return m_lineOffset; } protected: ProjectFileUpdater(const QString &projectFile); QString projectFile() const { return m_projectFile; } void setLineOffset(int offset) { m_lineOffset = offset; } void setItemPosition(const CodeLocation &cl) { m_itemPosition = cl; } private: virtual void doApply(QString &fileContent, QbsQmlJS::AST::UiProgram *ast) = 0; enum LineEndingType { UnknownLineEndings, UnixLineEndings, WindowsLineEndings, MixedLineEndings }; static LineEndingType guessLineEndingType(const QByteArray &text); static void convertToUnixLineEndings(QByteArray *text, LineEndingType oldLineEndings); static void convertFromUnixLineEndings(QByteArray *text, LineEndingType newLineEndings); const QString m_projectFile; CodeLocation m_itemPosition; int m_lineOffset; }; class ProjectFileGroupInserter : public ProjectFileUpdater { public: ProjectFileGroupInserter(const ProductData &product, const QString &groupName); private: void doApply(QString &fileContent, QbsQmlJS::AST::UiProgram *ast); const ProductData m_product; const QString m_groupName; }; class ProjectFileFilesAdder : public ProjectFileUpdater { public: ProjectFileFilesAdder(const ProductData &product, const GroupData &group, const QStringList &files); private: void doApply(QString &fileContent, QbsQmlJS::AST::UiProgram *ast); const ProductData m_product; const GroupData m_group; const QStringList m_files; }; class ProjectFileFilesRemover : public ProjectFileUpdater { public: ProjectFileFilesRemover(const ProductData &product, const GroupData &group, const QStringList &files); private: void doApply(QString &fileContent, QbsQmlJS::AST::UiProgram *ast); const ProductData m_product; const GroupData m_group; const QStringList m_files; }; class ProjectFileGroupRemover : public ProjectFileUpdater { public: ProjectFileGroupRemover(const ProductData &product, const GroupData &group); private: void doApply(QString &fileContent, QbsQmlJS::AST::UiProgram *ast); const ProductData m_product; const GroupData m_group; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.4.5/src/lib/corelib/api/propertymap_p.h000066400000000000000000000034001266132464200216750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROPERTYMAP_P_H #define QBS_PROPERTYMAP_P_H #include namespace qbs { namespace Internal { class PropertyMapPrivate { public: PropertyMapPtr m_map; }; } // namespace Internal } // namespace qbs #endif // QBS_PROPERTYMAP_P_H qbs-src-1.4.5/src/lib/corelib/api/qmljsrewriter.cpp000066400000000000000000000632411266132464200222520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "qmljsrewriter.h" #include #include #include #include namespace QbsQmlJS { using namespace AST; static QString toString(UiQualifiedId *qualifiedId, QChar delimiter = QLatin1Char('.')) { QString result; for (UiQualifiedId *iter = qualifiedId; iter; iter = iter->next) { if (iter != qualifiedId) result += delimiter; result += iter->name; } return result; } Rewriter::Rewriter(const QString &originalText, ChangeSet *changeSet, const QStringList &propertyOrder) : m_originalText(originalText) , m_changeSet(changeSet) , m_propertyOrder(propertyOrder) { Q_ASSERT(changeSet); } Rewriter::Range Rewriter::addBinding(AST::UiObjectInitializer *ast, const QString &propertyName, const QString &propertyValue, BindingType bindingType) { UiObjectMemberList *insertAfter = searchMemberToInsertAfter(ast->members, propertyName, m_propertyOrder); return addBinding(ast, propertyName, propertyValue, bindingType, insertAfter); } Rewriter::Range Rewriter::addBinding(AST::UiObjectInitializer *ast, const QString &propertyName, const QString &propertyValue, BindingType bindingType, UiObjectMemberList *insertAfter) { SourceLocation endOfPreviousMember; SourceLocation startOfNextMember; if (insertAfter == 0 || insertAfter->member == 0) { // insert as first member endOfPreviousMember = ast->lbraceToken; if (ast->members && ast->members->member) startOfNextMember = ast->members->member->firstSourceLocation(); else startOfNextMember = ast->rbraceToken; } else { endOfPreviousMember = insertAfter->member->lastSourceLocation(); if (insertAfter->next && insertAfter->next->member) startOfNextMember = insertAfter->next->member->firstSourceLocation(); else startOfNextMember = ast->rbraceToken; } const bool isOneLiner = endOfPreviousMember.startLine == startOfNextMember.startLine; bool needsPreceedingSemicolon = false; bool needsTrailingSemicolon = false; if (isOneLiner) { if (insertAfter == 0) { // we're inserting after an lbrace if (ast->members) { // we're inserting before a member (and not the rbrace) needsTrailingSemicolon = bindingType == ScriptBinding; } } else { // we're inserting after a member, not after the lbrace if (endOfPreviousMember.isValid()) { // there already is a semicolon after the previous member if (insertAfter->next && insertAfter->next->member) { // and the after us there is a member, not an rbrace, so: needsTrailingSemicolon = bindingType == ScriptBinding; } } else { // there is no semicolon after the previous member (probably because there is an rbrace after us/it, so: needsPreceedingSemicolon = true; } } } QString newPropertyTemplate; switch (bindingType) { case ArrayBinding: newPropertyTemplate = QLatin1String("%1: [\n%2\n]"); break; case ObjectBinding: newPropertyTemplate = QLatin1String("%1: %2"); break; case ScriptBinding: newPropertyTemplate = QLatin1String("%1: %2"); break; default: Q_ASSERT(!"unknown property type"); } if (isOneLiner) { if (needsPreceedingSemicolon) newPropertyTemplate.prepend(QLatin1Char(';')); newPropertyTemplate.prepend(QLatin1Char(' ')); if (needsTrailingSemicolon) newPropertyTemplate.append(QLatin1Char(';')); } else { newPropertyTemplate.prepend(QLatin1Char('\n')); } m_changeSet->insert(endOfPreviousMember.end(), newPropertyTemplate.arg(propertyName, propertyValue)); return Range(endOfPreviousMember.end(), endOfPreviousMember.end()); } UiObjectMemberList *Rewriter::searchMemberToInsertAfter(UiObjectMemberList *members, const QStringList &propertyOrder) { const int objectDefinitionInsertionPoint = propertyOrder.indexOf(QString()); UiObjectMemberList *lastObjectDef = 0; UiObjectMemberList *lastNonObjectDef = 0; for (UiObjectMemberList *iter = members; iter; iter = iter->next) { UiObjectMember *member = iter->member; int idx = -1; if (cast(member)) lastObjectDef = iter; else if (UiArrayBinding *arrayBinding = cast(member)) idx = propertyOrder.indexOf(toString(arrayBinding->qualifiedId)); else if (UiObjectBinding *objectBinding = cast(member)) idx = propertyOrder.indexOf(toString(objectBinding->qualifiedId)); else if (UiScriptBinding *scriptBinding = cast(member)) idx = propertyOrder.indexOf(toString(scriptBinding->qualifiedId)); else if (cast(member)) idx = propertyOrder.indexOf(QLatin1String("property")); if (idx < objectDefinitionInsertionPoint) lastNonObjectDef = iter; } if (lastObjectDef) return lastObjectDef; else return lastNonObjectDef; } UiArrayMemberList *Rewriter::searchMemberToInsertAfter(UiArrayMemberList *members, const QStringList &propertyOrder) { const int objectDefinitionInsertionPoint = propertyOrder.indexOf(QString()); UiArrayMemberList *lastObjectDef = 0; UiArrayMemberList *lastNonObjectDef = 0; for (UiArrayMemberList *iter = members; iter; iter = iter->next) { UiObjectMember *member = iter->member; int idx = -1; if (cast(member)) lastObjectDef = iter; else if (UiArrayBinding *arrayBinding = cast(member)) idx = propertyOrder.indexOf(toString(arrayBinding->qualifiedId)); else if (UiObjectBinding *objectBinding = cast(member)) idx = propertyOrder.indexOf(toString(objectBinding->qualifiedId)); else if (UiScriptBinding *scriptBinding = cast(member)) idx = propertyOrder.indexOf(toString(scriptBinding->qualifiedId)); else if (cast(member)) idx = propertyOrder.indexOf(QLatin1String("property")); if (idx < objectDefinitionInsertionPoint) lastNonObjectDef = iter; } if (lastObjectDef) return lastObjectDef; else return lastNonObjectDef; } UiObjectMemberList *Rewriter::searchMemberToInsertAfter(UiObjectMemberList *members, const QString &propertyName, const QStringList &propertyOrder) { if (!members) return 0; // empty members QHash orderedMembers; for (UiObjectMemberList *iter = members; iter; iter = iter->next) { UiObjectMember *member = iter->member; if (UiArrayBinding *arrayBinding = cast(member)) orderedMembers[toString(arrayBinding->qualifiedId)] = iter; else if (UiObjectBinding *objectBinding = cast(member)) orderedMembers[toString(objectBinding->qualifiedId)] = iter; else if (cast(member)) orderedMembers[QString::null] = iter; else if (UiScriptBinding *scriptBinding = cast(member)) orderedMembers[toString(scriptBinding->qualifiedId)] = iter; else if (cast(member)) orderedMembers[QLatin1String("property")] = iter; } int idx = propertyOrder.indexOf(propertyName); if (idx == -1) idx = propertyOrder.indexOf(QString()); if (idx == -1) idx = propertyOrder.size() - 1; for (; idx > 0; --idx) { const QString prop = propertyOrder.at(idx - 1); UiObjectMemberList *candidate = orderedMembers.value(prop, 0); if (candidate != 0) return candidate; } return 0; } void Rewriter::changeBinding(UiObjectInitializer *ast, const QString &propertyName, const QString &newValue, BindingType binding) { QString prefix, suffix; int dotIdx = propertyName.indexOf(QLatin1Char('.')); if (dotIdx != -1) { prefix = propertyName.left(dotIdx); suffix = propertyName.mid(dotIdx + 1); } for (UiObjectMemberList *members = ast->members; members; members = members->next) { UiObjectMember *member = members->member; // for non-grouped properties: if (isMatchingPropertyMember(propertyName, member)) { switch (binding) { case ArrayBinding: insertIntoArray(cast(member), newValue); break; case ObjectBinding: replaceMemberValue(member, newValue, false); break; case ScriptBinding: replaceMemberValue(member, newValue, nextMemberOnSameLine(members)); break; default: Q_ASSERT(!"Unhandled QmlRefactoring::PropertyType"); } break; // for grouped properties: } else if (!prefix.isEmpty()) { if (UiObjectDefinition *def = cast(member)) { if (toString(def->qualifiedTypeNameId) == prefix) changeBinding(def->initializer, suffix, newValue, binding); } } } } void Rewriter::replaceMemberValue(UiObjectMember *propertyMember, const QString &newValue, bool needsSemicolon) { QString replacement = newValue; int startOffset = -1; int endOffset = -1; if (UiObjectBinding *objectBinding = AST::cast(propertyMember)) { startOffset = objectBinding->qualifiedTypeNameId->identifierToken.offset; endOffset = objectBinding->initializer->rbraceToken.end(); } else if (UiScriptBinding *scriptBinding = AST::cast(propertyMember)) { startOffset = scriptBinding->statement->firstSourceLocation().offset; endOffset = scriptBinding->statement->lastSourceLocation().end(); } else if (UiArrayBinding *arrayBinding = AST::cast(propertyMember)) { startOffset = arrayBinding->lbracketToken.offset; endOffset = arrayBinding->rbracketToken.end(); } else if (UiPublicMember *publicMember = AST::cast(propertyMember)) { if (publicMember->statement) { startOffset = publicMember->statement->firstSourceLocation().offset; if (publicMember->semicolonToken.isValid()) endOffset = publicMember->semicolonToken.end(); else endOffset = publicMember->statement->lastSourceLocation().offset; } else { startOffset = publicMember->lastSourceLocation().end(); endOffset = startOffset; if (publicMember->semicolonToken.isValid()) startOffset = publicMember->semicolonToken.offset; replacement.prepend(QLatin1String(": ")); } } else { return; } if (needsSemicolon) replacement += QLatin1Char(';'); m_changeSet->replace(startOffset, endOffset, replacement); } bool Rewriter::isMatchingPropertyMember(const QString &propertyName, UiObjectMember *member) { if (UiPublicMember *publicMember = cast(member)) return publicMember->name == propertyName; else if (UiObjectBinding *objectBinding = cast(member)) return toString(objectBinding->qualifiedId) == propertyName; else if (UiScriptBinding *scriptBinding = cast(member)) return toString(scriptBinding->qualifiedId) == propertyName; else if (UiArrayBinding *arrayBinding = cast(member)) return toString(arrayBinding->qualifiedId) == propertyName; else return false; } bool Rewriter::nextMemberOnSameLine(UiObjectMemberList *members) { if (members && members->next && members->next->member) return members->next->member->firstSourceLocation().startLine == members->member->lastSourceLocation().startLine; else return false; } void Rewriter::insertIntoArray(UiArrayBinding *ast, const QString &newValue) { if (!ast) return; UiObjectMember *lastMember = 0; for (UiArrayMemberList *iter = ast->members; iter; iter = iter->next) { lastMember = iter->member; } if (!lastMember) return; const int insertionPoint = lastMember->lastSourceLocation().end(); m_changeSet->insert(insertionPoint, QLatin1String(",\n") + newValue); } void Rewriter::removeBindingByName(UiObjectInitializer *ast, const QString &propertyName) { QString prefix; int dotIdx = propertyName.indexOf(QLatin1Char('.')); if (dotIdx != -1) prefix = propertyName.left(dotIdx); for (UiObjectMemberList *it = ast->members; it; it = it->next) { UiObjectMember *member = it->member; // run full name match (for ungrouped properties): if (isMatchingPropertyMember(propertyName, member)) { removeMember(member); // check for grouped properties: } else if (!prefix.isEmpty()) { if (UiObjectDefinition *def = cast(member)) { if (toString(def->qualifiedTypeNameId) == prefix) removeGroupedProperty(def, propertyName); } } } } void Rewriter::removeGroupedProperty(UiObjectDefinition *ast, const QString &propertyName) { int dotIdx = propertyName.indexOf(QLatin1Char('.')); if (dotIdx == -1) return; const QString propName = propertyName.mid(dotIdx + 1); UiObjectMember *wanted = 0; unsigned memberCount = 0; for (UiObjectMemberList *it = ast->initializer->members; it; it = it->next) { ++memberCount; UiObjectMember *member = it->member; if (!wanted && isMatchingPropertyMember(propName, member)) wanted = member; } if (!wanted) return; if (memberCount == 1) removeMember(ast); else removeMember(wanted); } void Rewriter::removeMember(UiObjectMember *member) { int start = member->firstSourceLocation().offset; int end = member->lastSourceLocation().end(); includeSurroundingWhitespace(m_originalText, start, end); m_changeSet->remove(start, end); } bool Rewriter::includeSurroundingWhitespace(const QString &source, int &start, int &end) { bool includeStartingWhitespace = true; bool paragraphFound = false; bool paragraphSkipped = false; if (end >= 0) { QChar c = source.at(end); while (c.isSpace()) { ++end; if (c.unicode() == 10) { paragraphFound = true; paragraphSkipped = true; break; } else if (end == source.length()) { break; } c = source.at(end); } includeStartingWhitespace = paragraphFound; } paragraphFound = false; if (includeStartingWhitespace) { while (start > 0) { const QChar c = source.at(start - 1); if (c.unicode() == 10) { paragraphFound = true; break; } if (!c.isSpace()) break; --start; } } if (!paragraphFound && paragraphSkipped) //keep the line ending --end; return paragraphFound; } void Rewriter::includeLeadingEmptyLine(const QString &source, int &start) { QTextDocument doc(source); if (start == 0) return; if (doc.characterAt(start - 1) != QChar::ParagraphSeparator) return; QTextCursor tc(&doc); tc.setPosition(start); const int blockNr = tc.blockNumber(); if (blockNr == 0) return; const QTextBlock prevBlock = tc.block().previous(); const QString trimmedPrevBlockText = prevBlock.text().trimmed(); if (!trimmedPrevBlockText.isEmpty()) return; start = prevBlock.position(); } void Rewriter::includeEmptyGroupedProperty(UiObjectDefinition *groupedProperty, UiObjectMember *memberToBeRemoved, int &start, int &end) { if (groupedProperty->qualifiedTypeNameId && !groupedProperty->qualifiedTypeNameId->name.isEmpty() && groupedProperty->qualifiedTypeNameId->name.at(0).isLower()) { // grouped property UiObjectMemberList *memberIter = groupedProperty->initializer->members; while (memberIter) { if (memberIter->member != memberToBeRemoved) return; memberIter = memberIter->next; } start = groupedProperty->firstSourceLocation().begin(); end = groupedProperty->lastSourceLocation().end(); } } #if 0 UiObjectMemberList *QMLRewriter::searchMemberToInsertAfter(UiObjectMemberList *members, const QStringList &propertyOrder) { const int objectDefinitionInsertionPoint = propertyOrder.indexOf(QString::null); UiObjectMemberList *lastObjectDef = 0; UiObjectMemberList *lastNonObjectDef = 0; for (UiObjectMemberList *iter = members; iter; iter = iter->next) { UiObjectMember *member = iter->member; int idx = -1; if (cast(member)) lastObjectDef = iter; else if (UiArrayBinding *arrayBinding = cast(member)) idx = propertyOrder.indexOf(toString(arrayBinding->qualifiedId)); else if (UiObjectBinding *objectBinding = cast(member)) idx = propertyOrder.indexOf(toString(objectBinding->qualifiedId)); else if (UiScriptBinding *scriptBinding = cast(member)) idx = propertyOrder.indexOf(toString(scriptBinding->qualifiedId)); else if (cast(member)) idx = propertyOrder.indexOf(QLatin1String("property")); if (idx < objectDefinitionInsertionPoint) lastNonObjectDef = iter; } if (lastObjectDef) return lastObjectDef; else return lastNonObjectDef; } UiObjectMemberList *QMLRewriter::searchMemberToInsertAfter(UiObjectMemberList *members, const QString &propertyName, const QStringList &propertyOrder) { if (!members) return 0; // empty members QHash orderedMembers; for (UiObjectMemberList *iter = members; iter; iter = iter->next) { UiObjectMember *member = iter->member; if (UiArrayBinding *arrayBinding = cast(member)) orderedMembers[toString(arrayBinding->qualifiedId)] = iter; else if (UiObjectBinding *objectBinding = cast(member)) orderedMembers[toString(objectBinding->qualifiedId)] = iter; else if (cast(member)) orderedMembers[QString::null] = iter; else if (UiScriptBinding *scriptBinding = cast(member)) orderedMembers[toString(scriptBinding->qualifiedId)] = iter; else if (cast(member)) orderedMembers[QLatin1String("property")] = iter; } int idx = propertyOrder.indexOf(propertyName); if (idx == -1) idx = propertyOrder.indexOf(QString()); if (idx == -1) idx = propertyOrder.size() - 1; for (; idx > 0; --idx) { const QString prop = propertyOrder.at(idx - 1); UiObjectMemberList *candidate = orderedMembers.value(prop, 0); if (candidate != 0) return candidate; } return 0; } #endif void Rewriter::appendToArrayBinding(UiArrayBinding *arrayBinding, const QString &content) { UiObjectMember *lastMember = 0; for (UiArrayMemberList *iter = arrayBinding->members; iter; iter = iter->next) if (iter->member) lastMember = iter->member; if (!lastMember) return; // an array binding cannot be empty, so there will (or should) always be a last member. const int insertionPoint = lastMember->lastSourceLocation().end(); m_changeSet->insert(insertionPoint, QLatin1String(",\n") + content); } Rewriter::Range Rewriter::addObject(UiObjectInitializer *ast, const QString &content) { UiObjectMemberList *insertAfter = searchMemberToInsertAfter(ast->members, m_propertyOrder); return addObject(ast, content, insertAfter); } Rewriter::Range Rewriter::addObject(UiObjectInitializer *ast, const QString &content, UiObjectMemberList *insertAfter) { int insertionPoint; QString textToInsert; if (insertAfter && insertAfter->member) { insertionPoint = insertAfter->member->lastSourceLocation().end(); textToInsert += QLatin1String("\n"); } else { insertionPoint = ast->lbraceToken.end(); } textToInsert += content; m_changeSet->insert(insertionPoint, QLatin1String("\n") + textToInsert); return Range(insertionPoint, insertionPoint); } Rewriter::Range Rewriter::addObject(UiArrayBinding *ast, const QString &content) { UiArrayMemberList *insertAfter = searchMemberToInsertAfter(ast->members, m_propertyOrder); return addObject(ast, content, insertAfter); } Rewriter::Range Rewriter::addObject(UiArrayBinding *ast, const QString &content, UiArrayMemberList *insertAfter) { int insertionPoint; QString textToInsert; if (insertAfter && insertAfter->member) { insertionPoint = insertAfter->member->lastSourceLocation().end(); textToInsert = QLatin1String(",\n") + content; } else { insertionPoint = ast->lbracketToken.end(); textToInsert += QLatin1String("\n") + content + QLatin1Char(','); } m_changeSet->insert(insertionPoint, textToInsert); return Range(insertionPoint, insertionPoint); } void Rewriter::removeObjectMember(UiObjectMember *member, UiObjectMember *parent) { int start = member->firstSourceLocation().offset; int end = member->lastSourceLocation().end(); if (UiArrayBinding *parentArray = cast(parent)) { extendToLeadingOrTrailingComma(parentArray, member, start, end); } else { if (UiObjectDefinition *parentObjectDefinition = cast(parent)) includeEmptyGroupedProperty(parentObjectDefinition, member, start, end); includeSurroundingWhitespace(m_originalText, start, end); } includeLeadingEmptyLine(m_originalText, start); m_changeSet->remove(start, end); } void Rewriter::extendToLeadingOrTrailingComma(UiArrayBinding *parentArray, UiObjectMember *member, int &start, int &end) const { UiArrayMemberList *currentMember = 0; for (UiArrayMemberList *it = parentArray->members; it; it = it->next) { if (it->member == member) { currentMember = it; break; } } if (!currentMember) return; if (currentMember->commaToken.isValid()) { // leading comma start = currentMember->commaToken.offset; if (includeSurroundingWhitespace(m_originalText, start, end)) --end; } else if (currentMember->next && currentMember->next->commaToken.isValid()) { // trailing comma end = currentMember->next->commaToken.end(); includeSurroundingWhitespace(m_originalText, start, end); } else { // array with 1 element, so remove the complete binding start = parentArray->firstSourceLocation().offset; end = parentArray->lastSourceLocation().end(); includeSurroundingWhitespace(m_originalText, start, end); } } } // namespace QbsQmlJS qbs-src-1.4.5/src/lib/corelib/api/qmljsrewriter.h000066400000000000000000000117531266132464200217200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QMLJSREWRITER_H #define QMLJSREWRITER_H #include "changeset.h" #include #include namespace QbsQmlJS { class Rewriter { public: enum BindingType { ScriptBinding, ObjectBinding, ArrayBinding }; typedef ChangeSet::Range Range; public: Rewriter(const QString &originalText, ChangeSet *changeSet, const QStringList &propertyOrder); Range addBinding(AST::UiObjectInitializer *ast, const QString &propertyName, const QString &propertyValue, BindingType bindingType); Range addBinding(AST::UiObjectInitializer *ast, const QString &propertyName, const QString &propertyValue, BindingType bindingType, AST::UiObjectMemberList *insertAfter); void changeBinding(AST::UiObjectInitializer *ast, const QString &propertyName, const QString &newValue, BindingType binding); void removeBindingByName(AST::UiObjectInitializer *ast, const QString &propertyName); void appendToArrayBinding(AST::UiArrayBinding *arrayBinding, const QString &content); Range addObject(AST::UiObjectInitializer *ast, const QString &content); Range addObject(AST::UiObjectInitializer *ast, const QString &content, AST::UiObjectMemberList *insertAfter); Range addObject(AST::UiArrayBinding *ast, const QString &content); Range addObject(AST::UiArrayBinding *ast, const QString &content, AST::UiArrayMemberList *insertAfter); void removeObjectMember(AST::UiObjectMember *member, AST::UiObjectMember *parent); static AST::UiObjectMemberList *searchMemberToInsertAfter(AST::UiObjectMemberList *members, const QStringList &propertyOrder); static AST::UiArrayMemberList *searchMemberToInsertAfter(AST::UiArrayMemberList *members, const QStringList &propertyOrder); static AST::UiObjectMemberList *searchMemberToInsertAfter(AST::UiObjectMemberList *members, const QString &propertyName, const QStringList &propertyOrder); static bool includeSurroundingWhitespace(const QString &source, int &start, int &end); static void includeLeadingEmptyLine(const QString &source, int &start); static void includeEmptyGroupedProperty(AST::UiObjectDefinition *groupedProperty, AST::UiObjectMember *memberToBeRemoved, int &start, int &end); private: void replaceMemberValue(AST::UiObjectMember *propertyMember, const QString &newValue, bool needsSemicolon); static bool isMatchingPropertyMember(const QString &propertyName, AST::UiObjectMember *member); static bool nextMemberOnSameLine(AST::UiObjectMemberList *members); void insertIntoArray(AST::UiArrayBinding* ast, const QString &newValue); void removeMember(AST::UiObjectMember *member); void removeGroupedProperty(AST::UiObjectDefinition *ast, const QString &propertyName); void extendToLeadingOrTrailingComma(AST::UiArrayBinding *parentArray, AST::UiObjectMember *member, int &start, int &end) const; private: QString m_originalText; ChangeSet *m_changeSet; const QStringList m_propertyOrder; }; } // namespace QbsQmlJS #endif // QMLJSREWRITER_H qbs-src-1.4.5/src/lib/corelib/api/rulecommand.cpp000066400000000000000000000111111266132464200216330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "rulecommand.h" #include "rulecommand_p.h" #include namespace qbs { /*! * \class RuleCommand * \brief The \c RuleCommand class corresponds to a \c ProcessCommand or \c JavaScriptCommand * in \QBS. */ /*! * \enum RuleCommand::Type * This enum type represents the different kinds of commands. * \value ProcessCommandType For the \QBS type \c ProcessCommand, which represents a command * whose execution involves calling an executable. * \value JavaScriptCommandType For the \QBS type \c JavaScriptCommand, which represents a command * whose execution involves running a piece of JavaScript code inside \QBS. * \value InvalidType Used to mark \c RuleCommand objects as invalid. */ RuleCommand::RuleCommand() : d(new Internal::RuleCommandPrivate) { } RuleCommand::RuleCommand(const RuleCommand &other) : d(other.d) {} RuleCommand::~RuleCommand() { } RuleCommand& RuleCommand::operator=(const RuleCommand &other) { d = other.d; return *this; } /*! * Returns the type of this object. If the value is \c InvalidType, the object is invalid. */ RuleCommand::Type RuleCommand::type() const { return d->type; } /*! * Returns the human-readable description of this command that \QBS will print when * the command executed. */ QString RuleCommand::description() const { return d->description; } /*! * Returns the source of the command if \c type() is \c JavaScriptCommandType. * If \c type() is anything else, the behavior of this function is undefined. */ QString RuleCommand::sourceCode() const { QBS_ASSERT(type() == JavaScriptCommandType, return QString()); return d->sourceCode; } /*! * Returns the executable that will be called when the corresponding \c ProcessCommand * is executed. * If \c type() is not \c ProcessCommandType, the behavior of this function is undefined. */ QString RuleCommand::executable() const { QBS_ASSERT(type() == ProcessCommandType, return QString()); return d->executable; } /*! * Returns the command-line arguments of the executable that will be called when the * corresponding \c ProcessCommand is executed. * If \c type() is not \c ProcessCommandType, the behavior of this function is undefined. */ QStringList RuleCommand::arguments() const { QBS_ASSERT(type() == ProcessCommandType, return QStringList()); return d->arguments; } /*! * Returns the working directory of the executable that will be called when the * corresponding \c ProcessCommand is executed. * If \c type() is not \c ProcessCommandType, the behavior of this function is undefined. */ QString RuleCommand::workingDirectory() const { QBS_ASSERT(type() == ProcessCommandType, return QString()); return d->workingDir; } /*! * Returns the environment of the executable that will be called when the * corresponding \c ProcessCommand is executed. * If \c type() is not \c ProcessCommandType, the behavior of this function is undefined. */ QProcessEnvironment RuleCommand::environment() const { QBS_ASSERT(type() == ProcessCommandType, return QProcessEnvironment()); return d->environment; } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/api/rulecommand.h000066400000000000000000000047421266132464200213140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_RULECOMMAND_H #define QBS_RULECOMMAND_H #include #include #include QT_BEGIN_NAMESPACE class QProcessEnvironment; QT_END_NAMESPACE namespace qbs { namespace Internal { class ProjectPrivate; class RuleCommandPrivate; } class QBS_EXPORT RuleCommand { friend class Internal::ProjectPrivate; public: RuleCommand(); RuleCommand(const RuleCommand &other); ~RuleCommand(); RuleCommand &operator=(const RuleCommand &other); enum Type { ProcessCommandType, JavaScriptCommandType, InvalidType }; Type type() const; QString description() const; QString sourceCode() const; QString executable() const; QStringList arguments() const; QString workingDirectory() const; QProcessEnvironment environment() const; private: QExplicitlySharedDataPointer d; }; typedef QList RuleCommandList; } // namespace qbs #endif // Include guard. qbs-src-1.4.5/src/lib/corelib/api/rulecommand_p.h000066400000000000000000000040411266132464200216230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_RULECOMMAND_P_H #define QBS_RULECOMMAND_P_H #include "rulecommand.h" #include #include namespace qbs { namespace Internal { class RuleCommandPrivate : public QSharedData { public: RuleCommandPrivate(): type(RuleCommand::InvalidType) {} RuleCommand::Type type; QString description; QString sourceCode; QString executable; QStringList arguments; QString workingDir; QProcessEnvironment environment; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.4.5/src/lib/corelib/api/runenvironment.cpp000066400000000000000000000231361266132464200224300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "runenvironment.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { using namespace Internal; class RunEnvironment::RunEnvironmentPrivate { public: RunEnvironmentPrivate(const ResolvedProductPtr &product, const InstallOptions &installOptions, const QProcessEnvironment &environment, Settings *settings, const Logger &logger) : engine(logger) , resolvedProduct(product) , installOptions(installOptions) , environment(environment) , settings(settings) , logger(logger) { } ScriptEngine engine; const ResolvedProductPtr resolvedProduct; InstallOptions installOptions; const QProcessEnvironment environment; Settings * const settings; Logger logger; }; RunEnvironment::RunEnvironment(const ResolvedProductPtr &product, const InstallOptions &installOptions, const QProcessEnvironment &environment, Settings *settings, const Logger &logger) : d(new RunEnvironmentPrivate(product, installOptions, environment, settings, logger)) { } RunEnvironment::~RunEnvironment() { delete d; } int RunEnvironment::runShell() { d->resolvedProduct->setupBuildEnvironment(&d->engine, d->environment); const QString productId = d->resolvedProduct->name; d->logger.qbsInfo() << Tr::tr("Starting shell for target '%1'.").arg(productId); const QProcessEnvironment environment = d->resolvedProduct->buildEnvironment; #if defined(Q_OS_LINUX) clearenv(); #endif foreach (const QString &key, environment.keys()) qputenv(key.toLocal8Bit().constData(), environment.value(key).toLocal8Bit()); QString command; QScopedPointer envFile; if (HostOsInfo::isWindowsHost()) { command = environment.value(QLatin1String("COMSPEC")); if (command.isEmpty()) command = QLatin1String("cmd"); const QString prompt = environment.value(QLatin1String("PROMPT")); command += QLatin1String(" /k prompt [qbs] ") + prompt; } else { const QVariantMap qbsProps = d->resolvedProduct->topLevelProject()->buildConfiguration() .value(QLatin1String("qbs")).toMap(); const QString profileName = qbsProps.value(QLatin1String("profile")).toString(); command = Preferences(d->settings, profileName).shell(); if (command.isEmpty()) command = environment.value(QLatin1String("SHELL"), QLatin1String("/bin/sh")); // Yes, we have to use this prcoedure. PS1 is not inherited from the environment. const QString prompt = QLatin1String("qbs ") + productId + QLatin1String(" $ "); envFile.reset(new QTemporaryFile); if (envFile->open()) { if (command.endsWith(QLatin1String("bash"))) command += QLatin1String(" --posix"); // Teach bash some manners. const QString promptLine = QLatin1String("PS1='") + prompt + QLatin1String("'\n"); envFile->write(promptLine.toLocal8Bit()); envFile->close(); qputenv("ENV", envFile->fileName().toLocal8Bit()); } else { d->logger.qbsWarning() << Tr::tr("Setting custom shell prompt failed."); } } // We cannot use QProcess, since it does not do stdin forwarding. return system(command.toLocal8Bit().constData()); } static QString findExecutable(const QStringList &fileNames) { const QStringList path = QString::fromLocal8Bit(qgetenv("PATH")) .split(HostOsInfo::pathListSeparator(), QString::SkipEmptyParts); foreach (const QString &fileName, fileNames) { const QString exeFileName = HostOsInfo::appendExecutableSuffix(fileName); foreach (const QString &ppath, path) { const QString fullPath = ppath + QLatin1Char('/') + exeFileName; QFileInfo fi(fullPath); if (fi.exists() && fi.isFile() && fi.isExecutable()) return QDir::cleanPath(fullPath); } } return QString(); } int RunEnvironment::runTarget(const QString &targetBin, const QStringList &arguments) { const QStringList targetOS = PropertyFinder().propertyValue( d->resolvedProduct->moduleProperties->value(), QLatin1String("qbs"), QLatin1String("targetOS")).toStringList(); QString targetExecutable = targetBin; QStringList targetArguments = arguments; const QString completeSuffix = QFileInfo(targetBin).completeSuffix(); if (targetOS.contains(QLatin1String("windows"))) { if (completeSuffix == QLatin1String("msi")) { targetExecutable = QLatin1String("msiexec"); targetArguments.prepend(QDir::toNativeSeparators(targetBin)); targetArguments.prepend(QLatin1String("/package")); } // Run Windows executables through Wine when not on Windows if (!HostOsInfo::isWindowsHost()) { targetArguments.prepend(targetExecutable); targetExecutable = QLatin1String("wine"); } } if (completeSuffix == QLatin1String("js")) { // The Node.js binary is called nodejs on Debian/Ubuntu-family operating systems due to a // conflict with another package containing a binary named node targetExecutable = findExecutable(QStringList() << QLatin1String("nodejs") << QLatin1String("node")); targetArguments.prepend(targetBin); } // Only check if the target is executable if we're not running it through another // known application such as msiexec or wine, as we can't check in this case anyways QFileInfo fi(targetExecutable); if (targetBin == targetExecutable && (!fi.isFile() || !fi.isExecutable())) { d->logger.qbsLog(LoggerError) << Tr::tr("File '%1' is not an executable.") .arg(QDir::toNativeSeparators(targetExecutable)); return EXIT_FAILURE; } QProcessEnvironment env = d->environment; env.insert(QLatin1String("QBS_RUN_FILE_PATH"), targetBin); d->resolvedProduct->setupRunEnvironment(&d->engine, env); d->logger.qbsInfo() << Tr::tr("Starting target '%1'.").arg(QDir::toNativeSeparators(targetBin)); QProcess process; process.setProcessEnvironment(d->resolvedProduct->runEnvironment); process.setProcessChannelMode(QProcess::ForwardedChannels); process.start(targetExecutable, targetArguments); if (!process.waitForFinished(-1)) { if (process.error() == QProcess::FailedToStart) { QString errorPrefixString; #ifdef Q_OS_UNIX if (QFileInfo(targetExecutable).isExecutable()) { const QString interpreter(shellInterpreter(targetExecutable)); if (!interpreter.isEmpty()) { errorPrefixString = Tr::tr("%1: bad interpreter: ").arg(interpreter); } } #endif throw ErrorInfo(Tr::tr("The process '%1' could not be started: %2") .arg(targetExecutable) .arg(errorPrefixString + process.errorString())); } else { d->logger.qbsWarning() << "QProcess error: " << process.errorString(); } return EXIT_FAILURE; } return process.exitCode(); } const QProcessEnvironment RunEnvironment::runEnvironment() const { d->resolvedProduct->setupRunEnvironment(&d->engine, d->environment); return d->resolvedProduct->runEnvironment; } const QProcessEnvironment RunEnvironment::buildEnvironment() const { d->resolvedProduct->setupBuildEnvironment(&d->engine, d->environment); return d->resolvedProduct->buildEnvironment; } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/api/runenvironment.h000066400000000000000000000050441266132464200220730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_RUNENVIRONMENT_H #define QBS_RUNENVIRONMENT_H #include #include #include QT_BEGIN_NAMESPACE class QProcessEnvironment; QT_END_NAMESPACE namespace qbs { class InstallOptions; class Settings; namespace Internal { class Logger; class ResolvedProduct; } // namespace Internal class QBS_EXPORT RunEnvironment { friend class Project; public: ~RunEnvironment(); // These can throw an Error int runShell(); int runTarget(const QString &targetBin, const QStringList &arguments); const QProcessEnvironment runEnvironment() const; const QProcessEnvironment buildEnvironment() const; private: RunEnvironment(const Internal::ResolvedProductPtr &product, const InstallOptions &installOptions, const QProcessEnvironment &environment, Settings *settings, const Internal::Logger &logger); class RunEnvironmentPrivate; RunEnvironmentPrivate * const d; }; } // namespace qbs #endif // QBS_RUNENVIRONMENT_H qbs-src-1.4.5/src/lib/corelib/buildgraph/000077500000000000000000000000001266132464200201765ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/buildgraph/abstractcommandexecutor.cpp000066400000000000000000000052231266132464200256250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "abstractcommandexecutor.h" #include "command.h" #include #include namespace qbs { namespace Internal { AbstractCommandExecutor::AbstractCommandExecutor(const Logger &logger, QObject *parent) : QObject(parent) , m_echoMode(defaultCommandEchoMode()) , m_command(0) , m_transformer(0) , m_mainThreadScriptEngine(0) , m_dryRun(false) , m_logger(logger) { } void AbstractCommandExecutor::start(Transformer *transformer, const AbstractCommand *cmd) { m_transformer = transformer; m_command = cmd; doSetup(); doReportCommandDescription(); doStart(); } void AbstractCommandExecutor::doReportCommandDescription() { if (m_command->isSilent() || m_echoMode == CommandEchoModeSilent) return; if (m_command->description().isEmpty()) { m_logger.printWarning( ErrorInfo(Tr::tr("Command is not marked silent, but has no description."), m_command->codeLocation())); } else { emit reportCommandDescription(m_command->highlight(), m_command->description()); } } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/abstractcommandexecutor.h000066400000000000000000000063051266132464200252740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_ABSTRACTCOMMANDEXECUTOR_H #define QBS_ABSTRACTCOMMANDEXECUTOR_H #include #include #include #include namespace qbs { class ErrorInfo; namespace Internal { class AbstractCommand; class ScriptEngine; class Transformer; class AbstractCommandExecutor : public QObject { Q_OBJECT public: explicit AbstractCommandExecutor(const Internal::Logger &logger, QObject *parent = 0); void setMainThreadScriptEngine(ScriptEngine *engine) { m_mainThreadScriptEngine = engine; } void setDryRunEnabled(bool enabled) { m_dryRun = enabled; } void setEchoMode(CommandEchoMode echoMode) { m_echoMode = echoMode; } virtual void cancel() = 0; public slots: void start(Transformer *transformer, const AbstractCommand *cmd); signals: void reportCommandDescription(const QString &highlight, const QString &message); void finished(const qbs::ErrorInfo &err = ErrorInfo()); // !hasError() <=> command successful protected: virtual void doReportCommandDescription(); const AbstractCommand *command() const { return m_command; } Transformer *transformer() const { return m_transformer; } ScriptEngine *scriptEngine() const { return m_mainThreadScriptEngine; } bool dryRun() const { return m_dryRun; } Internal::Logger logger() const { return m_logger; } CommandEchoMode m_echoMode; private: virtual void doSetup() { }; virtual void doStart() = 0; private: const AbstractCommand *m_command; Transformer *m_transformer; ScriptEngine *m_mainThreadScriptEngine; bool m_dryRun; Internal::Logger m_logger; }; } // namespace Internal } // namespace qbs #endif // QBS_ABSTRACTCOMMANDEXECUTOR_H qbs-src-1.4.5/src/lib/corelib/buildgraph/artifact.cpp000066400000000000000000000121531266132464200225010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "artifact.h" #include "transformer.h" #include "buildgraphvisitor.h" #include "productbuilddata.h" #include #include #include #include QT_BEGIN_NAMESPACE static QDataStream &operator >>(QDataStream &s, qbs::Internal::Artifact::ArtifactType &t) { int i; s >> i; t = static_cast(i); return s; } static QDataStream &operator <<(QDataStream &s, const qbs::Internal::Artifact::ArtifactType &t) { return s << (int)t; } QT_END_NAMESPACE namespace qbs { namespace Internal { Artifact::Artifact() { initialize(); } Artifact::~Artifact() { foreach (Artifact *p, parentArtifacts()) p->childrenAddedByScanner.remove(this); } void Artifact::accept(BuildGraphVisitor *visitor) { if (visitor->visit(this)) acceptChildren(visitor); visitor->endVisit(this); } QString Artifact::toString() const { return QLatin1String("ARTIFACT ") + filePath(); } void Artifact::addFileTag(const FileTag &t) { m_fileTags += t; if (!product.isNull() && product->buildData) product->buildData->artifactsByFileTag[t] += this; } void Artifact::removeFileTag(const FileTag &t) { m_fileTags -= t; if (!product.isNull() && product->buildData) removeArtifactFromSetByFileTag(this, t, product->buildData->artifactsByFileTag); } void Artifact::setFileTags(const FileTags &newFileTags) { if (product.isNull() || !product->buildData) { m_fileTags = newFileTags; return; } foreach (const FileTag &t, m_fileTags) removeArtifactFromSetByFileTag(this, t, product->buildData->artifactsByFileTag); m_fileTags = newFileTags; addArtifactToSet(this, product->buildData->artifactsByFileTag); } void Artifact::initialize() { artifactType = Unknown; inputsScanned = false; timestampRetrieved = false; alwaysUpdated = true; oldDataPossiblyPresent = true; } ArtifactSet Artifact::parentArtifacts() const { return ArtifactSet::fromNodeSet(parents); } ArtifactSet Artifact::childArtifacts() const { return ArtifactSet::fromNodeSet(children); } void Artifact::onChildDisconnected(BuildGraphNode *child) { Artifact *childArtifact = dynamic_cast(child); if (!childArtifact) return; childrenAddedByScanner.remove(childArtifact); } void Artifact::load(PersistentPool &pool) { FileResourceBase::load(pool); BuildGraphNode::load(pool); children.load(pool); // restore parents of the loaded children for (NodeSet::const_iterator it = children.constBegin(); it != children.constEnd(); ++it) (*it)->parents.insert(this); pool.loadContainer(childrenAddedByScanner); pool.loadContainer(fileDependencies); properties = pool.idLoadS(); transformer = pool.idLoadS(); unsigned char c; pool.stream() >> m_fileTags >> artifactType >> c; alwaysUpdated = c; pool.stream() >> c; oldDataPossiblyPresent = c; } void Artifact::store(PersistentPool &pool) const { FileResourceBase::store(pool); BuildGraphNode::store(pool); // Do not store parents to avoid recursion. children.store(pool); pool.storeContainer(childrenAddedByScanner); pool.storeContainer(fileDependencies); pool.store(properties); pool.store(transformer); pool.stream() << m_fileTags << artifactType << static_cast(alwaysUpdated) << static_cast(oldDataPossiblyPresent); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/artifact.h000066400000000000000000000100101266132464200221340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_ARTIFACT_H #define QBS_ARTIFACT_H #include "artifactset.h" #include "filedependency.h" #include "buildgraphnode.h" #include "forward_decls.h" #include #include #include #include namespace qbs { namespace Internal { class Logger; /** * The Artifact class * * Let artifact P be the parent of artifact C. Thus C is child of P. * C produces P using the transformer P.transformer. * * */ class Artifact : public FileResourceBase, public BuildGraphNode { public: Artifact(); ~Artifact(); Type type() const { return ArtifactNodeType; } void accept(BuildGraphVisitor *visitor); QString toString() const; void addFileTag(const FileTag &t); void removeFileTag(const FileTag &t); void setFileTags(const FileTags &newFileTags); const FileTags &fileTags() const { return m_fileTags; } ArtifactSet childrenAddedByScanner; QSet fileDependencies; TransformerPtr transformer; PropertyMapPtr properties; enum ArtifactType { Unknown = 1, SourceFile = 2, Generated = 4 }; ArtifactType artifactType; bool inputsScanned : 1; // Do not serialize. Will be refreshed for every build. bool timestampRetrieved : 1; // Do not serialize. Will be refreshed for every build. bool alwaysUpdated : 1; bool oldDataPossiblyPresent : 1; void initialize(); ArtifactSet parentArtifacts() const; ArtifactSet childArtifacts() const; void onChildDisconnected(BuildGraphNode *child); private: void load(PersistentPool &pool); void store(PersistentPool &pool) const; FileTags m_fileTags; }; // debugging helper inline QString toString(Artifact::ArtifactType t) { switch (t) { case Artifact::SourceFile: return QLatin1String("SourceFile"); case Artifact::Generated: return QLatin1String("Generated"); case Artifact::Unknown: default: return QLatin1String("Unknown"); } } // debugging helper inline QString toString(BuildGraphNode::BuildState s) { switch (s) { case BuildGraphNode::Untouched: return QLatin1String("Untouched"); case BuildGraphNode::Buildable: return QLatin1String("Buildable"); case BuildGraphNode::Building: return QLatin1String("Building"); case BuildGraphNode::Built: return QLatin1String("Built"); default: return QLatin1String("Unknown"); } } } // namespace Internal } // namespace qbs #endif // QBS_ARTIFACT_H qbs-src-1.4.5/src/lib/corelib/buildgraph/artifactcleaner.cpp000066400000000000000000000201631266132464200240330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "artifactcleaner.h" #include "artifact.h" #include "artifactvisitor.h" #include "productbuilddata.h" #include "projectbuilddata.h" #include "transformer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { static void printRemovalMessage(const QString &path, bool dryRun, const Logger &logger) { if (dryRun) logger.qbsInfo() << Tr::tr("Would remove '%1'.").arg(path); else logger.qbsDebug() << "Removing '" << path << "'."; } static void invalidateArtifactTimestamp(Artifact *artifact) { if (artifact->timestamp().isValid()) { artifact->clearTimestamp(); artifact->product->topLevelProject()->buildData->isDirty = true; } } static void removeArtifactFromDisk(Artifact *artifact, bool dryRun, const Logger &logger) { QFileInfo fileInfo(artifact->filePath()); if (!FileInfo::fileExists(fileInfo)) { if (!dryRun) invalidateArtifactTimestamp(artifact); return; } printRemovalMessage(fileInfo.filePath(), dryRun, logger); if (dryRun) return; invalidateArtifactTimestamp(artifact); QString errorMessage; if (!removeFileRecursion(fileInfo, &errorMessage)) throw ErrorInfo(errorMessage); } class CleanupVisitor : public ArtifactVisitor { public: CleanupVisitor(const CleanOptions &options, const ProgressObserver *observer, const Logger &logger) : ArtifactVisitor(Artifact::Generated) , m_options(options) , m_observer(observer) , m_logger(logger) , m_hasError(false) { } void visitProduct(const ResolvedProductPtr &product) { m_product = product; ArtifactVisitor::visitProduct(product); auto it = product->buildData->rescuableArtifactData.begin(); while (it != product->buildData->rescuableArtifactData.end()) { // TODO: This does not respect CleanOptions::cleanType(), because the information // about whether an artifact is a target artifact is not stored in the RAD structure. // Rather than add it there, we should get rid of the CleanType altogether, as it // makes little sense. Artifact tmp; tmp.product = product; tmp.setFilePath(it.key()); tmp.setTimestamp(it.value().timeStamp); removeArtifactFromDisk(&tmp, m_options.dryRun(), m_logger); it = product->buildData->rescuableArtifactData.erase(it); } } const QSet &directories() const { return m_directories; } bool hasError() const { return m_hasError; } private: void doVisit(Artifact *artifact) { if (m_observer->canceled()) throw ErrorInfo(Tr::tr("Cleaning up was canceled.")); if (artifact->product != m_product) return; if (m_options.cleanType() == CleanOptions::CleanupTemporaries) { QBS_CHECK(artifact->transformer); foreach (Artifact * const sibling, artifact->transformer->outputs) { if (artifact->product->targetArtifacts().contains(sibling)) return; } } try { removeArtifactFromDisk(artifact, m_options.dryRun(), m_logger); } catch (const ErrorInfo &error) { if (!m_options.keepGoing()) throw; m_logger.printWarning(error); m_hasError = true; } m_directories << artifact->dirPath(); } const CleanOptions m_options; const ProgressObserver * const m_observer; Logger m_logger; bool m_hasError; ResolvedProductConstPtr m_product; QSet m_directories; }; ArtifactCleaner::ArtifactCleaner(const Logger &logger, ProgressObserver *observer) : m_logger(logger), m_observer(observer) { } void ArtifactCleaner::cleanup(const TopLevelProjectPtr &project, const QList &products, const CleanOptions &options) { m_hasError = false; const QString configString = Tr::tr(" for configuration %1").arg(project->id()); m_observer->initialize(Tr::tr("Cleaning up%1").arg(configString), products.count() + 1); QSet directories; foreach (const ResolvedProductPtr &product, products) { CleanupVisitor visitor(options, m_observer, m_logger); visitor.visitProduct(product); directories.unite(visitor.directories()); if (visitor.hasError()) m_hasError = true; m_observer->incrementProgressValue(); } // Directories created during the build are not artifacts (TODO: should they be?), // so we have to clean them up manually. QList dirList = directories.toList(); for (int i = 0; i < dirList.count(); ++i) { const QString &dir = dirList.at(i); if (!dir.startsWith(project->buildDirectory)) continue; if (FileInfo(dir).exists()) removeEmptyDirectories(dir, options); if (dir != project->buildDirectory) { const QString parentDir = QDir::cleanPath(dir + QLatin1String("/..")); if (parentDir != project->buildDirectory && !dirList.contains(parentDir)) dirList << parentDir; } } m_observer->incrementProgressValue(); if (m_hasError) throw ErrorInfo(Tr::tr("Failed to remove some files.")); m_observer->setFinished(); } void ArtifactCleaner::removeEmptyDirectories(const QString &rootDir, const CleanOptions &options, bool *isEmpty) { bool subTreeIsEmpty = true; QDirIterator it(rootDir, QDir::Files | QDir::Dirs | QDir::Hidden | QDir::NoDotAndDotDot); while (it.hasNext()) { it.next(); if (!it.fileInfo().isSymLink() && it.fileInfo().isDir()) removeEmptyDirectories(it.filePath(), options, &subTreeIsEmpty); else subTreeIsEmpty = false; } if (subTreeIsEmpty) { printRemovalMessage(rootDir, options.dryRun(), m_logger); if (!QDir::root().rmdir(rootDir)) { ErrorInfo error(Tr::tr("Failure to remove empty directory '%1'.").arg(rootDir)); if (!options.keepGoing()) throw error; m_logger.printWarning(error); m_hasError = true; subTreeIsEmpty = false; } } if (!subTreeIsEmpty && isEmpty) *isEmpty = false; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/artifactcleaner.h000066400000000000000000000043751266132464200235070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_ARTIFACTCLEANER_H #define QBS_ARTIFACTCLEANER_H #include #include #include namespace qbs { class CleanOptions; namespace Internal { class ProgressObserver; class ArtifactCleaner { public: ArtifactCleaner(const Logger &logger, ProgressObserver *observer); void cleanup(const TopLevelProjectPtr &project, const QList &products, const CleanOptions &options); private: void removeEmptyDirectories(const QString &rootDir, const CleanOptions &options, bool *isEmpty = 0); Logger m_logger; bool m_hasError; ProgressObserver *m_observer; }; } // namespace Internal } // namespace qbs #endif // QBS_ARTIFACTCLEANER_H qbs-src-1.4.5/src/lib/corelib/buildgraph/artifactset.cpp000066400000000000000000000054241266132464200232200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "artifactset.h" #include "artifact.h" namespace qbs { namespace Internal { ArtifactSet::ArtifactSet() { } ArtifactSet::ArtifactSet(const ArtifactSet &other) : QSet(other) { } ArtifactSet::ArtifactSet(const QSet &other) : QSet(other) { } ArtifactSet &ArtifactSet::unite(const ArtifactSet &other) { QSet::unite(other); return *this; } QStringList ArtifactSet::toStringList() const { QStringList sl; foreach (Artifact *a, *this) sl += a->filePath(); return sl; } QString ArtifactSet::toString() const { return QLatin1Char('[') + toStringList().join(QLatin1String(", ")) + QLatin1Char(']'); } ArtifactSet ArtifactSet::fromNodeSet(const NodeSet &nodes) { ArtifactSet result; result.reserve(nodes.count()); foreach (BuildGraphNode *node, nodes) { Artifact *artifact = dynamic_cast(node); if (artifact) result += artifact; } return result; } ArtifactSet ArtifactSet::fromNodeList(const QList &lst) { ArtifactSet result; result.reserve(lst.count()); for (QList::const_iterator it = lst.constBegin(); it != lst.end(); ++it) result.insert(*it); return result; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/artifactset.h000066400000000000000000000041761266132464200226700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_ARTIFACTSET_H #define QBS_ARTIFACTSET_H #include #include namespace qbs { namespace Internal { class Artifact; class NodeSet; class ArtifactSet : public QSet { public: ArtifactSet(); ArtifactSet(const ArtifactSet &other); ArtifactSet(const QSet &other); ArtifactSet &unite(const ArtifactSet &other); QStringList toStringList() const; QString toString() const; static ArtifactSet fromNodeSet(const NodeSet &nodes); static ArtifactSet fromNodeList(const QList &lst); }; } // namespace Internal } // namespace qbs #endif // QBS_ARTIFACTSET_H qbs-src-1.4.5/src/lib/corelib/buildgraph/artifactvisitor.cpp000066400000000000000000000047121266132464200241230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "artifactvisitor.h" #include "artifact.h" #include "productbuilddata.h" #include #include namespace qbs { namespace Internal { ArtifactVisitor::ArtifactVisitor(int artifactType) : m_artifactType(artifactType) { } void ArtifactVisitor::visitProduct(const ResolvedProductConstPtr &product) { if (!product->buildData) return; foreach (BuildGraphNode *node, product->buildData->nodes) node->accept(this); } void ArtifactVisitor::visitProject(const ResolvedProjectConstPtr &project) { foreach (const ResolvedProductConstPtr &product, project->allProducts()) visitProduct(product); } bool ArtifactVisitor::visit(RuleNode *ruleNode) { Q_UNUSED(ruleNode); return false; } bool ArtifactVisitor::visit(Artifact *artifact) { QBS_CHECK(artifact); if (m_artifactType & artifact->artifactType) doVisit(artifact); return false; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/artifactvisitor.h000066400000000000000000000042561266132464200235730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_ARTIFACTVISITOR_H #define QBS_ARTIFACTVISITOR_H #include "forward_decls.h" #include "buildgraphvisitor.h" #include #include #include namespace qbs { namespace Internal { class ArtifactVisitor : public BuildGraphVisitor { public: ArtifactVisitor(int artifactType); void visitProduct(const ResolvedProductConstPtr &product); void visitProject(const ResolvedProjectConstPtr &project); bool visit(RuleNode *ruleNode); bool visit(Artifact *artifact); private: virtual void doVisit(Artifact *artifact) = 0; const int m_artifactType; }; } // namespace Internal } // namespace qbs #endif // QBS_ARTIFACTVISITOR_H qbs-src-1.4.5/src/lib/corelib/buildgraph/buildgraph.cpp000066400000000000000000000537261266132464200230400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "buildgraph.h" #include "artifact.h" #include "cycledetector.h" #include "projectbuilddata.h" #include "productbuilddata.h" #include "transformer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { static QScriptValue setupProjectScriptValue(ScriptEngine *engine, const ResolvedProjectConstPtr &project, PrepareScriptObserver *observer) { QScriptValue obj = engine->newObject(); obj.setProperty(QLatin1String("filePath"), project->location.filePath()); obj.setProperty(QLatin1String("path"), FileInfo::path(project->location.filePath())); const QVariantMap &projectProperties = project->projectProperties(); for (QVariantMap::const_iterator it = projectProperties.begin(); it != projectProperties.end(); ++it) { engine->setObservedProperty(obj, it.key(), engine->toScriptValue(it.value()), observer); } return obj; } static void setupProductScriptValue(ScriptEngine *engine, QScriptValue &productScriptValue, const ResolvedProductConstPtr &product, PrepareScriptObserver *observer); class DependenciesFunction { public: DependenciesFunction(ScriptEngine *engine) : m_engine(engine) { } void init(QScriptValue &productScriptValue, const ResolvedProductConstPtr &product) { QScriptValue depfunc = m_engine->newFunction(&js_productDependencies, (void *)product.data()); setProduct(depfunc, product.data()); productScriptValue.setProperty(QLatin1String("dependencies"), depfunc, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::PropertyGetter); } private: static QScriptValue js_productDependencies(QScriptContext *, QScriptEngine *engine, void *arg) { const ResolvedProduct * const product = static_cast(arg); QScriptValue result = engine->newArray(); quint32 idx = 0; QList productDeps = product->dependencies.toList(); std::sort(productDeps.begin(), productDeps.end(), [](const ResolvedProductPtr &p1, const ResolvedProductPtr &p2) { return p1->name < p2->name; }); foreach (const ResolvedProductPtr &dependency, productDeps) { QScriptValue obj = engine->newObject(); setupProductScriptValue(static_cast(engine), obj, dependency, 0); result.setProperty(idx++, obj); } foreach (const ResolvedModuleConstPtr &dependency, product->modules) { QScriptValue obj = engine->newObject(); setupModuleScriptValue(static_cast(engine), obj, product->moduleProperties->value(), dependency->name); result.setProperty(idx++, obj); } return result; } static QScriptValue js_moduleDependencies(QScriptContext *, QScriptEngine *engine, void *arg) { const QVariantMap *modulesMap = static_cast(arg); QScriptValue result = engine->newArray(); quint32 idx = 0; for (QVariantMap::const_iterator it = modulesMap->begin(); it != modulesMap->end(); ++it) { QScriptValue obj = engine->newObject(); obj.setProperty(QLatin1String("name"), it.key()); setupModuleScriptValue(static_cast(engine), obj, it.value().toMap(), it.key()); result.setProperty(idx++, obj); } return result; } static void setupModuleScriptValue(ScriptEngine *engine, QScriptValue &moduleScriptValue, const QVariantMap &propertyMap, const QString &moduleName) { const QVariantMap propMap = propertyMap.value(QLatin1String("modules")).toMap().value(moduleName).toMap(); for (QVariantMap::ConstIterator it = propMap.constBegin(); it != propMap.constEnd(); ++it) { const QVariant &value = it.value(); if (value.isValid() && it.key() != QLatin1String("modules")) moduleScriptValue.setProperty(it.key(), engine->toScriptValue(value)); } QVariantMap *modulesMap = new QVariantMap(propMap.value(QLatin1String("modules")).toMap()); engine->registerOwnedVariantMap(modulesMap); QScriptValue depfunc = engine->newFunction(&js_moduleDependencies, modulesMap); moduleScriptValue.setProperty(QLatin1String("dependencies"), depfunc, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::PropertyGetter); } static void setProduct(QScriptValue scriptValue, const ResolvedProduct *product) { attachPointerTo(scriptValue, product); } static const ResolvedProduct *getProduct(const QScriptValue &scriptValue) { return attachedPointer(scriptValue); } ScriptEngine *m_engine; }; static void setupProductScriptValue(ScriptEngine *engine, QScriptValue &productScriptValue, const ResolvedProductConstPtr &product, PrepareScriptObserver *observer) { ModuleProperties::init(productScriptValue, product); DependenciesFunction(engine).init(productScriptValue, product); if (observer) observer->setProductObjectId(productScriptValue.objectId()); const QVariantMap &propMap = product->productProperties; for (QVariantMap::ConstIterator it = propMap.constBegin(); it != propMap.constEnd(); ++it) { engine->setObservedProperty(productScriptValue, it.key(), engine->toScriptValue(it.value()), observer); } } void setupScriptEngineForFile(ScriptEngine *engine, const ResolvedFileContextConstPtr &fileContext, QScriptValue targetObject) { engine->import(fileContext, targetObject, targetObject); JsExtensions::setupExtensions(fileContext->jsExtensions(), targetObject); } void setupScriptEngineForProduct(ScriptEngine *engine, const ResolvedProductConstPtr &product, const ResolvedModuleConstPtr &module, QScriptValue targetObject, PrepareScriptObserver *observer) { QScriptValue projectScriptValue = setupProjectScriptValue(engine, product->project, observer); targetObject.setProperty(QLatin1String("project"), projectScriptValue); if (observer) observer->setProjectObjectId(projectScriptValue.objectId()); { QVariant v; v.setValue(&product->buildEnvironment); engine->setProperty("_qbs_procenv", v); } QScriptValue productScriptValue = engine->newObject(); setupProductScriptValue(engine, productScriptValue, product, observer); targetObject.setProperty(QLatin1String("product"), productScriptValue); // If the Rule is in a Module, set up the 'moduleName' property productScriptValue.setProperty(QLatin1String("moduleName"), module->name.isEmpty() ? QScriptValue() : module->name); } bool findPath(BuildGraphNode *u, BuildGraphNode *v, QList &path) { if (u == v) { path.append(v); return true; } for (NodeSet::const_iterator it = u->children.begin(); it != u->children.end(); ++it) { if (findPath(*it, v, path)) { path.prepend(u); return true; } } return false; } /* * c must be built before p * p ----> c * p.children = c * c.parents = p * * also: children means i depend on or i am produced by * parent means "produced by me" or "depends on me" */ void connect(BuildGraphNode *p, BuildGraphNode *c) { QBS_CHECK(p != c); if (Artifact *ac = dynamic_cast(c)) { foreach (const Artifact * const child, ArtifactSet::fromNodeSet(p->children)) if (child != ac && child->filePath() == ac->filePath()) { throw ErrorInfo(QString::fromLocal8Bit("%1 already has a child artifact %2 as " "different object.").arg(p->toString(), ac->filePath()), CodeLocation(), true); } } p->children.insert(c); c->parents.insert(p); p->product->topLevelProject()->buildData->isDirty = true; } void loggedConnect(BuildGraphNode *u, BuildGraphNode *v, const Logger &logger) { QBS_CHECK(u != v); if (logger.traceEnabled()) { logger.qbsTrace() << QString::fromLocal8Bit("[BG] connect '%1' -> '%2'") .arg(u->toString(), v->toString()); } connect(u, v); } static bool existsPath_impl(BuildGraphNode *u, BuildGraphNode *v, QSet *seen) { if (u == v) return true; if (seen->contains(u)) return false; seen->insert(u); for (NodeSet::const_iterator it = u->children.begin(); it != u->children.end(); ++it) if (existsPath_impl(*it, v, seen)) return true; return false; } static bool existsPath(BuildGraphNode *u, BuildGraphNode *v) { QSet seen; return existsPath_impl(u, v, &seen); } static QStringList toStringList(const QList &path) { QStringList lst; foreach (BuildGraphNode *node, path) lst << node->toString(); return lst; } bool safeConnect(Artifact *u, Artifact *v, const Logger &logger) { QBS_CHECK(u != v); if (logger.traceEnabled()) { logger.qbsTrace() << QString::fromLocal8Bit("[BG] safeConnect: '%1' '%2'") .arg(relativeArtifactFileName(u), relativeArtifactFileName(v)); } if (existsPath(v, u)) { QList circle; findPath(v, u, circle); logger.qbsTrace() << "[BG] safeConnect: circle detected " << toStringList(circle); return false; } connect(u, v); return true; } void disconnect(BuildGraphNode *u, BuildGraphNode *v, const Logger &logger) { if (logger.traceEnabled()) { logger.qbsTrace() << QString::fromLocal8Bit("[BG] disconnect: '%1' '%2'") .arg(u->toString(), v->toString()); } u->children.remove(v); v->parents.remove(u); u->onChildDisconnected(v); } void removeGeneratedArtifactFromDisk(Artifact *artifact, const Logger &logger) { if (artifact->artifactType != Artifact::Generated) return; removeGeneratedArtifactFromDisk(artifact->filePath(), logger); } void removeGeneratedArtifactFromDisk(const QString &filePath, const Logger &logger) { QFile file(filePath); if (!file.exists()) return; logger.qbsDebug() << "removing " << filePath; if (!file.remove()) logger.qbsWarning() << QString::fromLocal8Bit("Cannot remove '%1'.").arg(filePath); } QString relativeArtifactFileName(const Artifact *artifact) { const QString &buildDir = artifact->product->topLevelProject()->buildDirectory; QString str = artifact->filePath(); if (str.startsWith(buildDir)) str.remove(0, buildDir.count()); if (str.startsWith(QLatin1Char('/'))) str.remove(0, 1); return str; } Artifact *lookupArtifact(const ResolvedProductConstPtr &product, const ProjectBuildData *projectBuildData, const QString &dirPath, const QString &fileName, bool compareByName) { const QList lookupResults = projectBuildData->lookupFiles(dirPath, fileName); for (QList::const_iterator it = lookupResults.constBegin(); it != lookupResults.constEnd(); ++it) { Artifact *artifact = dynamic_cast(*it); if (artifact && (compareByName ? artifact->product->uniqueName() == product->uniqueName() : artifact->product == product)) return artifact; } return 0; } Artifact *lookupArtifact(const ResolvedProductConstPtr &product, const QString &dirPath, const QString &fileName, bool compareByName) { return lookupArtifact(product, product->topLevelProject()->buildData.data(), dirPath, fileName, compareByName); } Artifact *lookupArtifact(const ResolvedProductConstPtr &product, const QString &filePath, bool compareByName) { QString dirPath, fileName; FileInfo::splitIntoDirectoryAndFileName(filePath, &dirPath, &fileName); return lookupArtifact(product, dirPath, fileName, compareByName); } Artifact *lookupArtifact(const ResolvedProductConstPtr &product, const ProjectBuildData *buildData, const QString &filePath, bool compareByName) { QString dirPath, fileName; FileInfo::splitIntoDirectoryAndFileName(filePath, &dirPath, &fileName); return lookupArtifact(product, buildData, dirPath, fileName, compareByName); } Artifact *lookupArtifact(const ResolvedProductConstPtr &product, const Artifact *artifact, bool compareByName) { return lookupArtifact(product, artifact->dirPath(), artifact->fileName(), compareByName); } Artifact *createArtifact(const ResolvedProductPtr &product, const SourceArtifactConstPtr &sourceArtifact, const Logger &logger) { Artifact *artifact = new Artifact; artifact->artifactType = Artifact::SourceFile; artifact->setFilePath(sourceArtifact->absoluteFilePath); artifact->setFileTags(sourceArtifact->fileTags); artifact->properties = sourceArtifact->properties; insertArtifact(product, artifact, logger); return artifact; } void insertArtifact(const ResolvedProductPtr &product, Artifact *artifact, const Logger &logger) { QBS_CHECK(!artifact->product); QBS_CHECK(!artifact->filePath().isEmpty()); QBS_CHECK(!product->buildData->nodes.contains(artifact)); #ifdef QT_DEBUG foreach (const ResolvedProductConstPtr &otherProduct, product->project->products) { if (lookupArtifact(otherProduct, artifact->filePath())) { if (artifact->artifactType == Artifact::Generated) { QString pl; pl.append(QString::fromLatin1(" - %1 \n").arg(product->uniqueName())); foreach (const ResolvedProductConstPtr &p, product->project->products) { if (lookupArtifact(p, artifact->filePath())) pl.append(QString::fromLatin1(" - %1 \n").arg(p->uniqueName())); } throw ErrorInfo(QString::fromLatin1("BUG: already inserted in this project: %1\n%2") .arg(artifact->filePath()).arg(pl), CodeLocation(), true); } } } #endif product->buildData->nodes.insert(artifact); addArtifactToSet(artifact, product->buildData->artifactsByFileTag); artifact->product = product; product->topLevelProject()->buildData->insertIntoLookupTable(artifact); product->topLevelProject()->buildData->isDirty = true; if (logger.traceEnabled()) { logger.qbsTrace() << QString::fromLocal8Bit("[BG] insert artifact '%1'") .arg(artifact->filePath()); } } static void doSanityChecksForProduct(const ResolvedProductConstPtr &product, const QSet &allProducts, const Logger &logger) { logger.qbsTrace() << "Sanity checking product '" << product->uniqueName() << "'"; CycleDetector cycleDetector(logger); cycleDetector.visitProduct(product); const ProductBuildData * const buildData = product->buildData.data(); if (logger.traceEnabled()) logger.qbsTrace() << "enabled: " << product->enabled << "; build data: " << buildData; QBS_CHECK(!!product->enabled == !!buildData); if (!product->enabled) return; foreach (BuildGraphNode * const node, buildData->roots) { if (logger.traceEnabled()) logger.qbsTrace() << "Checking root node '" << node->toString() << "'."; QBS_CHECK(buildData->nodes.contains(node)); } QSet filePaths; foreach (BuildGraphNode * const node, buildData->nodes) { logger.qbsTrace() << "Sanity checking node '" << node->toString() << "'"; QBS_CHECK(node->product == product); foreach (const BuildGraphNode * const parent, node->parents) QBS_CHECK(parent->children.contains(node)); foreach (BuildGraphNode * const child, node->children) { QBS_CHECK(child->parents.contains(node)); QBS_CHECK(!child->product.isNull()); QBS_CHECK(!child->product->buildData.isNull()); QBS_CHECK(child->product->buildData->nodes.contains(child)); QBS_CHECK(allProducts.contains(child->product)); } Artifact * const artifact = dynamic_cast(node); if (!artifact) continue; QBS_CHECK(!filePaths.contains(artifact->filePath())); filePaths << artifact->filePath(); foreach (Artifact * const child, artifact->childrenAddedByScanner) QBS_CHECK(artifact->children.contains(child)); const TransformerConstPtr transformer = artifact->transformer; if (artifact->artifactType == Artifact::SourceFile) continue; QBS_CHECK(transformer); QBS_CHECK(transformer->outputs.contains(artifact)); logger.qbsTrace() << "The transformer has " << transformer->outputs.count() << " outputs."; ArtifactSet transformerOutputChildren; foreach (const Artifact * const output, transformer->outputs) { QBS_CHECK(output->transformer == transformer); transformerOutputChildren.unite(ArtifactSet::fromNodeSet(output->children)); QSet childFilePaths; foreach (const Artifact * const a, ArtifactSet::fromNodeSet(output->children)) { if (childFilePaths.contains(a->filePath())) { throw ErrorInfo(QString::fromLocal8Bit("There is more than one artifact for " "file '%1' in the child list for output '%2'.") .arg(a->filePath(), output->filePath()), CodeLocation(), true); } childFilePaths << a->filePath(); } } if (logger.traceEnabled()) { logger.qbsTrace() << "The transformer output children are:"; foreach (const Artifact * const a, transformerOutputChildren) logger.qbsTrace() << "\t" << a->fileName(); logger.qbsTrace() << "The transformer inputs are:"; foreach (const Artifact * const a, transformer->inputs) logger.qbsTrace() << "\t" << a->fileName(); } QBS_CHECK(transformer->inputs.count() <= transformerOutputChildren.count()); foreach (Artifact * const transformerInput, transformer->inputs) QBS_CHECK(transformerOutputChildren.contains(transformerInput)); } } static void doSanityChecks(const ResolvedProjectPtr &project, const QSet &allProducts, QSet &productNames, const Logger &logger) { logger.qbsDebug() << "Sanity checking project '" << project->name << "'"; foreach (const ResolvedProjectPtr &subProject, project->subProjects) doSanityChecks(subProject, allProducts, productNames, logger); foreach (const ResolvedProductConstPtr &product, project->products) { QBS_CHECK(product->project == project); QBS_CHECK(product->topLevelProject() == project->topLevelProject()); doSanityChecksForProduct(product, allProducts, logger); QBS_CHECK(!productNames.contains(product->uniqueName())); productNames << product->uniqueName(); } } void doSanityChecks(const ResolvedProjectPtr &project, const Logger &logger) { QSet productNames; const QSet allProducts = project->allProducts().toSet(); doSanityChecks(project, allProducts, productNames, logger); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/buildgraph.h000066400000000000000000000101221266132464200224640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_BUILDGRAPH_H #define QBS_BUILDGRAPH_H #include "forward_decls.h" #include #include #include namespace qbs { namespace Internal { class BuildGraphNode; class Logger; class ScriptEngine; class PrepareScriptObserver; Artifact *lookupArtifact(const ResolvedProductConstPtr &product, const ProjectBuildData *projectBuildData, const QString &dirPath, const QString &fileName, bool compareByName = false); Artifact *lookupArtifact(const ResolvedProductConstPtr &product, const QString &dirPath, const QString &fileName, bool compareByName = false); Artifact *lookupArtifact(const ResolvedProductConstPtr &product, const ProjectBuildData *buildData, const QString &filePath, bool compareByName = false); Artifact *lookupArtifact(const ResolvedProductConstPtr &product, const QString &filePath, bool compareByName = false); Artifact *lookupArtifact(const ResolvedProductConstPtr &product, const Artifact *artifact, bool compareByName); Artifact *createArtifact(const ResolvedProductPtr &product, const SourceArtifactConstPtr &sourceArtifact, const Logger &logger); void insertArtifact(const ResolvedProductPtr &product, Artifact *artifact, const Logger &logger); void dumpProductBuildData(const ResolvedProductConstPtr &product); bool findPath(BuildGraphNode *u, BuildGraphNode *v, QList &path); void connect(BuildGraphNode *p, BuildGraphNode *c); void loggedConnect(BuildGraphNode *u, BuildGraphNode *v, const Logger &logger); bool safeConnect(Artifact *u, Artifact *v, const Logger &logger); void removeGeneratedArtifactFromDisk(Artifact *artifact, const Logger &logger); void removeGeneratedArtifactFromDisk(const QString &filePath, const Logger &logger); void disconnect(BuildGraphNode *u, BuildGraphNode *v, const Logger &logger); void setupScriptEngineForFile(ScriptEngine *engine, const ResolvedFileContextConstPtr &fileContext, QScriptValue targetObject); void setupScriptEngineForProduct(ScriptEngine *engine, const ResolvedProductConstPtr &product, const ResolvedModuleConstPtr &module, QScriptValue targetObject, PrepareScriptObserver *observer = 0); QString relativeArtifactFileName(const Artifact *artifact); // Debugging helpers void doSanityChecks(const ResolvedProjectPtr &project, const Logger &logger); } // namespace Internal } // namespace qbs #endif // QBS_BUILDGRAPH_H qbs-src-1.4.5/src/lib/corelib/buildgraph/buildgraph.pri000066400000000000000000000044571266132464200230450ustar00rootroot00000000000000include(../../../install_prefix.pri) SOURCES += \ $$PWD/abstractcommandexecutor.cpp \ $$PWD/artifact.cpp \ $$PWD/artifactcleaner.cpp \ $$PWD/artifactset.cpp \ $$PWD/artifactvisitor.cpp \ $$PWD/buildgraph.cpp \ $$PWD/buildgraphloader.cpp \ $$PWD/buildgraphnode.cpp \ $$PWD/command.cpp \ $$PWD/cycledetector.cpp \ $$PWD/depscanner.cpp \ $$PWD/emptydirectoriesremover.cpp \ $$PWD/executor.cpp \ $$PWD/executorjob.cpp \ $$PWD/filedependency.cpp \ $$PWD/inputartifactscanner.cpp \ $$PWD/jscommandexecutor.cpp \ $$PWD/nodeset.cpp \ $$PWD/nodetreedumper.cpp \ $$PWD/processcommandexecutor.cpp \ $$PWD/productbuilddata.cpp \ $$PWD/productinstaller.cpp \ $$PWD/projectbuilddata.cpp \ $$PWD/qtmocscanner.cpp \ $$PWD/rescuableartifactdata.cpp \ $$PWD/rulegraph.cpp \ $$PWD/rulenode.cpp \ $$PWD/rulesapplicator.cpp \ $$PWD/rulesevaluationcontext.cpp \ $$PWD/scanresultcache.cpp \ $$PWD/timestampsupdater.cpp \ $$PWD/transformer.cpp HEADERS += \ $$PWD/abstractcommandexecutor.h \ $$PWD/artifact.h \ $$PWD/artifactcleaner.h \ $$PWD/artifactset.h \ $$PWD/artifactvisitor.h \ $$PWD/buildgraph.h \ $$PWD/buildgraphloader.h \ $$PWD/buildgraphnode.h \ $$PWD/buildgraphvisitor.h \ $$PWD/command.h \ $$PWD/cycledetector.h \ $$PWD/depscanner.h \ $$PWD/emptydirectoriesremover.h \ $$PWD/executor.h \ $$PWD/executorjob.h \ $$PWD/filedependency.h \ $$PWD/forward_decls.h \ $$PWD/inputartifactscanner.h \ $$PWD/jscommandexecutor.h \ $$PWD/nodeset.h \ $$PWD/nodetreedumper.h \ $$PWD/processcommandexecutor.h \ $$PWD/productbuilddata.h \ $$PWD/productinstaller.h \ $$PWD/projectbuilddata.h \ $$PWD/qtmocscanner.h \ $$PWD/rescuableartifactdata.h \ $$PWD/rulegraph.h \ $$PWD/rulenode.h \ $$PWD/rulesapplicator.h \ $$PWD/rulesevaluationcontext.h \ $$PWD/scanresultcache.h \ $$PWD/timestampsupdater.h \ $$PWD/transformer.h qbs_enable_unit_tests { HEADERS += $$PWD/tst_buildgraph.h SOURCES += $$PWD/tst_buildgraph.cpp } !qbs_no_dev_install { buildgraph_headers.files = $$PWD/forward_decls.h buildgraph_headers.path = $${QBS_INSTALL_PREFIX}/include/qbs/buildgraph INSTALLS += buildgraph_headers } qbs-src-1.4.5/src/lib/corelib/buildgraph/buildgraphloader.cpp000066400000000000000000001073031266132464200242160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "buildgraphloader.h" #include "artifact.h" #include "artifactset.h" #include "buildgraph.h" #include "command.h" #include "cycledetector.h" #include "emptydirectoriesremover.h" #include "productbuilddata.h" #include "projectbuilddata.h" #include "rulesevaluationcontext.h" #include "transformer.h" #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { BuildGraphLoader::BuildGraphLoader(const QProcessEnvironment &env, const Logger &logger) : m_logger(logger), m_environment(env) { } BuildGraphLoader::~BuildGraphLoader() { qDeleteAll(m_objectsToDelete); } static void restoreBackPointers(const ResolvedProjectPtr &project) { foreach (const ResolvedProductPtr &product, project->products) { product->project = project; if (!product->buildData) continue; foreach (BuildGraphNode * const n, product->buildData->nodes) { if (Artifact *a = dynamic_cast(n)) project->topLevelProject()->buildData->insertIntoLookupTable(a); } } foreach (const ResolvedProjectPtr &subProject, project->subProjects) { subProject->parentProject = project; restoreBackPointers(subProject); } } BuildGraphLoadResult BuildGraphLoader::load(const TopLevelProjectPtr &existingProject, const SetupProjectParameters ¶meters, const RulesEvaluationContextPtr &evalContext) { m_parameters = parameters; m_result = BuildGraphLoadResult(); m_evalContext = evalContext; if (existingProject) { QBS_CHECK(existingProject->buildData); existingProject->buildData->evaluationContext = evalContext; checkBuildGraphCompatibility(existingProject); m_result.loadedProject = existingProject; } else { loadBuildGraphFromDisk(); } if (!m_result.loadedProject) return m_result; if (parameters.restoreBehavior() == SetupProjectParameters::RestoreOnly) return m_result; QBS_CHECK(parameters.restoreBehavior() == SetupProjectParameters::RestoreAndTrackChanges); trackProjectChanges(); return m_result; } void BuildGraphLoader::loadBuildGraphFromDisk() { const QString projectId = TopLevelProject::deriveId(m_parameters.topLevelProfile(), m_parameters.finalBuildConfigurationTree()); const QString buildDir = TopLevelProject::deriveBuildDirectory(m_parameters.buildRoot(), projectId); const QString buildGraphFilePath = ProjectBuildData::deriveBuildGraphFilePath(buildDir, projectId); PersistentPool pool(m_logger); m_logger.qbsDebug() << "[BG] trying to load: " << buildGraphFilePath; try { pool.load(buildGraphFilePath); } catch (const ErrorInfo &loadError) { if (m_parameters.restoreBehavior() == SetupProjectParameters::RestoreOnly) throw; m_logger.qbsInfo() << loadError.toString(); return; } const TopLevelProjectPtr project = TopLevelProject::create(); // TODO: Store some meta data that will enable us to show actual progress (e.g. number of products). m_evalContext->initializeObserver(Tr::tr("Restoring build graph from disk"), 1); project->load(pool); project->buildData->evaluationContext = m_evalContext; project->setBuildConfiguration(pool.headData().projectConfig); project->buildDirectory = buildDir; checkBuildGraphCompatibility(project); restoreBackPointers(project); project->location = CodeLocation(m_parameters.projectFilePath(), project->location.line(), project->location.column()); m_result.loadedProject = project; m_evalContext->incrementProgressValue(); doSanityChecks(project, m_logger); } void BuildGraphLoader::checkBuildGraphCompatibility(const TopLevelProjectConstPtr &project) { if (QFileInfo(project->location.filePath()) != QFileInfo(m_parameters.projectFilePath())) { QString errorMessage = Tr::tr("Stored build graph at '%1' is for project file '%2', but " "input file is '%3'. ") .arg(QDir::toNativeSeparators(project->buildGraphFilePath()), QDir::toNativeSeparators(project->location.filePath()), QDir::toNativeSeparators(m_parameters.projectFilePath())); if (!m_parameters.ignoreDifferentProjectFilePath()) { errorMessage += Tr::tr("Aborting."); throw ErrorInfo(errorMessage); } // Okay, let's assume it's the same project anyway (the source dir might have moved). errorMessage += Tr::tr("Ignoring."); m_logger.qbsWarning() << errorMessage; } } static bool checkProductForChangedDependency(QList &changedProducts, QSet &seenProducts, const ResolvedProductPtr &product) { if (seenProducts.contains(product)) return false; if (changedProducts.contains(product)) return true; foreach (const ResolvedProductPtr &dep, product->dependencies) { if (checkProductForChangedDependency(changedProducts, seenProducts, dep)) { changedProducts << product; return true; } } seenProducts << product; return false; } // All products depending on changed products also become changed. Otherwise the output // artifacts of the rules taking the artifacts from the dependency as inputs will be // rebuilt due to their rule getting re-applied (as the rescued input artifacts will show // up as newly added) and no rescue data being available. static void makeChangedProductsListComplete(QList &changedProducts, const QList &allRestoredProducts) { QSet seenProducts; foreach (const ResolvedProductPtr &p, allRestoredProducts) checkProductForChangedDependency(changedProducts, seenProducts, p); } void BuildGraphLoader::trackProjectChanges() { const TopLevelProjectPtr &restoredProject = m_result.loadedProject; QSet buildSystemFiles = restoredProject->buildSystemFiles; QList allRestoredProducts = restoredProject->allProducts(); QList changedProducts; bool reResolvingNecessary = false; if (!isConfigCompatible()) reResolvingNecessary = true; if (hasProductFileChanged(allRestoredProducts, restoredProject->lastResolveTime, buildSystemFiles, changedProducts)) { reResolvingNecessary = true; } // "External" changes, e.g. in the environment or in a JavaScript file, // can make the list of source files in a product change without the respective file // having been touched. In such a case, the build data for that product will have to be set up // anew. if (hasBuildSystemFileChanged(buildSystemFiles, restoredProject->lastResolveTime) || hasEnvironmentChanged(restoredProject) || hasCanonicalFilePathResultChanged(restoredProject) || hasFileExistsResultChanged(restoredProject) || hasFileLastModifiedResultChanged(restoredProject)) { reResolvingNecessary = true; } if (!reResolvingNecessary) return; restoredProject->buildData->isDirty = true; Loader ldr(m_evalContext->engine(), m_logger); ldr.setSearchPaths(m_parameters.searchPaths()); ldr.setProgressObserver(m_evalContext->observer()); m_result.newlyResolvedProject = ldr.loadProject(m_parameters); QMap freshProductsByName; QList allNewlyResolvedProducts = m_result.newlyResolvedProject->allProducts(); foreach (const ResolvedProductPtr &cp, allNewlyResolvedProducts) freshProductsByName.insert(cp->uniqueName(), cp); checkAllProductsForChanges(allRestoredProducts, freshProductsByName, changedProducts); QSharedPointer oldBuildData; ChildListHash childLists; if (!changedProducts.isEmpty()) { oldBuildData = QSharedPointer( new ProjectBuildData(restoredProject->buildData.data())); foreach (const ResolvedProductConstPtr &product, allRestoredProducts) { if (!product->buildData) continue; // If the product gets temporarily removed, its artifacts will get disconnected // and this structural information will no longer be directly available from them. foreach (const Artifact * const a, ArtifactSet::fromNodeSet(product->buildData->nodes)) { childLists.insert(a, ChildrenInfo(ArtifactSet::fromNodeSet(a->children), a->childrenAddedByScanner)); } } } makeChangedProductsListComplete(changedProducts, allRestoredProducts); // Set up build data from scratch for all changed products. This does not necessarily // mean that artifacts will have to get rebuilt; whether this is necesessary will be decided // an a per-artifact basis by the Executor on the next build. QHash rescuableArtifactData; foreach (const ResolvedProductPtr &product, changedProducts) { ResolvedProductPtr freshProduct = freshProductsByName.value(product->uniqueName()); if (!freshProduct) continue; onProductRemoved(product, product->topLevelProject()->buildData.data(), false); if (product->buildData) { rescuableArtifactData.insert(product->uniqueName(), product->buildData->rescuableArtifactData); } allRestoredProducts.removeOne(product); } // Move over restored build data to newly resolved project. m_result.newlyResolvedProject->buildData.swap(restoredProject->buildData); QBS_CHECK(m_result.newlyResolvedProject->buildData); m_result.newlyResolvedProject->buildData->isDirty = true; for (int i = allNewlyResolvedProducts.count() - 1; i >= 0; --i) { const ResolvedProductPtr &newlyResolvedProduct = allNewlyResolvedProducts.at(i); for (int j = allRestoredProducts.count() - 1; j >= 0; --j) { const ResolvedProductPtr &restoredProduct = allRestoredProducts.at(j); if (newlyResolvedProduct->uniqueName() == restoredProduct->uniqueName()) { if (newlyResolvedProduct->enabled) newlyResolvedProduct->buildData.swap(restoredProduct->buildData); if (newlyResolvedProduct->buildData) { foreach (BuildGraphNode *node, newlyResolvedProduct->buildData->nodes) node->product = newlyResolvedProduct; } // Keep in list if build data still needs to be resolved. if (!newlyResolvedProduct->enabled || newlyResolvedProduct->buildData) allNewlyResolvedProducts.removeAt(i); allRestoredProducts.removeAt(j); break; } } } // Products still left in the list do not exist anymore. foreach (const ResolvedProductPtr &removedProduct, allRestoredProducts) { changedProducts.removeOne(removedProduct); onProductRemoved(removedProduct, m_result.newlyResolvedProject->buildData.data()); } // Products still left in the list need resolving, either because they are new // or because they are newly enabled. if (!allNewlyResolvedProducts.isEmpty()) { BuildDataResolver bpr(m_logger); bpr.resolveProductBuildDataForExistingProject(m_result.newlyResolvedProject, allNewlyResolvedProducts); } foreach (const ResolvedProductConstPtr &changedProduct, changedProducts) { rescueOldBuildData(changedProduct, freshProductsByName.value(changedProduct->uniqueName()), oldBuildData.data(), childLists, rescuableArtifactData.value(changedProduct->uniqueName())); } EmptyDirectoriesRemover(m_result.newlyResolvedProject.data(), m_logger) .removeEmptyParentDirectories(m_artifactsRemovedFromDisk); foreach (FileResourceBase * const f, m_objectsToDelete) { Artifact * const a = dynamic_cast(f); if (a) a->product.clear(); // To help with the sanity checks. } doSanityChecks(m_result.newlyResolvedProject, m_logger); } bool BuildGraphLoader::hasEnvironmentChanged(const TopLevelProjectConstPtr &restoredProject) const { QProcessEnvironment oldEnv = restoredProject->environment; QProcessEnvironment newEnv = m_environment; // HACK. Valgrind screws up our null-build benchmarker otherwise. // TODO: Think about a (module-provided) whitelist. oldEnv.remove(QLatin1String("LD_PRELOAD")); newEnv.remove(QLatin1String("LD_PRELOAD")); if (oldEnv != newEnv) { m_logger.qbsDebug() << "Set of environment variables changed. Must re-resolve project."; m_logger.qbsTrace() << "old: " << restoredProject->environment.toStringList() << "\nnew:" << m_environment.toStringList(); return true; } return false; } bool BuildGraphLoader::hasCanonicalFilePathResultChanged(const TopLevelProjectConstPtr &restoredProject) const { for (auto it = restoredProject->canonicalFilePathResults.constBegin(); it != restoredProject->canonicalFilePathResults.constEnd(); ++it) { if (QFileInfo(it.key()).canonicalFilePath() != it.value()) { m_logger.qbsDebug() << "Canonical file path for file '" << it.key() << "' changed, must re-resolve project."; return true; } } return false; } bool BuildGraphLoader::hasFileExistsResultChanged(const TopLevelProjectConstPtr &restoredProject) const { for (QHash::ConstIterator it = restoredProject->fileExistsResults.constBegin(); it != restoredProject->fileExistsResults.constEnd(); ++it) { if (FileInfo(it.key()).exists() != it.value()) { m_logger.qbsDebug() << "Existence check for file '" << it.key() << " 'changed, must re-resolve project."; return true; } } return false; } bool BuildGraphLoader::hasFileLastModifiedResultChanged(const TopLevelProjectConstPtr &restoredProject) const { for (QHash::ConstIterator it = restoredProject->fileLastModifiedResults.constBegin(); it != restoredProject->fileLastModifiedResults.constEnd(); ++it) { if (FileInfo(it.key()).lastModified() != it.value()) { m_logger.qbsDebug() << "Timestamp for file '" << it.key() << " 'changed, must re-resolve project."; return true; } } return false; } bool BuildGraphLoader::hasProductFileChanged(const QList &restoredProducts, const FileTime &referenceTime, QSet &remainingBuildSystemFiles, QList &changedProducts) { bool hasChanged = false; foreach (const ResolvedProductPtr &product, restoredProducts) { const QString filePath = product->location.filePath(); const FileInfo pfi(filePath); remainingBuildSystemFiles.remove(filePath); if (!pfi.exists()) { m_logger.qbsDebug() << "A product was removed, must re-resolve project"; hasChanged = true; } else if (referenceTime < pfi.lastModified()) { m_logger.qbsDebug() << "A product was changed, must re-resolve project"; hasChanged = true; } else if (!changedProducts.contains(product)) { foreach (const GroupPtr &group, product->groups) { if (!group->wildcards) continue; const QSet files = group->wildcards->expandPatterns(group, product->sourceDirectory); QSet wcFiles; foreach (const SourceArtifactConstPtr &sourceArtifact, group->wildcards->files) wcFiles += sourceArtifact->absoluteFilePath; if (files == wcFiles) continue; hasChanged = true; changedProducts += product; break; } } } return hasChanged; } bool BuildGraphLoader::hasBuildSystemFileChanged(const QSet &buildSystemFiles, const FileTime &referenceTime) { foreach (const QString &file, buildSystemFiles) { const FileInfo fi(file); if (!fi.exists() || referenceTime < fi.lastModified()) { m_logger.qbsDebug() << "A qbs or js file changed, must re-resolve project."; return true; } } return false; } void BuildGraphLoader::checkAllProductsForChanges(const QList &restoredProducts, const QMap &newlyResolvedProductsByName, QList &changedProducts) { foreach (const ResolvedProductPtr &restoredProduct, restoredProducts) { const ResolvedProductPtr newlyResolvedProduct = newlyResolvedProductsByName.value(restoredProduct->uniqueName()); if (!newlyResolvedProduct) continue; if (newlyResolvedProduct->enabled != restoredProduct->enabled) { m_logger.qbsDebug() << "Condition of product '" << restoredProduct->uniqueName() << "' was changed, must set up build data from scratch"; if (!changedProducts.contains(restoredProduct)) changedProducts << restoredProduct; continue; } if (checkProductForChanges(restoredProduct, newlyResolvedProduct)) { m_logger.qbsDebug() << "Product '" << restoredProduct->uniqueName() << "' was changed, must set up build data from scratch"; if (!changedProducts.contains(restoredProduct)) changedProducts << restoredProduct; continue; } if (!sourceArtifactSetsAreEqual(restoredProduct->allEnabledFiles(), newlyResolvedProduct->allEnabledFiles())) { m_logger.qbsDebug() << "File list of product '" << restoredProduct->uniqueName() << "' was changed."; if (!changedProducts.contains(restoredProduct)) changedProducts << restoredProduct; } } } static bool dependenciesAreEqual(const ResolvedProductConstPtr &p1, const ResolvedProductConstPtr &p2) { if (p1->dependencies.count() != p2->dependencies.count()) return false; QSet names1; QSet names2; foreach (const ResolvedProductConstPtr &dep, p1->dependencies) names1 << dep->uniqueName(); foreach (const ResolvedProductConstPtr &dep, p2->dependencies) names2 << dep->uniqueName(); return names1 == names2; } bool BuildGraphLoader::checkProductForChanges(const ResolvedProductPtr &restoredProduct, const ResolvedProductPtr &newlyResolvedProduct) { // This check must come first, as it can prevent build data rescuing as a side effect. // TODO: Similar special checks must be done for qbs.getEnv() and File.exists() in // commands (or possibly it could be reasonable to just forbid such "dynamic" constructs // within commands). if (checkForPropertyChanges(restoredProduct, newlyResolvedProduct)) return true; return !transformerListsAreEqual(restoredProduct->transformers, newlyResolvedProduct->transformers) || !ruleListsAreEqual(restoredProduct->rules.toList(), newlyResolvedProduct->rules.toList()) || !dependenciesAreEqual(restoredProduct, newlyResolvedProduct); } bool BuildGraphLoader::checkProductForInstallInfoChanges(const ResolvedProductPtr &restoredProduct, const ResolvedProductPtr &newlyResolvedProduct) { // These are not requested from rules at build time, but we still need to take // them into account. const QStringList specialProperties = QStringList() << QLatin1String("install") << QLatin1String("installDir") << QLatin1String("installPrefix") << QLatin1String("installRoot"); foreach (const QString &key, specialProperties) { if (restoredProduct->moduleProperties->qbsPropertyValue(key) != newlyResolvedProduct->moduleProperties->qbsPropertyValue(key)) { m_logger.qbsDebug() << "Product property 'qbs." << key << "' changed."; return true; } } return false; } bool BuildGraphLoader::checkForPropertyChanges(const ResolvedProductPtr &restoredProduct, const ResolvedProductPtr &newlyResolvedProduct) { m_logger.qbsDebug() << "Checking for changes in properties requested in prepare scripts for " "product '" << restoredProduct->uniqueName() << "'."; if (!restoredProduct->buildData) return false; // This check must come first, as it can prevent build data rescuing. if (checkTransformersForPropertyChanges(restoredProduct, newlyResolvedProduct)) return true; if (restoredProduct->fileTags != newlyResolvedProduct->fileTags) { m_logger.qbsTrace() << "Product type changed from " << restoredProduct->fileTags << "to " << newlyResolvedProduct->fileTags; return true; } if (checkProductForInstallInfoChanges(restoredProduct, newlyResolvedProduct)) return true; if (!artifactPropertyListsAreEqual(restoredProduct->artifactProperties, newlyResolvedProduct->artifactProperties)) { return true; } return false; } bool BuildGraphLoader::checkTransformersForPropertyChanges(const ResolvedProductPtr &restoredProduct, const ResolvedProductPtr &newlyResolvedProduct) { bool transformerChanges = false; QSet seenTransformers; foreach (Artifact *artifact, ArtifactSet::fromNodeSet(restoredProduct->buildData->nodes)) { const TransformerPtr transformer = artifact->transformer; if (!transformer || seenTransformers.contains(transformer)) continue; seenTransformers.insert(transformer); if (checkForPropertyChanges(transformer, newlyResolvedProduct)) transformerChanges = true; } if (transformerChanges) { m_logger.qbsDebug() << "Property changes in product '" << newlyResolvedProduct->uniqueName() << "'."; } return transformerChanges; } void BuildGraphLoader::onProductRemoved(const ResolvedProductPtr &product, ProjectBuildData *projectBuildData, bool removeArtifactsFromDisk) { m_logger.qbsDebug() << "[BG] product '" << product->uniqueName() << "' removed."; product->project->products.removeOne(product); if (product->buildData) { foreach (BuildGraphNode * const node, product->buildData->nodes) { if (node->type() == BuildGraphNode::ArtifactNodeType) { Artifact * const artifact = static_cast(node); projectBuildData->removeArtifact(artifact, m_logger, removeArtifactsFromDisk, false); if (removeArtifactsFromDisk && artifact->artifactType == Artifact::Generated) m_artifactsRemovedFromDisk << artifact->filePath(); } else { foreach (BuildGraphNode * const parent, node->parents) parent->children.remove(node); node->parents.clear(); foreach (BuildGraphNode * const child, node->children) child->parents.remove(node); node->children.clear(); } } } } static SourceArtifactConstPtr findSourceArtifact(const ResolvedProductConstPtr &product, const QString &artifactFilePath, QMap &artifactMap) { SourceArtifactConstPtr &artifact = artifactMap[artifactFilePath]; if (!artifact) { foreach (const SourceArtifactConstPtr &a, product->allFiles()) { if (a->absoluteFilePath == artifactFilePath) { artifact = a; break; } } } return artifact; } static QVariantMap propertyMapByKind(const ResolvedProductConstPtr &product, Property::Kind kind) { switch (kind) { case Property::PropertyInModule: return product->moduleProperties->value(); case Property::PropertyInProduct: return product->productProperties; case Property::PropertyInProject: return product->project->projectProperties(); default: QBS_CHECK(false); } return QVariantMap(); } bool BuildGraphLoader::checkForPropertyChanges(const TransformerPtr &restoredTrafo, const ResolvedProductPtr &freshProduct) { // This check must come first, as it can prevent build data rescuing. foreach (const Property &property, restoredTrafo->propertiesRequestedInCommands) { if (checkForPropertyChange(property, propertyMapByKind(freshProduct, property.kind))) { const JavaScriptCommandPtr &pseudoCommand = JavaScriptCommand::create(); pseudoCommand->setSourceCode(QLatin1String("random stuff that will cause " "commandsEqual() to fail")); restoredTrafo->commands << pseudoCommand; return true; } } foreach (const Property &property, restoredTrafo->propertiesRequestedInPrepareScript) { if (checkForPropertyChange(property, propertyMapByKind(freshProduct, property.kind))) return true; } QMap artifactMap; for (QHash::ConstIterator it = restoredTrafo->propertiesRequestedFromArtifactInPrepareScript.constBegin(); it != restoredTrafo->propertiesRequestedFromArtifactInPrepareScript.constEnd(); ++it) { const SourceArtifactConstPtr artifact = findSourceArtifact(freshProduct, it.key(), artifactMap); if (!artifact) continue; foreach (const Property &property, it.value()) { if (checkForPropertyChange(property, artifact->properties->value())) return true; } } return false; } bool BuildGraphLoader::checkForPropertyChange(const Property &restoredProperty, const QVariantMap &newProperties) { PropertyFinder finder; QVariant v; switch (restoredProperty.kind) { case Property::PropertyInProduct: case Property::PropertyInProject: v = newProperties.value(restoredProperty.propertyName); break; case Property::PropertyInModule: if (restoredProperty.value.type() == QVariant::List) { v = finder.propertyValues(newProperties, restoredProperty.moduleName, restoredProperty.propertyName); } else { v = finder.propertyValue(newProperties, restoredProperty.moduleName, restoredProperty.propertyName); } break; } if (restoredProperty.value != v) { m_logger.qbsDebug() << "Value for property '" << restoredProperty.moduleName << "." << restoredProperty.propertyName << "' has changed."; m_logger.qbsDebug() << "Old value was '" << restoredProperty.value << "'."; m_logger.qbsDebug() << "New value is '" << v << "'."; return true; } return false; } void BuildGraphLoader::replaceFileDependencyWithArtifact(const ResolvedProductPtr &fileDepProduct, FileDependency *filedep, Artifact *artifact) { if (m_logger.traceEnabled()) { m_logger.qbsTrace() << QString::fromLocal8Bit("[BG] replace file dependency '%1' " "with artifact of type '%2'") .arg(filedep->filePath()).arg(artifact->artifactType); } foreach (const ResolvedProductPtr &product, fileDepProduct->topLevelProject()->allProducts()) { if (!product->buildData) continue; foreach (Artifact *artifactInProduct, ArtifactSet::fromNodeSet(product->buildData->nodes)) { if (artifactInProduct->fileDependencies.contains(filedep)) { artifactInProduct->fileDependencies.remove(filedep); loggedConnect(artifactInProduct, artifact, m_logger); } } } fileDepProduct->topLevelProject()->buildData->fileDependencies.remove(filedep); fileDepProduct->topLevelProject()->buildData->removeFromLookupTable(filedep); m_objectsToDelete << filedep; } bool BuildGraphLoader::isConfigCompatible() { const TopLevelProjectConstPtr restoredProject = m_result.loadedProject; if (m_parameters.finalBuildConfigurationTree() != restoredProject->buildConfiguration()) return false; for (QVariantMap::ConstIterator it = restoredProject->profileConfigs.constBegin(); it != restoredProject->profileConfigs.constEnd(); ++it) { const QVariantMap buildConfig = SetupProjectParameters::expandedBuildConfiguration( m_parameters.settingsDirectory(), it.key(), m_parameters.buildVariant()); const QVariantMap newConfig = SetupProjectParameters::finalBuildConfigurationTree( buildConfig, m_parameters.overriddenValues(), m_parameters.buildRoot(), m_parameters.topLevelProfile()); if (newConfig != it.value()) return false; } return true; } void BuildGraphLoader::rescueOldBuildData(const ResolvedProductConstPtr &restoredProduct, const ResolvedProductPtr &newlyResolvedProduct, ProjectBuildData *oldBuildData, const ChildListHash &childLists, const AllRescuableArtifactData &existingRad) { QBS_CHECK(newlyResolvedProduct); if (!restoredProduct->enabled || !newlyResolvedProduct->enabled) return; if (m_logger.traceEnabled()) { m_logger.qbsTrace() << QString::fromLocal8Bit("[BG] rescue data of " "product '%1'").arg(restoredProduct->uniqueName()); } QBS_CHECK(newlyResolvedProduct->buildData); QBS_CHECK(newlyResolvedProduct->buildData->rescuableArtifactData.isEmpty()); newlyResolvedProduct->buildData->rescuableArtifactData = existingRad; // This is needed for artifacts created by manually added transformers, which are // already present in the build graph. // FIXME: This complete block could go away if Transformers were also to create their // output artifacts at build time. QList oldArtifactsCreatedByTransformers; foreach (Artifact *artifact, ArtifactSet::fromNodeSet(newlyResolvedProduct->buildData->nodes)) { if (!artifact->transformer) continue; if (m_logger.traceEnabled()) { m_logger.qbsTrace() << QString::fromLocal8Bit("[BG] artifact '%1'") .arg(artifact->fileName()); } Artifact * const oldArtifact = lookupArtifact(restoredProduct, oldBuildData, artifact->dirPath(), artifact->fileName(), true); if (!oldArtifact || !oldArtifact->transformer) { if (m_logger.traceEnabled()) m_logger.qbsTrace() << QString::fromLocal8Bit("[BG] no transformer data"); continue; } oldArtifactsCreatedByTransformers << oldArtifact; if (!commandListsAreEqual(artifact->transformer->commands, oldArtifact->transformer->commands)) { if (m_logger.traceEnabled()) m_logger.qbsTrace() << QString::fromLocal8Bit("[BG] artifact invalidated"); removeGeneratedArtifactFromDisk(oldArtifact, m_logger); m_artifactsRemovedFromDisk << oldArtifact->filePath(); continue; } artifact->setTimestamp(oldArtifact->timestamp()); const ChildrenInfo &childrenInfo = childLists.value(oldArtifact); foreach (Artifact * const oldChild, childrenInfo.children) { Artifact * const newChild = lookupArtifact(oldChild->product, newlyResolvedProduct->topLevelProject()->buildData.data(), oldChild->filePath(), true); if (!newChild || artifact->children.contains(newChild)) continue; safeConnect(artifact, newChild, m_logger); if (childrenInfo.childrenAddedByScanner.contains(oldChild)) artifact->childrenAddedByScanner << newChild; } } // This is needed for artifacts created by rules, which happens later in the executor. foreach (Artifact * const oldArtifact, ArtifactSet::fromNodeSet(restoredProduct->buildData->nodes)) { if (!oldArtifact->transformer) continue; if (oldArtifactsCreatedByTransformers.contains(oldArtifact)) continue; Artifact * const newArtifact = lookupArtifact(newlyResolvedProduct, oldArtifact, false); if (!newArtifact) { RescuableArtifactData rad; rad.timeStamp = oldArtifact->timestamp(); rad.commands = oldArtifact->transformer->commands; const ChildrenInfo &childrenInfo = childLists.value(oldArtifact); foreach (Artifact * const child, childrenInfo.children) { rad.children << RescuableArtifactData::ChildData(child->product->name, child->product->profile, child->filePath(), childrenInfo.childrenAddedByScanner.contains(child)); } newlyResolvedProduct->buildData->rescuableArtifactData.insert( oldArtifact->filePath(), rad); } } } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/buildgraphloader.h000066400000000000000000000136301266132464200236620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_BUILDGRAPHLOADER_H #define QBS_BUILDGRAPHLOADER_H #include "forward_decls.h" #include "rescuableartifactdata.h" #include #include #include #include #include #include namespace qbs { namespace Internal { class FileDependency; class FileResourceBase; class FileTime; class NodeSet; class Property; class BuildGraphLoadResult { public: TopLevelProjectPtr newlyResolvedProject; TopLevelProjectPtr loadedProject; }; class BuildGraphLoader { public: BuildGraphLoader(const QProcessEnvironment &env, const Logger &logger); ~BuildGraphLoader(); BuildGraphLoadResult load(const TopLevelProjectPtr &existingProject, const SetupProjectParameters ¶meters, const RulesEvaluationContextPtr &evalContext); private: void loadBuildGraphFromDisk(); void checkBuildGraphCompatibility(const TopLevelProjectConstPtr &project); void trackProjectChanges(); bool hasEnvironmentChanged(const TopLevelProjectConstPtr &restoredProject) const; bool hasCanonicalFilePathResultChanged(const TopLevelProjectConstPtr &restoredProject) const; bool hasFileExistsResultChanged(const TopLevelProjectConstPtr &restoredProject) const; bool hasFileLastModifiedResultChanged(const TopLevelProjectConstPtr &restoredProject) const; bool hasProductFileChanged(const QList &restoredProducts, const FileTime &referenceTime, QSet &remainingBuildSystemFiles, QList &productsWithChangedFiles); bool hasBuildSystemFileChanged(const QSet &buildSystemFiles, const FileTime &referenceTime); void checkAllProductsForChanges(const QList &restoredProducts, const QMap &newlyResolvedProductsByName, QList &changedProducts); bool checkProductForChanges(const ResolvedProductPtr &restoredProduct, const ResolvedProductPtr &newlyResolvedProduct); bool checkProductForInstallInfoChanges(const ResolvedProductPtr &restoredProduct, const ResolvedProductPtr &newlyResolvedProduct); bool checkForPropertyChanges(const ResolvedProductPtr &restoredProduct, const ResolvedProductPtr &newlyResolvedProduct); bool checkTransformersForPropertyChanges(const ResolvedProductPtr &restoredProduct, const ResolvedProductPtr &newlyResolvedProduct); void onProductRemoved(const ResolvedProductPtr &product, ProjectBuildData *projectBuildData, bool removeArtifactsFromDisk = true); bool checkForPropertyChanges(const TransformerPtr &restoredTrafo, const ResolvedProductPtr &freshProduct); bool checkForPropertyChange(const Property &restoredProperty, const QVariantMap &newProperties); void replaceFileDependencyWithArtifact(const ResolvedProductPtr &fileDepProduct, FileDependency *filedep, Artifact *artifact); bool isConfigCompatible(); struct ChildrenInfo { ChildrenInfo() {} ChildrenInfo(const ArtifactSet &c1, const ArtifactSet &c2) : children(c1), childrenAddedByScanner(c2) {} ArtifactSet children; ArtifactSet childrenAddedByScanner; }; typedef QHash ChildListHash; void rescueOldBuildData(const ResolvedProductConstPtr &restoredProduct, const ResolvedProductPtr &newlyResolvedProduct, ProjectBuildData *oldBuildData, const ChildListHash &childLists, const AllRescuableArtifactData &existingRad); RulesEvaluationContextPtr m_evalContext; SetupProjectParameters m_parameters; BuildGraphLoadResult m_result; Logger m_logger; QProcessEnvironment m_environment; QStringList m_artifactsRemovedFromDisk; // These must only be deleted at the end so we can still peek into the old look-up table. QList m_objectsToDelete; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.4.5/src/lib/corelib/buildgraph/buildgraphnode.cpp000066400000000000000000000050431266132464200236730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "buildgraphnode.h" #include "buildgraphvisitor.h" #include "projectbuilddata.h" #include #include #include #include //#include namespace qbs { namespace Internal { BuildGraphNode::BuildGraphNode() : buildState(Untouched) { } BuildGraphNode::~BuildGraphNode() { foreach (BuildGraphNode *p, parents) p->children.remove(this); foreach (BuildGraphNode *c, children) c->parents.remove(this); } void BuildGraphNode::onChildDisconnected(BuildGraphNode *child) { Q_UNUSED(child); } void BuildGraphNode::acceptChildren(BuildGraphVisitor *visitor) { foreach (BuildGraphNode *child, children) child->accept(visitor); } void BuildGraphNode::load(PersistentPool &pool) { children.load(pool); // Parents must be updated after loading all nodes. } void BuildGraphNode::store(PersistentPool &pool) const { children.store(pool); // Do not store parents to avoid recursion. } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/buildgraphnode.h000066400000000000000000000052651266132464200233460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_BUILDGRAPHNODE_H #define QBS_BUILDGRAPHNODE_H #include "nodeset.h" #include #include #include namespace qbs { namespace Internal { class BuildGraphVisitor; class TopLevelProject; class BuildGraphNode : public virtual PersistentObject { friend class NodeSet; public: virtual ~BuildGraphNode(); NodeSet parents; NodeSet children; WeakPointer product; enum BuildState { Untouched = 0, Buildable, Building, Built }; BuildState buildState; // Do not serialize. Will be refreshed for every build. enum Type { ArtifactNodeType, RuleNodeType }; virtual Type type() const = 0; virtual void accept(BuildGraphVisitor *visitor) = 0; virtual QString toString() const = 0; virtual void onChildDisconnected(BuildGraphNode *child); protected: explicit BuildGraphNode(); void acceptChildren(BuildGraphVisitor *visitor); void load(PersistentPool &pool); void store(PersistentPool &pool) const; }; } // namespace Internal } // namespace qbs #endif // QBS_BUILDGRAPHNODE_H qbs-src-1.4.5/src/lib/corelib/buildgraph/buildgraphvisitor.h000066400000000000000000000041231266132464200241100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_BUILDGRAPHVISITOR_H #define QBS_BUILDGRAPHVISITOR_H namespace qbs { namespace Internal { class Artifact; class RuleNode; /*! * \brief The BuildGraphVisitor class * * The return value of a visit method indicates whether the children of the current node * are to be visited next. */ class BuildGraphVisitor { public: virtual bool visit(Artifact *) { return true; } virtual void endVisit(Artifact *) { } virtual bool visit(RuleNode *) { return true; } virtual void endVisit(RuleNode *) { } }; } // namespace Internal } // namespace qbs #endif // QBS_BUILDGRAPHVISITOR_H qbs-src-1.4.5/src/lib/corelib/buildgraph/command.cpp000066400000000000000000000342631266132464200223300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "command.h" #include #include #include #include #include #include #include namespace qbs { namespace Internal { AbstractCommand::AbstractCommand() : m_description(defaultDescription()), m_highlight(defaultHighLight()), m_silent(defaultIsSilent()) { } AbstractCommand::~AbstractCommand() { } bool AbstractCommand::equals(const AbstractCommand *other) const { return m_description == other->m_description && m_highlight == other->m_highlight && m_silent == other->m_silent && type() == other->type() && m_properties == other->m_properties; } void AbstractCommand::fillFromScriptValue(const QScriptValue *scriptValue, const CodeLocation &codeLocation) { m_description = scriptValue->property(QLatin1String("description")).toString(); m_highlight = scriptValue->property(QLatin1String("highlight")).toString(); m_silent = scriptValue->property(QLatin1String("silent")).toBool(); m_codeLocation = codeLocation; m_predefinedProperties << QLatin1String("description") << QLatin1String("highlight") << QLatin1String("silent"); } void AbstractCommand::load(PersistentPool &pool) { m_description = pool.idLoadString(); m_highlight = pool.idLoadString(); pool.stream() >> m_silent; m_codeLocation.load(pool); m_properties = pool.loadVariantMap(); } void AbstractCommand::store(PersistentPool &pool) const { pool.storeString(m_description); pool.storeString(m_highlight); pool.stream() << m_silent; m_codeLocation.store(pool); pool.store(m_properties); } void AbstractCommand::applyCommandProperties(const QScriptValue *scriptValue) { QScriptValueIterator it(*scriptValue); while (it.hasNext()) { it.next(); if (m_predefinedProperties.contains(it.name())) continue; m_properties.insert(it.name(), it.value().toVariant()); } } static QScriptValue js_CommandBase(QScriptContext *context, QScriptEngine *engine) { QScriptValue cmd = context->thisObject(); QBS_ASSERT(context->isCalledAsConstructor(), cmd = engine->newObject()); cmd.setProperty(QLatin1String("description"), engine->toScriptValue(AbstractCommand::defaultDescription())); cmd.setProperty(QLatin1String("highlight"), engine->toScriptValue(AbstractCommand::defaultHighLight())); cmd.setProperty(QLatin1String("silent"), engine->toScriptValue(AbstractCommand::defaultIsSilent())); return cmd; } static QScriptValue js_Command(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(!context->isCalledAsConstructor())) return context->throwError(Tr::tr("Command constructor called without new.")); static ProcessCommandPtr commandPrototype = ProcessCommand::create(); QScriptValue program = context->argument(0); if (program.isUndefined()) program = engine->toScriptValue(commandPrototype->program()); QScriptValue arguments = context->argument(1); if (arguments.isUndefined()) arguments = engine->toScriptValue(commandPrototype->arguments()); QScriptValue cmd = js_CommandBase(context, engine); cmd.setProperty(QLatin1String("className"), engine->toScriptValue(QString::fromLatin1("Command"))); cmd.setProperty(QLatin1String("program"), program); cmd.setProperty(QLatin1String("arguments"), arguments); cmd.setProperty(QLatin1String("workingDir"), engine->toScriptValue(commandPrototype->workingDir())); cmd.setProperty(QLatin1String("maxExitCode"), engine->toScriptValue(commandPrototype->maxExitCode())); cmd.setProperty(QLatin1String("stdoutFilterFunction"), engine->toScriptValue(commandPrototype->stdoutFilterFunction())); cmd.setProperty(QLatin1String("stderrFilterFunction"), engine->toScriptValue(commandPrototype->stderrFilterFunction())); cmd.setProperty(QLatin1String("responseFileThreshold"), engine->toScriptValue(commandPrototype->responseFileThreshold())); cmd.setProperty(QLatin1String("responseFileUsagePrefix"), engine->toScriptValue(commandPrototype->responseFileUsagePrefix())); cmd.setProperty(QLatin1String("environment"), engine->toScriptValue(commandPrototype->environment().toStringList())); return cmd; } void ProcessCommand::setupForJavaScript(QScriptValue targetObject) { QBS_CHECK(targetObject.isObject()); QScriptValue ctor = targetObject.engine()->newFunction(js_Command, 2); targetObject.setProperty(QLatin1String("Command"), ctor); } ProcessCommand::ProcessCommand() : m_maxExitCode(0) , m_responseFileThreshold(HostOsInfo::isWindowsHost() ? 32000 : -1) { } void ProcessCommand::getEnvironmentFromList(const QStringList &envList) { m_environment.clear(); foreach (const QString &env, envList) { const int equalsIndex = env.indexOf(QLatin1Char('=')); if (equalsIndex <= 0 || equalsIndex == env.count() - 1) continue; const QString &var = env.left(equalsIndex); const QString &value = env.mid(equalsIndex + 1); m_environment.insert(var, value); } } bool ProcessCommand::equals(const AbstractCommand *otherAbstractCommand) const { if (!AbstractCommand::equals(otherAbstractCommand)) return false; const ProcessCommand * const other = static_cast(otherAbstractCommand); return m_program == other->m_program && m_arguments == other->m_arguments && m_workingDir == other->m_workingDir && m_maxExitCode == other->m_maxExitCode && m_stdoutFilterFunction == other->m_stdoutFilterFunction && m_stderrFilterFunction == other->m_stderrFilterFunction && m_responseFileThreshold == other->m_responseFileThreshold && m_responseFileUsagePrefix == other->m_responseFileUsagePrefix && m_environment == other->m_environment; } void ProcessCommand::fillFromScriptValue(const QScriptValue *scriptValue, const CodeLocation &codeLocation) { AbstractCommand::fillFromScriptValue(scriptValue, codeLocation); m_program = scriptValue->property(QLatin1String("program")).toString(); m_arguments = scriptValue->property(QLatin1String("arguments")).toVariant().toStringList(); m_workingDir = scriptValue->property(QLatin1String("workingDirectory")).toString(); m_maxExitCode = scriptValue->property(QLatin1String("maxExitCode")).toInt32(); QScriptValue stdoutFilterFunction = scriptValue->property(QLatin1String("stdoutFilterFunction")).toString(); if (stdoutFilterFunction.isFunction()) m_stdoutFilterFunction = QLatin1String("(") + stdoutFilterFunction.toString() + QLatin1String(")()"); else m_stdoutFilterFunction = stdoutFilterFunction.toString(); QScriptValue stderrFilterFunction = scriptValue->property(QLatin1String("stderrFilterFunction")).toString(); if (stderrFilterFunction.isFunction()) m_stderrFilterFunction = QLatin1String("(") + stderrFilterFunction.toString() + QLatin1String(")()"); else m_stderrFilterFunction = stderrFilterFunction.toString(); m_responseFileThreshold = scriptValue->property(QLatin1String("responseFileThreshold")) .toInt32(); m_responseFileUsagePrefix = scriptValue->property(QLatin1String("responseFileUsagePrefix")) .toString(); QStringList envList = scriptValue->property(QLatin1String("environment")).toVariant() .toStringList(); getEnvironmentFromList(envList); m_predefinedProperties << QLatin1String("program") << QLatin1String("arguments") << QLatin1String("workingDirectory") << QLatin1String("maxExitCode") << QLatin1String("stdoutFilterFunction") << QLatin1String("stderrFilterFunction") << QLatin1String("responseFileThreshold") << QLatin1String("responseFileUsagePrefix") << QLatin1String("environment"); applyCommandProperties(scriptValue); } void ProcessCommand::load(PersistentPool &pool) { AbstractCommand::load(pool); m_program = pool.idLoadString(); m_arguments = pool.idLoadStringList(); const QStringList envList = pool.idLoadStringList(); m_workingDir = pool.idLoadString(); m_stdoutFilterFunction = pool.idLoadString(); m_stderrFilterFunction = pool.idLoadString(); m_responseFileUsagePrefix = pool.idLoadString(); pool.stream() >> m_maxExitCode >> m_responseFileThreshold; getEnvironmentFromList(envList); } void ProcessCommand::store(PersistentPool &pool) const { AbstractCommand::store(pool); pool.storeString(m_program); pool.storeStringList(m_arguments); pool.storeStringList(m_environment.toStringList()); pool.storeString(m_workingDir); pool.storeString(m_stdoutFilterFunction); pool.storeString(m_stderrFilterFunction); pool.storeString(m_responseFileUsagePrefix); pool.stream() << m_maxExitCode << m_responseFileThreshold; } static QScriptValue js_JavaScriptCommand(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(!context->isCalledAsConstructor())) return context->throwError(Tr::tr("JavaScriptCommand constructor called without new.")); if (Q_UNLIKELY(context->argumentCount() != 0)) { return context->throwError(QScriptContext::SyntaxError, QLatin1String("JavaScriptCommand c'tor doesn't take arguments.")); } static JavaScriptCommandPtr commandPrototype = JavaScriptCommand::create(); QScriptValue cmd = js_CommandBase(context, engine); cmd.setProperty(QLatin1String("className"), engine->toScriptValue(QString::fromLatin1("JavaScriptCommand"))); cmd.setProperty(QLatin1String("sourceCode"), engine->toScriptValue(commandPrototype->sourceCode())); return cmd; } void JavaScriptCommand::setupForJavaScript(QScriptValue targetObject) { QBS_CHECK(targetObject.isObject()); QScriptValue ctor = targetObject.engine()->newFunction(js_JavaScriptCommand, 0); targetObject.setProperty(QLatin1String("JavaScriptCommand"), ctor); } JavaScriptCommand::JavaScriptCommand() { } bool JavaScriptCommand::equals(const AbstractCommand *otherAbstractCommand) const { if (!AbstractCommand::equals(otherAbstractCommand)) return false; const JavaScriptCommand * const other = static_cast(otherAbstractCommand); return m_sourceCode == other->m_sourceCode; } void JavaScriptCommand::fillFromScriptValue(const QScriptValue *scriptValue, const CodeLocation &codeLocation) { AbstractCommand::fillFromScriptValue(scriptValue, codeLocation); QScriptValue sourceCode = scriptValue->property(QLatin1String("sourceCode")); if (sourceCode.isFunction()) m_sourceCode = QLatin1String("(") + sourceCode.toString() + QLatin1String(")()"); else m_sourceCode = sourceCode.toString(); m_predefinedProperties << QLatin1String("className") << QLatin1String("sourceCode"); applyCommandProperties(scriptValue); } void JavaScriptCommand::load(PersistentPool &pool) { AbstractCommand::load(pool); m_sourceCode = pool.idLoadString(); } void JavaScriptCommand::store(PersistentPool &pool) const { AbstractCommand::store(pool); pool.storeString(m_sourceCode); } QList loadCommandList(PersistentPool &pool) { QList commands; int count; pool.stream() >> count; commands.reserve(count); while (--count >= 0) { int cmdType; pool.stream() >> cmdType; AbstractCommandPtr cmd; switch (cmdType) { case AbstractCommand::JavaScriptCommandType: cmd = pool.idLoadS(); break; case AbstractCommand::ProcessCommandType: cmd = pool.idLoadS(); break; default: QBS_CHECK(false); } commands += cmd; } return commands; } void storeCommandList(const QList &commands, PersistentPool &pool) { pool.stream() << commands.count(); foreach (const AbstractCommandPtr &cmd, commands) { pool.stream() << int(cmd->type()); pool.store(cmd); } } bool commandListsAreEqual(const QList &l1, const QList &l2) { if (l1.count() != l2.count()) return false; for (int i = 0; i < l1.count(); ++i) if (!l1.at(i)->equals(l2.at(i).data())) return false; return true; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/command.h000066400000000000000000000131151266132464200217660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_COMMAND_H #define QBS_COMMAND_H #include "forward_decls.h" #include #include #include #include #include #include #include namespace qbs { namespace Internal { class AbstractCommand : public PersistentObject { public: virtual ~AbstractCommand(); enum CommandType { ProcessCommandType, JavaScriptCommandType }; static QString defaultDescription() { return QString(); } static QString defaultHighLight() { return QString(); } static bool defaultIsSilent() { return false; } virtual CommandType type() const = 0; virtual bool equals(const AbstractCommand *other) const; virtual void fillFromScriptValue(const QScriptValue *scriptValue, const CodeLocation &codeLocation); const QString description() const { return m_description; } const QString highlight() const { return m_highlight; } bool isSilent() const { return m_silent; } CodeLocation codeLocation() const { return m_codeLocation; } const QVariantMap &properties() const { return m_properties; } protected: AbstractCommand(); void load(PersistentPool &pool); void store(PersistentPool &pool) const; void applyCommandProperties(const QScriptValue *scriptValue); QSet m_predefinedProperties; private: QString m_description; QString m_highlight; bool m_silent; CodeLocation m_codeLocation; QVariantMap m_properties; }; class ProcessCommand : public AbstractCommand { public: static ProcessCommandPtr create() { return ProcessCommandPtr(new ProcessCommand); } static void setupForJavaScript(QScriptValue targetObject); CommandType type() const { return ProcessCommandType; } bool equals(const AbstractCommand *otherAbstractCommand) const; void fillFromScriptValue(const QScriptValue *scriptValue, const CodeLocation &codeLocation); const QString program() const { return m_program; } const QStringList arguments() const { return m_arguments; } const QString workingDir() const { return m_workingDir; } int maxExitCode() const { return m_maxExitCode; } QString stdoutFilterFunction() const { return m_stdoutFilterFunction; } QString stderrFilterFunction() const { return m_stderrFilterFunction; } int responseFileThreshold() const { return m_responseFileThreshold; } QString responseFileUsagePrefix() const { return m_responseFileUsagePrefix; } QProcessEnvironment environment() const { return m_environment; } private: ProcessCommand(); void load(PersistentPool &pool); void store(PersistentPool &pool) const; void getEnvironmentFromList(const QStringList &envList); QString m_program; QStringList m_arguments; QString m_workingDir; int m_maxExitCode; QString m_stdoutFilterFunction; QString m_stderrFilterFunction; int m_responseFileThreshold; // When to use response files? In bytes of (program name + arguments). QString m_responseFileUsagePrefix; QProcessEnvironment m_environment; }; class JavaScriptCommand : public AbstractCommand { public: static JavaScriptCommandPtr create() { return JavaScriptCommandPtr(new JavaScriptCommand); } static void setupForJavaScript(QScriptValue targetObject); virtual CommandType type() const { return JavaScriptCommandType; } bool equals(const AbstractCommand *otherAbstractCommand) const; void fillFromScriptValue(const QScriptValue *scriptValue, const CodeLocation &codeLocation); const QString &sourceCode() const { return m_sourceCode; } void setSourceCode(const QString &str) { m_sourceCode = str; } private: JavaScriptCommand(); void load(PersistentPool &pool); void store(PersistentPool &pool) const; QString m_sourceCode; }; QList loadCommandList(PersistentPool &pool); void storeCommandList(const QList &commands, PersistentPool &pool); bool commandListsAreEqual(const QList &l1, const QList &l2); } // namespace Internal } // namespace qbs #endif // QBS_COMMAND_H qbs-src-1.4.5/src/lib/corelib/buildgraph/cycledetector.cpp000066400000000000000000000063321266132464200235370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "cycledetector.h" #include "artifact.h" #include "buildgraph.h" #include "projectbuilddata.h" #include "rulenode.h" #include #include #include namespace qbs { namespace Internal { CycleDetector::CycleDetector(const Logger &logger) : m_parent(0), m_logger(logger) { } void CycleDetector::visitProject(const TopLevelProjectConstPtr &project) { const QString description = QString::fromLocal8Bit("Cycle detection for project '%1'") .arg(project->name); TimedActivityLogger timeLogger(m_logger, description, QLatin1String("[BG] "), LoggerTrace); project->accept(this); } void CycleDetector::visitProduct(const ResolvedProductConstPtr &product) { product->accept(this); } bool CycleDetector::visit(Artifact *artifact) { return visitNode(artifact); } bool CycleDetector::visit(RuleNode *ruleNode) { return visitNode(ruleNode); } bool CycleDetector::visitNode(BuildGraphNode *node) { if (Q_UNLIKELY(m_nodesInCurrentPath.contains(node))) { ErrorInfo error(Tr::tr("Cycle in build graph detected.")); foreach (const BuildGraphNode * const n, cycle(node)) error.append(n->toString()); throw error; } if (m_allNodes.contains(node)) return false; m_nodesInCurrentPath += node; m_parent = node; foreach (BuildGraphNode * const child, node->children) child->accept(this); m_nodesInCurrentPath -= node; m_allNodes += node; return false; } QList CycleDetector::cycle(BuildGraphNode *doubleEntry) { QList path; findPath(doubleEntry, m_parent, path); return path << doubleEntry; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/cycledetector.h000066400000000000000000000045261266132464200232070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_CYCLEDETECTOR_H #define QBS_CYCLEDETECTOR_H #include "buildgraphvisitor.h" #include #include #include namespace qbs { namespace Internal { class BuildGraphNode; class CycleDetector : private BuildGraphVisitor { public: CycleDetector(const Logger &logger); void visitProject(const TopLevelProjectConstPtr &project); void visitProduct(const ResolvedProductConstPtr &product); private: bool visit(Artifact *artifact); bool visit(RuleNode *ruleNode); bool visitNode(BuildGraphNode *node); QList cycle(BuildGraphNode *doubleEntry); QSet m_allNodes; QSet m_nodesInCurrentPath; BuildGraphNode *m_parent; Logger m_logger; }; } // namespace Internal } // namespace qbs #endif // QBS_CYCLEDETECTOR_H qbs-src-1.4.5/src/lib/corelib/buildgraph/depscanner.cpp000066400000000000000000000172641266132464200230360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "depscanner.h" #include "artifact.h" #include "projectbuilddata.h" #include "buildgraph.h" #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { static void collectCppIncludePaths(const QVariantMap &modules, QSet *collectedPaths) { QMapIterator iterator(modules); while (iterator.hasNext()) { iterator.next(); if (iterator.key() == QLatin1String("cpp")) { QVariant includePathsVariant = iterator.value().toMap().value(QLatin1String("includePaths")); if (includePathsVariant.isValid()) collectedPaths->unite(QSet::fromList(includePathsVariant.toStringList())); } else { collectCppIncludePaths(iterator.value().toMap().value(QLatin1String("modules")).toMap(), collectedPaths); } } } PluginDependencyScanner::PluginDependencyScanner(ScannerPlugin *plugin) : m_plugin(plugin) { } QStringList PluginDependencyScanner::collectSearchPaths(Artifact *artifact) { if (m_plugin->flags & ScannerUsesCppIncludePaths) { QVariantMap modules = artifact->properties->value().value(QLatin1String("modules")).toMap(); QSet collectedPaths; collectCppIncludePaths(modules, &collectedPaths); return QStringList(collectedPaths.toList()); } else { return QStringList(); } } QStringList PluginDependencyScanner::collectDependencies(FileResourceBase *file) { QSet result; QString baseDirOfInFilePath = file->dirPath(); const QString &filepath = file->filePath(); void *scannerHandle = m_plugin->open(filepath.utf16(), ScanForDependenciesFlag); if (!scannerHandle) return QStringList(); forever { int flags = 0; int length = 0; const char *szOutFilePath = m_plugin->next(scannerHandle, &length, &flags); if (szOutFilePath == 0) break; QString outFilePath = QString::fromLocal8Bit(szOutFilePath, length); if (outFilePath.isEmpty()) continue; if (flags & SC_LOCAL_INCLUDE_FLAG) { QString localFilePath = FileInfo::resolvePath(baseDirOfInFilePath, outFilePath); if (FileInfo::exists(localFilePath)) outFilePath = localFilePath; } result += outFilePath; } m_plugin->close(scannerHandle); return QStringList(result.toList()); } bool PluginDependencyScanner::recursive() const { return m_plugin->flags & ScannerRecursiveDependencies; } const void *PluginDependencyScanner::key() const { return m_plugin; } UserDependencyScanner::UserDependencyScanner(const ResolvedScannerConstPtr &scanner, const Logger &logger) : m_scanner(scanner), m_logger(logger), m_engine(new ScriptEngine(logger)), m_observer(m_engine), m_product(0) { m_engine->setProcessEventsInterval(-1); // QBS-782 m_global = m_engine->newObject(); setupScriptEngineForFile(m_engine, m_scanner->scanScript->fileContext, m_global); } UserDependencyScanner::~UserDependencyScanner() { delete m_engine; } QStringList UserDependencyScanner::collectSearchPaths(Artifact *artifact) { return evaluate(artifact, m_scanner->searchPathsScript); } QStringList UserDependencyScanner::collectDependencies(FileResourceBase *file) { // ### support user dependency scanners for file deps Artifact *artifact = dynamic_cast(file); if (!artifact) return QStringList(); return evaluate(artifact, m_scanner->scanScript); } bool UserDependencyScanner::recursive() const { return m_scanner->recursive; } const void *UserDependencyScanner::key() const { return m_scanner.data(); } QStringList UserDependencyScanner::evaluate(Artifact *artifact, const ScriptFunctionPtr &script) { if (artifact->product.data() != m_product) { m_product = artifact->product.data(); setupScriptEngineForProduct(m_engine, artifact->product, m_scanner->module, m_global, &m_observer); } QScriptValue artifactConfig = m_engine->newObject(); ModuleProperties::init(artifactConfig, artifact); artifactConfig.setProperty(QLatin1String("fileName"), artifact->filePath(), 0); const QStringList fileTags = artifact->fileTags().toStringList(); artifactConfig.setProperty(QLatin1String("fileTags"), m_engine->toScriptValue(fileTags)); if (!m_scanner->module->name.isEmpty()) artifactConfig.setProperty(QLatin1String("moduleName"), m_scanner->module->name); QScriptValueList args; args.reserve(3); args.append(m_global.property(QString::fromLatin1("project"))); args.append(m_global.property(QString::fromLatin1("product"))); args.append(artifactConfig); QScriptContext *ctx = m_engine->currentContext(); ctx->pushScope(m_global); QScriptValue &function = script->scriptFunction; if (!function.isValid() || function.engine() != m_engine) { function = m_engine->evaluate(script->sourceCode); if (Q_UNLIKELY(!function.isFunction())) throw ErrorInfo(Tr::tr("Invalid scan script."), script->location); } QScriptValue result = function.call(QScriptValue(), args); ctx->popScope(); m_engine->clearRequestedProperties(); if (Q_UNLIKELY(m_engine->hasErrorOrException(result))) { QString msg = Tr::tr("evaluating scan script: ") + m_engine->lastErrorString(result); m_engine->clearExceptions(); throw ErrorInfo(msg, script->location); } QStringList list; if (result.isArray()) { const int count = result.property(QLatin1String("length")).toInt32(); list.reserve(count); for (qint32 i = 0; i < count; ++i) { QScriptValue item = result.property(i); if (item.isValid() && !item.isUndefined()) list.append(item.toString()); } } return list; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/depscanner.h000066400000000000000000000062341266132464200224760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_DEPENDENCY_SCANNER_H #define QBS_DEPENDENCY_SCANNER_H #include #include #include #include #include class ScannerPlugin; namespace qbs { namespace Internal { class Artifact; class FileResourceBase; class Logger; class ScriptEngine; class DependencyScanner { public: virtual ~DependencyScanner() {} virtual QStringList collectSearchPaths(Artifact *artifact) = 0; virtual QStringList collectDependencies(FileResourceBase *file) = 0; virtual bool recursive() const = 0; virtual const void *key() const = 0; }; class PluginDependencyScanner : public DependencyScanner { public: PluginDependencyScanner(ScannerPlugin *plugin); private: QStringList collectSearchPaths(Artifact *artifact); QStringList collectDependencies(FileResourceBase *file); bool recursive() const; const void *key() const; ScannerPlugin* m_plugin; }; class UserDependencyScanner : public DependencyScanner { public: UserDependencyScanner(const ResolvedScannerConstPtr &scanner, const Logger &logger); ~UserDependencyScanner(); private: QStringList collectSearchPaths(Artifact *artifact); QStringList collectDependencies(FileResourceBase *file); bool recursive() const; const void *key() const; QStringList evaluate(Artifact *artifact, const ScriptFunctionPtr &script); ResolvedScannerConstPtr m_scanner; Logger m_logger; ScriptEngine *m_engine; PrepareScriptObserver m_observer; QScriptValue m_global; void *m_product; }; } // namespace Internal } // namespace qbs #endif // QBS_DEPENDENCY_SCANNER_H qbs-src-1.4.5/src/lib/corelib/buildgraph/emptydirectoriesremover.cpp000066400000000000000000000073641266132464200257070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "emptydirectoriesremover.h" #include "artifact.h" #include #include #include namespace qbs { namespace Internal { EmptyDirectoriesRemover::EmptyDirectoriesRemover(const TopLevelProject *project, const Logger &logger) : m_project(project), m_logger(logger) { } void EmptyDirectoriesRemover::removeEmptyParentDirectories(const QStringList &artifactFilePaths) { m_dirsToRemove.clear(); m_handledDirs.clear(); foreach (const QString &filePath, artifactFilePaths) insertSorted(QFileInfo(filePath).absolutePath()); while (!m_dirsToRemove.isEmpty()) removeDirIfEmpty(); } void EmptyDirectoriesRemover::removeEmptyParentDirectories(const ArtifactSet &artifacts) { QStringList filePaths; foreach (const Artifact * const a, artifacts) { if (a->artifactType == Artifact::Generated) filePaths << a->filePath(); } removeEmptyParentDirectories(filePaths); } // List is sorted so that "deeper" directories come first. void EmptyDirectoriesRemover::insertSorted(const QString &dirPath) { int i; for (i = 0; i < m_dirsToRemove.count(); ++i) { const QString &cur = m_dirsToRemove.at(i); if (dirPath == cur) return; if (dirPath.count(QLatin1Char('/')) > cur.count(QLatin1Char('/'))) break; } m_dirsToRemove.insert(i, dirPath); } void EmptyDirectoriesRemover::removeDirIfEmpty() { const QString dirPath = m_dirsToRemove.takeFirst(); m_handledDirs.insert(dirPath); QFileInfo fi(dirPath); if (fi.isSymLink() || !fi.exists() || !dirPath.startsWith(m_project->buildDirectory) || fi.filePath() == m_project->buildDirectory) { return; } QDir dir(dirPath); dir.setFilter(QDir::AllEntries | QDir::NoDotAndDotDot); if (dir.count() != 0) return; dir.cdUp(); if (!dir.rmdir(fi.fileName())) { m_logger.qbsWarning() << QString::fromLocal8Bit("Cannot remove empty directory '%1'.") .arg(dirPath); return; } const QString parentDir = dir.path(); if (!m_handledDirs.contains(parentDir)) insertSorted(parentDir); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/emptydirectoriesremover.h000066400000000000000000000044061266132464200253460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_EMPTYDIRECTORIESREMOVER_H #define QBS_EMPTYDIRECTORIESREMOVER_H #include #include #include namespace qbs { namespace Internal { class ArtifactSet; class TopLevelProject; class EmptyDirectoriesRemover { public: EmptyDirectoriesRemover(const TopLevelProject *project, const Logger &logger); void removeEmptyParentDirectories(const QStringList &artifactFilePaths); void removeEmptyParentDirectories(const ArtifactSet &artifacts); private: void insertSorted(const QString &dirPath); void removeDirIfEmpty(); const TopLevelProject * const m_project; Logger m_logger; QStringList m_dirsToRemove; QSet m_handledDirs; }; } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-1.4.5/src/lib/corelib/buildgraph/executor.cpp000066400000000000000000001131421266132464200225420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "executor.h" #include "buildgraph.h" #include "command.h" #include "emptydirectoriesremover.h" #include "productbuilddata.h" #include "projectbuilddata.h" #include "cycledetector.h" #include "executorjob.h" #include "inputartifactscanner.h" #include "productinstaller.h" #include "rescuableartifactdata.h" #include "rulenode.h" #include "rulesevaluationcontext.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { bool Executor::ComparePriority::operator() (const BuildGraphNode *x, const BuildGraphNode *y) const { return x->product->buildData->buildPriority < y->product->buildData->buildPriority; } Executor::Executor(const Logger &logger, QObject *parent) : QObject(parent) , m_productInstaller(0) , m_logger(logger) , m_progressObserver(0) , m_state(ExecutorIdle) , m_cancelationTimer(new QTimer(this)) , m_doTrace(logger.traceEnabled()) , m_doDebug(logger.debugEnabled()) { m_inputArtifactScanContext = new InputArtifactScannerContext(&m_scanResultCache); m_cancelationTimer->setSingleShot(false); m_cancelationTimer->setInterval(1000); connect(m_cancelationTimer, SIGNAL(timeout()), SLOT(checkForCancellation())); } Executor::~Executor() { // jobs must be destroyed before deleting the shared scan result cache foreach (ExecutorJob *job, m_availableJobs) delete job; foreach (ExecutorJob *job, m_processingJobs.keys()) delete job; delete m_inputArtifactScanContext; delete m_productInstaller; } FileTime Executor::recursiveFileTime(const QString &filePath) const { FileTime newest; FileInfo fileInfo(filePath); if (!fileInfo.exists()) { const QString nativeFilePath = QDir::toNativeSeparators(filePath); m_logger.qbsWarning() << Tr::tr("File '%1' not found.").arg(nativeFilePath); return newest; } newest = qMax(fileInfo.lastModified(), fileInfo.lastStatusChange()); if (!fileInfo.isDir()) return newest; const QStringList dirContents = QDir(filePath) .entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); foreach (const QString &curFileName, dirContents) { const FileTime ft = recursiveFileTime(filePath + QLatin1Char('/') + curFileName); if (ft > newest) newest = ft; } return newest; } void Executor::retrieveSourceFileTimestamp(Artifact *artifact) const { QBS_CHECK(artifact->artifactType == Artifact::SourceFile); if (m_buildOptions.changedFiles().isEmpty()) artifact->setTimestamp(recursiveFileTime(artifact->filePath())); else if (m_buildOptions.changedFiles().contains(artifact->filePath())) artifact->setTimestamp(FileTime::currentTime()); else if (!artifact->timestamp().isValid()) artifact->setTimestamp(recursiveFileTime(artifact->filePath())); artifact->timestampRetrieved = true; } void Executor::build() { try { doBuild(); } catch (const ErrorInfo &e) { handleError(e); } } void Executor::setProject(const TopLevelProjectPtr &project) { m_project = project; } void Executor::setProducts(const QList &productsToBuild) { m_productsToBuild = productsToBuild; } class ProductPrioritySetter { const TopLevelProject *m_topLevelProject; unsigned int m_priority; QSet m_seenProducts; public: ProductPrioritySetter(const TopLevelProject *tlp) : m_topLevelProject(tlp) { } void apply() { QList allProducts = m_topLevelProject->allProducts(); QSet allDependencies; foreach (const ResolvedProductPtr &product, allProducts) allDependencies += product->dependencies; QSet rootProducts = allProducts.toSet() - allDependencies; m_priority = UINT_MAX; m_seenProducts.clear(); foreach (const ResolvedProductPtr &rootProduct, rootProducts) traverse(rootProduct); } private: void traverse(const ResolvedProductPtr &product) { if (m_seenProducts.contains(product)) return; m_seenProducts += product; foreach (const ResolvedProductPtr &dependency, product->dependencies) traverse(dependency); if (!product->buildData) return; product->buildData->buildPriority = m_priority--; } }; void Executor::doBuild() { if (m_buildOptions.maxJobCount() <= 0) { m_buildOptions.setMaxJobCount(BuildOptions::defaultMaxJobCount()); m_logger.qbsDebug() << "max job count not explicitly set, using value of " << m_buildOptions.maxJobCount(); } QBS_CHECK(m_state == ExecutorIdle); m_leaves = Leaves(); m_changedSourceArtifacts.clear(); m_error.clear(); m_explicitlyCanceled = false; m_activeFileTags = FileTags::fromStringList(m_buildOptions.activeFileTags()); m_artifactsRemovedFromDisk.clear(); setState(ExecutorRunning); if (m_productsToBuild.isEmpty()) { m_logger.qbsTrace() << "No products to build, finishing."; QTimer::singleShot(0, this, SLOT(finish())); // Don't call back on the caller. return; } doSanityChecks(); m_evalContext = m_project->buildData->evaluationContext; if (!m_evalContext) { // Is null before the first build. m_evalContext = RulesEvaluationContextPtr(new RulesEvaluationContext(m_logger)); m_project->buildData->evaluationContext = m_evalContext; } InstallOptions installOptions; installOptions.setDryRun(m_buildOptions.dryRun()); installOptions.setInstallRoot(m_productsToBuild.first()->moduleProperties ->qbsPropertyValue(QLatin1String("installRoot")).toString()); installOptions.setKeepGoing(m_buildOptions.keepGoing()); m_productInstaller = new ProductInstaller(m_project, m_productsToBuild, installOptions, m_progressObserver, m_logger); if (m_buildOptions.removeExistingInstallation()) m_productInstaller->removeInstallRoot(); addExecutorJobs(); prepareAllNodes(); prepareProducts(); setupRootNodes(); prepareReachableNodes(); setupProgressObserver(); initLeaves(); if (!scheduleJobs()) { m_logger.qbsTrace() << "Nothing to do at all, finishing."; QTimer::singleShot(0, this, SLOT(finish())); // Don't call back on the caller. } if (m_progressObserver) m_cancelationTimer->start(); } void Executor::setBuildOptions(const BuildOptions &buildOptions) { m_buildOptions = buildOptions; } void Executor::initLeaves() { updateLeaves(m_roots); } void Executor::updateLeaves(const NodeSet &nodes) { NodeSet seenNodes; foreach (BuildGraphNode * const node, nodes) updateLeaves(node, seenNodes); } void Executor::updateLeaves(BuildGraphNode *node, NodeSet &seenNodes) { if (seenNodes.contains(node)) return; seenNodes += node; // Artifacts that appear in the build graph after // prepareBuildGraph() has been called, must be initialized. if (node->buildState == BuildGraphNode::Untouched) { node->buildState = BuildGraphNode::Buildable; Artifact *artifact = dynamic_cast(node); if (artifact && artifact->artifactType == Artifact::SourceFile) retrieveSourceFileTimestamp(artifact); } bool isLeaf = true; foreach (BuildGraphNode *child, node->children) { if (child->buildState != BuildGraphNode::Built) { isLeaf = false; updateLeaves(child, seenNodes); } } if (isLeaf) { if (m_doDebug) m_logger.qbsDebug() << "[EXEC] adding leaf " << node->toString(); m_leaves.push(node); } } // Returns true if some artifacts are still waiting to be built or currently building. bool Executor::scheduleJobs() { QBS_CHECK(m_state == ExecutorRunning); while (!m_leaves.empty() && !m_availableJobs.isEmpty()) { BuildGraphNode * const nodeToBuild = m_leaves.top(); m_leaves.pop(); switch (nodeToBuild->buildState) { case BuildGraphNode::Untouched: QBS_ASSERT(!"untouched node in leaves list", qDebug("%s", qPrintable(nodeToBuild->toString()))); break; case BuildGraphNode::Buildable: // This is the only state in which we want to build a node. nodeToBuild->accept(this); break; case BuildGraphNode::Building: if (m_doDebug) { m_logger.qbsDebug() << "[EXEC] " << nodeToBuild->toString(); m_logger.qbsDebug() << "[EXEC] node is currently being built. Skipping."; } break; case BuildGraphNode::Built: if (m_doDebug) { m_logger.qbsDebug() << "[EXEC] " << nodeToBuild->toString(); m_logger.qbsDebug() << "[EXEC] node already built. Skipping."; } break; } } return !m_leaves.empty() || !m_processingJobs.isEmpty(); } bool Executor::isUpToDate(Artifact *artifact) const { QBS_CHECK(artifact->artifactType == Artifact::Generated); if (m_doDebug) { m_logger.qbsDebug() << "[UTD] check " << artifact->filePath() << " " << artifact->timestamp().toString(); } if (m_buildOptions.forceTimestampCheck()) { artifact->setTimestamp(FileInfo(artifact->filePath()).lastModified()); if (m_doDebug) { m_logger.qbsDebug() << "[UTD] timestamp retrieved from filesystem: " << artifact->timestamp().toString(); } } if (!artifact->timestamp().isValid()) { if (m_doDebug) m_logger.qbsDebug() << "[UTD] invalid timestamp. Out of date."; return false; } foreach (Artifact *childArtifact, ArtifactSet::fromNodeSet(artifact->children)) { QBS_CHECK(childArtifact->timestamp().isValid()); if (m_doDebug) { m_logger.qbsDebug() << "[UTD] child timestamp " << childArtifact->timestamp().toString() << " " << childArtifact->filePath(); } if (artifact->timestamp() < childArtifact->timestamp()) return false; } foreach (FileDependency *fileDependency, artifact->fileDependencies) { if (!fileDependency->timestamp().isValid()) { FileInfo fi(fileDependency->filePath()); fileDependency->setTimestamp(fi.lastModified()); if (!fileDependency->timestamp().isValid()) { if (m_doDebug) { m_logger.qbsDebug() << "[UTD] file dependency doesn't exist " << fileDependency->filePath(); } return false; } } if (m_doDebug) { m_logger.qbsDebug() << "[UTD] file dependency timestamp " << fileDependency->timestamp().toString() << " " << fileDependency->filePath(); } if (artifact->timestamp() < fileDependency->timestamp()) return false; } return true; } bool Executor::mustExecuteTransformer(const TransformerPtr &transformer) const { bool hasAlwaysUpdatedArtifacts = false; foreach (Artifact *artifact, transformer->outputs) { if (artifact->alwaysUpdated) hasAlwaysUpdatedArtifacts = true; else if (!m_buildOptions.forceTimestampCheck()) continue; const bool upToDate = isUpToDate(artifact); // The invariant is that all output artifacts of a transformer have the same // "virtual" timestamp. However, if the user requested that on-disk timestamps be evaluated, // they can differ and the oldest output file of the transformer decides. if (!upToDate || !m_buildOptions.forceTimestampCheck()) return !upToDate; } // If all artifacts in a transformer have "alwaysUpdated" set to false, that transformer // is always run. return !hasAlwaysUpdatedArtifacts; } void Executor::buildArtifact(Artifact *artifact) { if (m_doDebug) m_logger.qbsDebug() << "[EXEC] " << relativeArtifactFileName(artifact); QBS_CHECK(artifact->buildState == BuildGraphNode::Buildable); // skip artifacts without transformer if (artifact->artifactType != Artifact::Generated) { // For source artifacts, that were not reachable when initializing the build, we must // retrieve timestamps. This can happen, if a dependency that's added during the build // makes the source artifact reachable. if (artifact->artifactType == Artifact::SourceFile && !artifact->timestampRetrieved) retrieveSourceFileTimestamp(artifact); if (m_doDebug) m_logger.qbsDebug() << QString::fromLocal8Bit("[EXEC] artifact type %1. Skipping.") .arg(toString(artifact->artifactType)); finishArtifact(artifact); return; } // Every generated artifact must have a transformer. QBS_CHECK(artifact->transformer); potentiallyRunTransformer(artifact->transformer); } void Executor::executeRuleNode(RuleNode *ruleNode) { QBS_CHECK(!m_evalContext->isActive()); ArtifactSet changedInputArtifacts; if (ruleNode->rule()->isDynamic()) { foreach (Artifact *artifact, m_changedSourceArtifacts) { if (artifact->product != ruleNode->product) continue; if (ruleNode->rule()->acceptsAsInput(artifact)) changedInputArtifacts += artifact; } foreach (Artifact *artifact, ArtifactSet::fromNodeSet(ruleNode->product->buildData->nodes)) { if (artifact->artifactType == Artifact::SourceFile) continue; if (artifact->timestampRetrieved && !isUpToDate(artifact) && ruleNode->rule()->acceptsAsInput(artifact)) { changedInputArtifacts += artifact; } } } RuleNode::ApplicationResult result; ruleNode->apply(m_logger, changedInputArtifacts, &result); if (result.upToDate) { if (m_doDebug) m_logger.qbsDebug() << "[EXEC] " << ruleNode->toString() << " is up to date. Skipping."; } else { if (m_doDebug) m_logger.qbsDebug() << "[EXEC] " << ruleNode->toString(); const WeakPointer &product = ruleNode->product; QSet parentRules; if (!result.createdNodes.isEmpty()) { foreach (BuildGraphNode *parent, ruleNode->parents) { if (RuleNode *parentRule = dynamic_cast(parent)) parentRules += parentRule; } } foreach (BuildGraphNode *node, result.createdNodes) { if (m_doDebug) m_logger.qbsDebug() << "[EXEC] rule created " << node->toString(); loggedConnect(node, ruleNode, m_logger); Artifact *outputArtifact = dynamic_cast(node); if (!outputArtifact) continue; if (outputArtifact->fileTags().matches(product->fileTags)) product->buildData->roots += outputArtifact; foreach (Artifact *inputArtifact, outputArtifact->transformer->inputs) loggedConnect(ruleNode, inputArtifact, m_logger); foreach (RuleNode *parentRule, parentRules) loggedConnect(parentRule, outputArtifact, m_logger); } updateLeaves(result.createdNodes); updateLeaves(result.invalidatedNodes); } finishNode(ruleNode); if (m_progressObserver) m_progressObserver->incrementProgressValue(); } void Executor::finishJob(ExecutorJob *job, bool success) { QBS_CHECK(job); QBS_CHECK(m_state != ExecutorIdle); const JobMap::Iterator it = m_processingJobs.find(job); QBS_CHECK(it != m_processingJobs.end()); const TransformerPtr transformer = it.value(); m_processingJobs.erase(it); m_availableJobs.append(job); if (success) { m_project->buildData->isDirty = true; foreach (Artifact *artifact, transformer->outputs) { if (artifact->alwaysUpdated) artifact->setTimestamp(FileTime::currentTime()); else artifact->setTimestamp(FileInfo(artifact->filePath()).lastModified()); } finishTransformer(transformer); } if (!success && !m_buildOptions.keepGoing()) cancelJobs(); if (m_state == ExecutorRunning && m_progressObserver && m_progressObserver->canceled()) { m_logger.qbsTrace() << "Received cancel request; canceling build."; m_explicitlyCanceled = true; cancelJobs(); } if (m_state == ExecutorCanceling) { if (m_processingJobs.isEmpty()) { m_logger.qbsTrace() << "All pending jobs are done, finishing."; finish(); } return; } if (!scheduleJobs()) { m_logger.qbsTrace() << "Nothing left to build; finishing."; finish(); } } static bool allChildrenBuilt(BuildGraphNode *node) { foreach (BuildGraphNode *child, node->children) if (child->buildState != BuildGraphNode::Built) return false; return true; } void Executor::finishNode(BuildGraphNode *leaf) { leaf->buildState = BuildGraphNode::Built; foreach (BuildGraphNode *parent, leaf->parents) { if (parent->buildState != BuildGraphNode::Buildable) { if (m_doTrace) { m_logger.qbsTrace() << "[EXEC] parent " << parent->toString() << " build state: " << toString(parent->buildState); } continue; } if (allChildrenBuilt(parent)) { m_leaves.push(parent); if (m_doTrace) { m_logger.qbsTrace() << "[EXEC] finishNode adds leaf " << parent->toString() << " " << toString(parent->buildState); } } else { if (m_doTrace) { m_logger.qbsTrace() << "[EXEC] parent " << parent->toString() << " build state: " << toString(parent->buildState); } } } } void Executor::finishArtifact(Artifact *leaf) { QBS_CHECK(leaf); if (m_doTrace) m_logger.qbsTrace() << "[EXEC] finishArtifact " << relativeArtifactFileName(leaf); finishNode(leaf); m_scanResultCache.remove(leaf->filePath()); } QString Executor::configString() const { return tr(" for configuration %1").arg(m_project->id()); } bool Executor::transformerHasMatchingOutputTags(const TransformerConstPtr &transformer) const { if (m_activeFileTags.isEmpty()) return true; // No filtering requested. foreach (Artifact * const output, transformer->outputs) { if (m_activeFileTags.matches(output->fileTags())) return true; } return false; } bool Executor::transformerHasMatchingInputFiles(const TransformerConstPtr &transformer) const { if (m_buildOptions.filesToConsider().isEmpty()) return true; // No filtering requested. foreach (const Artifact * const input, transformer->inputs) { foreach (const QString &filePath, m_buildOptions.filesToConsider()) { if (input->filePath() == filePath) return true; } } return false; } void Executor::cancelJobs() { m_logger.qbsTrace() << "Canceling all jobs."; setState(ExecutorCanceling); QList jobs = m_processingJobs.keys(); foreach (ExecutorJob *job, jobs) job->cancel(); } void Executor::setupProgressObserver() { if (!m_progressObserver) return; int totalEffort = 1; // For the effort after the last rule application; foreach (const ResolvedProductConstPtr &product, m_productsToBuild) { QBS_CHECK(product->buildData); foreach (const BuildGraphNode * const node, product->buildData->nodes) { const RuleNode * const ruleNode = dynamic_cast(node); if (ruleNode) ++totalEffort; } } m_progressObserver->initialize(tr("Building%1").arg(configString()), totalEffort); } void Executor::doSanityChecks() { QBS_CHECK(m_project); QBS_CHECK(!m_productsToBuild.isEmpty()); foreach (const ResolvedProductConstPtr &product, m_productsToBuild) { QBS_CHECK(product->buildData); QBS_CHECK(product->topLevelProject() == m_project); } } void Executor::handleError(const ErrorInfo &error) { m_error.append(error.toString()); if (m_processingJobs.isEmpty()) finish(); else cancelJobs(); } void Executor::addExecutorJobs() { m_logger.qbsDebug() << QString::fromLocal8Bit("[EXEC] preparing executor for %1 jobs " "in parallel").arg(m_buildOptions.maxJobCount()); for (int i = 1; i <= m_buildOptions.maxJobCount(); i++) { ExecutorJob *job = new ExecutorJob(m_logger, this); job->setMainThreadScriptEngine(m_evalContext->engine()); job->setObjectName(QString::fromLatin1("J%1").arg(i)); job->setDryRun(m_buildOptions.dryRun()); job->setEchoMode(m_buildOptions.echoMode()); m_availableJobs.append(job); connect(job, SIGNAL(reportCommandDescription(QString,QString)), this, SIGNAL(reportCommandDescription(QString,QString)), Qt::QueuedConnection); connect(job, SIGNAL(reportProcessResult(qbs::ProcessResult)), this, SIGNAL(reportProcessResult(qbs::ProcessResult)), Qt::QueuedConnection); connect(job, SIGNAL(finished(qbs::ErrorInfo)), this, SLOT(onJobFinished(qbs::ErrorInfo)), Qt::QueuedConnection); } } void Executor::rescueOldBuildData(Artifact *artifact, bool *childrenAdded = 0) { if (childrenAdded) *childrenAdded = false; if (!artifact->oldDataPossiblyPresent) return; artifact->oldDataPossiblyPresent = false; if (artifact->artifactType != Artifact::Generated) return; ResolvedProduct * const product = artifact->product.data(); AllRescuableArtifactData::Iterator it = product->buildData->rescuableArtifactData.find(artifact->filePath()); if (it == product->buildData->rescuableArtifactData.end()) return; const RescuableArtifactData &rad = it.value(); if (m_logger.traceEnabled()) { m_logger.qbsTrace() << QString::fromLocal8Bit("[BG] Attempting to rescue data of " "artifact '%1'").arg(artifact->fileName()); } typedef QPair ChildArtifactData; QList childrenToConnect; bool canRescue = commandListsAreEqual(artifact->transformer->commands, rad.commands); if (canRescue) { ResolvedProductPtr pseudoProduct = ResolvedProduct::create(); foreach (const RescuableArtifactData::ChildData &cd, rad.children) { pseudoProduct->name = cd.productName; pseudoProduct->profile = cd.productProfile; Artifact * const child = lookupArtifact(pseudoProduct, m_project->buildData.data(), cd.childFilePath, true); if (artifact->children.contains(child)) continue; if (!child) { // If a child has disappeared, we must re-build even if the commands // are the same. Example: Header file included in cpp file does not exist anymore. canRescue = false; if (m_logger.traceEnabled()) m_logger.qbsTrace() << "Former child artifact '" << cd.childFilePath << "' does not exist anymore"; break; } // TODO: Shouldn't addedByScanner always be true here? Otherwise the child would be // in the list already, no? childrenToConnect << qMakePair(child, cd.addedByScanner); } if (canRescue) { const int newChildCount = childrenToConnect.count() + ArtifactSet::fromNodeSet(artifact->children).count(); QBS_CHECK(newChildCount >= rad.children.count()); if (newChildCount > rad.children.count()) { canRescue = false; if (m_logger.traceEnabled()) m_logger.qbsTrace() << "Artifact has children not present in rescue data"; } } } else { if (m_logger.traceEnabled()) m_logger.qbsTrace() << "Transformer commands changed."; } if (canRescue) { artifact->setTimestamp(rad.timeStamp); if (childrenAdded && !childrenToConnect.isEmpty()) *childrenAdded = true; foreach (const ChildArtifactData &cad, childrenToConnect) { safeConnect(artifact, cad.first, m_logger); if (cad.second) artifact->childrenAddedByScanner << cad.first; } if (m_logger.traceEnabled()) m_logger.qbsTrace() << "Data was rescued."; } else { removeGeneratedArtifactFromDisk(artifact, m_logger); m_artifactsRemovedFromDisk << artifact->filePath(); if (m_logger.traceEnabled()) m_logger.qbsTrace() << "Data not rescued."; } product->buildData->rescuableArtifactData.erase(it); } bool Executor::checkForUnbuiltDependencies(Artifact *artifact) { bool buildingDependenciesFound = false; NodeSet unbuiltDependencies; foreach (BuildGraphNode *dependency, artifact->children) { switch (dependency->buildState) { case BuildGraphNode::Untouched: case BuildGraphNode::Buildable: if (m_logger.debugEnabled()) { m_logger.qbsDebug() << "[EXEC] unbuilt dependency: " << dependency->toString(); } unbuiltDependencies += dependency; break; case BuildGraphNode::Building: { if (m_logger.debugEnabled()) { m_logger.qbsDebug() << "[EXEC] dependency in state 'Building': " << dependency->toString(); } buildingDependenciesFound = true; break; } case BuildGraphNode::Built: // do nothing break; } } if (!unbuiltDependencies.isEmpty()) { artifact->inputsScanned = false; updateLeaves(unbuiltDependencies); return true; } if (buildingDependenciesFound) { artifact->inputsScanned = false; return true; } return false; } void Executor::potentiallyRunTransformer(const TransformerPtr &transformer) { foreach (Artifact * const output, transformer->outputs) { // Rescuing build data can introduce new dependencies, potentially delaying execution of // this transformer. bool childrenAddedDueToRescue; rescueOldBuildData(output, &childrenAddedDueToRescue); if (childrenAddedDueToRescue && checkForUnbuiltDependencies(output)) return; } if (!transformerHasMatchingOutputTags(transformer)) { if (m_doDebug) m_logger.qbsDebug() << "[EXEC] file tags do not match. Skipping."; finishTransformer(transformer); return; } if (!transformerHasMatchingInputFiles(transformer)) { if (m_doDebug) m_logger.qbsDebug() << "[EXEC] input files do not match. Skipping."; finishTransformer(transformer); return; } if (!mustExecuteTransformer(transformer)) { if (m_doDebug) m_logger.qbsDebug() << "[EXEC] Up to date. Skipping."; finishTransformer(transformer); return; } foreach (Artifact * const output, transformer->outputs) { // Scan all input artifacts. If new dependencies were found during scanning, delay // execution of this transformer. InputArtifactScanner scanner(output, m_inputArtifactScanContext, m_logger); scanner.scan(); if (scanner.newDependencyAdded() && checkForUnbuiltDependencies(output)) return; } runTransformer(transformer); } void Executor::runTransformer(const TransformerPtr &transformer) { QBS_CHECK(transformer); // create the output directories if (!m_buildOptions.dryRun()) { ArtifactSet::const_iterator it = transformer->outputs.begin(); for (; it != transformer->outputs.end(); ++it) { Artifact *output = *it; QDir outDir = QFileInfo(output->filePath()).absoluteDir(); if (!outDir.exists() && !outDir.mkpath(QLatin1String("."))) { throw ErrorInfo(tr("Failed to create directory '%1'.") .arg(QDir::toNativeSeparators(outDir.absolutePath()))); } } } QBS_CHECK(!m_availableJobs.isEmpty()); ExecutorJob *job = m_availableJobs.takeFirst(); foreach (Artifact * const artifact, transformer->outputs) artifact->buildState = BuildGraphNode::Building; m_processingJobs.insert(job, transformer); job->run(transformer.data()); } void Executor::finishTransformer(const TransformerPtr &transformer) { foreach (Artifact * const artifact, transformer->outputs) { possiblyInstallArtifact(artifact); finishArtifact(artifact); } } void Executor::possiblyInstallArtifact(const Artifact *artifact) { if (m_buildOptions.install() && artifact->properties->qbsPropertyValue(QLatin1String("install")).toBool()) { m_productInstaller->copyFile(artifact); } } void Executor::onJobFinished(const qbs::ErrorInfo &err) { try { ExecutorJob * const job = qobject_cast(sender()); QBS_CHECK(job); if (m_evalContext->isActive()) { m_logger.qbsDebug() << "Executor job finished while rule execution is pausing. " "Delaying slot execution."; QMetaObject::invokeMethod(job, "finished", Qt::QueuedConnection, Q_ARG(qbs::ErrorInfo, err)); return; } if (err.hasError()) { if (m_buildOptions.keepGoing()) { ErrorInfo fullWarning(err); fullWarning.prepend(Tr::tr("Ignoring the following errors on user request:")); m_logger.printWarning(fullWarning); } else { if (!m_error.hasError()) m_error = err; // All but the first one could be due to canceling. } } finishJob(job, !err.hasError()); } catch (const ErrorInfo &error) { handleError(error); } } void Executor::finish() { QBS_ASSERT(m_state != ExecutorIdle, /* ignore */); QBS_ASSERT(!m_evalContext || !m_evalContext->isActive(), /* ignore */); QList unbuiltProducts; foreach (const ResolvedProductPtr &product, m_productsToBuild) { bool productBuilt = true; foreach (BuildGraphNode *rootNode, product->buildData->roots) { if (rootNode->buildState != BuildGraphNode::Built) { productBuilt = false; unbuiltProducts += product; break; } } if (productBuilt) { // Any element still left after a successful build has not been re-created // by any rule and therefore does not exist anymore as an artifact. foreach (const QString &filePath, product->buildData->rescuableArtifactData.keys()) { removeGeneratedArtifactFromDisk(filePath, m_logger); m_artifactsRemovedFromDisk << filePath; } product->buildData->rescuableArtifactData.clear(); } } if (unbuiltProducts.isEmpty()) { m_logger.qbsInfo() << Tr::tr("Build done%1.").arg(configString()); } else { m_error.append(Tr::tr("The following products could not be built%1:").arg(configString())); foreach (const ResolvedProductConstPtr &p, unbuiltProducts) { QString errorMessage = Tr::tr("\t%1").arg(p->name); if (p->profile != m_project->profile()) errorMessage += Tr::tr(" (for profile '%1')").arg(p->profile); m_error.append(errorMessage); } } if (m_explicitlyCanceled) m_error.append(Tr::tr("Build canceled%1.").arg(configString())); setState(ExecutorIdle); if (m_progressObserver) { m_progressObserver->setFinished(); m_cancelationTimer->stop(); } EmptyDirectoriesRemover(m_project.data(), m_logger) .removeEmptyParentDirectories(m_artifactsRemovedFromDisk); emit finished(); } void Executor::checkForCancellation() { QBS_ASSERT(m_progressObserver, return); if (m_state == ExecutorRunning && m_progressObserver->canceled()) { cancelJobs(); m_evalContext->engine()->cancel(); } } bool Executor::visit(Artifact *artifact) { QBS_CHECK(artifact->buildState != BuildGraphNode::Untouched); QBS_CHECK(artifact->artifactType == Artifact::SourceFile || m_productsToBuild.contains(artifact->product)); buildArtifact(artifact); return false; } bool Executor::visit(RuleNode *ruleNode) { QBS_CHECK(ruleNode->buildState != BuildGraphNode::Untouched); QBS_CHECK(m_productsToBuild.contains(ruleNode->product)); executeRuleNode(ruleNode); return false; } /** * Sets the state of all artifacts in the graph to "untouched". * This must be done before doing a build. * * Retrieves the timestamps of source artifacts. * * This function also fills the list of changed source files. */ void Executor::prepareAllNodes() { foreach (const ResolvedProductPtr &product, m_project->allProducts()) { if (product->enabled) { QBS_CHECK(product->buildData); foreach (BuildGraphNode * const node, product->buildData->nodes) node->buildState = BuildGraphNode::Untouched; } } foreach (const ResolvedProductPtr &product, m_productsToBuild) { QBS_CHECK(product->buildData); foreach (Artifact * const artifact, ArtifactSet::fromNodeSet(product->buildData->nodes)) prepareArtifact(artifact); } } void Executor::prepareArtifact(Artifact *artifact) { artifact->inputsScanned = false; artifact->timestampRetrieved = false; if (artifact->artifactType == Artifact::SourceFile) { const FileTime oldTimestamp = artifact->timestamp(); retrieveSourceFileTimestamp(artifact); if (oldTimestamp != artifact->timestamp()) m_changedSourceArtifacts.append(artifact); possiblyInstallArtifact(artifact); } // Timestamps of file dependencies must be invalid for every build. foreach (FileDependency *fileDependency, artifact->fileDependencies) fileDependency->clearTimestamp(); } /** * Walk the build graph top-down from the roots and for each reachable node N * - mark N as buildable. */ void Executor::prepareReachableNodes() { foreach (BuildGraphNode *root, m_roots) prepareReachableNodes_impl(root); } void Executor::prepareReachableNodes_impl(BuildGraphNode *node) { if (node->buildState != BuildGraphNode::Untouched) return; node->buildState = BuildGraphNode::Buildable; foreach (BuildGraphNode *child, node->children) prepareReachableNodes_impl(child); } void Executor::prepareProducts() { ProductPrioritySetter prioritySetter(m_project.data()); prioritySetter.apply(); foreach (ResolvedProductPtr product, m_productsToBuild) product->setupBuildEnvironment(m_evalContext->engine(), m_project->environment); } void Executor::setupRootNodes() { m_roots.clear(); foreach (const ResolvedProductPtr &product, m_productsToBuild) { foreach (BuildGraphNode *root, product->buildData->roots) m_roots += root; } } void Executor::setState(ExecutorState s) { if (m_state == s) return; m_state = s; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/executor.h000066400000000000000000000135021266132464200222060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_BUILDGRAPHEXECUTOR_H #define QBS_BUILDGRAPHEXECUTOR_H #include "forward_decls.h" #include "buildgraphvisitor.h" #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QTimer; QT_END_NAMESPACE namespace qbs { class ProcessResult; namespace Internal { class ExecutorJob; class FileTime; class InputArtifactScannerContext; class ProductInstaller; class ProgressObserver; class RuleNode; class Executor : public QObject, private BuildGraphVisitor { Q_OBJECT public slots: void build(); public: Executor(const Logger &logger, QObject *parent = 0); ~Executor(); void setProject(const TopLevelProjectPtr &project); void setProducts(const QList &productsToBuild); void setBuildOptions(const BuildOptions &buildOptions); void setProgressObserver(ProgressObserver *observer) { m_progressObserver = observer; } ErrorInfo error() const { return m_error; } signals: void reportCommandDescription(const QString &highlight, const QString &message); void reportProcessResult(const qbs::ProcessResult &result); void finished(); private slots: void onJobFinished(const qbs::ErrorInfo &err); void finish(); void checkForCancellation(); private: // BuildGraphVisitor implementation bool visit(Artifact *artifact); bool visit(RuleNode *ruleNode); enum ExecutorState { ExecutorIdle, ExecutorRunning, ExecutorCanceling }; struct ComparePriority { bool operator() (const BuildGraphNode *x, const BuildGraphNode *y) const; }; typedef std::priority_queue, ComparePriority> Leaves; void doBuild(); void prepareAllNodes(); void prepareArtifact(Artifact *artifact); void prepareReachableNodes(); void prepareReachableNodes_impl(BuildGraphNode *node); void prepareProducts(); void setupRootNodes(); void initLeaves(); void updateLeaves(const NodeSet &nodes); void updateLeaves(BuildGraphNode *node, NodeSet &seenNodes); bool scheduleJobs(); void buildArtifact(Artifact *artifact); void executeRuleNode(RuleNode *ruleNode); void finishJob(ExecutorJob *job, bool success); void finishNode(BuildGraphNode *leaf); void finishArtifact(Artifact *artifact); void setState(ExecutorState); void addExecutorJobs(); void cancelJobs(); void setupProgressObserver(); void doSanityChecks(); void handleError(const ErrorInfo &error); void rescueOldBuildData(Artifact *artifact, bool *childrenAdded); bool checkForUnbuiltDependencies(Artifact *artifact); void potentiallyRunTransformer(const TransformerPtr &transformer); void runTransformer(const TransformerPtr &transformer); void finishTransformer(const TransformerPtr &transformer); void possiblyInstallArtifact(const Artifact *artifact); bool mustExecuteTransformer(const TransformerPtr &transformer) const; bool isUpToDate(Artifact *artifact) const; void retrieveSourceFileTimestamp(Artifact *artifact) const; FileTime recursiveFileTime(const QString &filePath) const; QString configString() const; bool transformerHasMatchingOutputTags(const TransformerConstPtr &transformer) const; bool transformerHasMatchingInputFiles(const TransformerConstPtr &transformer) const; typedef QHash JobMap; JobMap m_processingJobs; ProductInstaller *m_productInstaller; RulesEvaluationContextPtr m_evalContext; BuildOptions m_buildOptions; Logger m_logger; ProgressObserver *m_progressObserver; QList m_availableJobs; ExecutorState m_state; TopLevelProjectPtr m_project; QList m_productsToBuild; NodeSet m_roots; Leaves m_leaves; QList m_changedSourceArtifacts; ScanResultCache m_scanResultCache; InputArtifactScannerContext *m_inputArtifactScanContext; ErrorInfo m_error; bool m_explicitlyCanceled; FileTags m_activeFileTags; QTimer * const m_cancelationTimer; QStringList m_artifactsRemovedFromDisk; const bool m_doTrace; const bool m_doDebug; }; } // namespace Internal } // namespace qbs #endif // QBS_BUILDGRAPHEXECUTOR_H qbs-src-1.4.5/src/lib/corelib/buildgraph/executorjob.cpp000066400000000000000000000123161266132464200232360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "executorjob.h" #include "artifact.h" #include "command.h" #include "jscommandexecutor.h" #include "processcommandexecutor.h" #include "transformer.h" #include #include #include #include namespace qbs { namespace Internal { ExecutorJob::ExecutorJob(const Logger &logger, QObject *parent) : QObject(parent) , m_processCommandExecutor(new ProcessCommandExecutor(logger, this)) , m_jsCommandExecutor(new JsCommandExecutor(logger, this)) { connect(m_processCommandExecutor, SIGNAL(reportCommandDescription(QString,QString)), this, SIGNAL(reportCommandDescription(QString,QString))); connect(m_processCommandExecutor, SIGNAL(reportProcessResult(qbs::ProcessResult)), this, SIGNAL(reportProcessResult(qbs::ProcessResult))); connect(m_processCommandExecutor, SIGNAL(finished(qbs::ErrorInfo)), this, SLOT(onCommandFinished(qbs::ErrorInfo))); connect(m_jsCommandExecutor, SIGNAL(reportCommandDescription(QString,QString)), this, SIGNAL(reportCommandDescription(QString,QString))); connect(m_jsCommandExecutor, SIGNAL(finished(qbs::ErrorInfo)), this, SLOT(onCommandFinished(qbs::ErrorInfo))); reset(); } ExecutorJob::~ExecutorJob() { } void ExecutorJob::setMainThreadScriptEngine(ScriptEngine *engine) { m_processCommandExecutor->setMainThreadScriptEngine(engine); m_jsCommandExecutor->setMainThreadScriptEngine(engine); } void ExecutorJob::setDryRun(bool enabled) { m_processCommandExecutor->setDryRunEnabled(enabled); m_jsCommandExecutor->setDryRunEnabled(enabled); } void ExecutorJob::setEchoMode(CommandEchoMode echoMode) { m_processCommandExecutor->setEchoMode(echoMode); m_jsCommandExecutor->setEchoMode(echoMode); } void ExecutorJob::run(Transformer *t) { QBS_ASSERT(m_currentCommandIdx == -1, return); if (t->commands.isEmpty()) { setFinished(); return; } t->propertiesRequestedInCommands.clear(); QBS_CHECK(!t->outputs.isEmpty()); m_processCommandExecutor->setProcessEnvironment( (*t->outputs.begin())->product->buildEnvironment); m_transformer = t; runNextCommand(); } void ExecutorJob::cancel() { if (!m_currentCommandExecutor) return; m_error = ErrorInfo(tr("Transformer execution canceled.")); m_currentCommandExecutor->cancel(); } void ExecutorJob::runNextCommand() { QBS_ASSERT(m_currentCommandIdx <= m_transformer->commands.count(), return); ++m_currentCommandIdx; if (m_currentCommandIdx >= m_transformer->commands.count()) { setFinished(); return; } const AbstractCommandPtr &command = m_transformer->commands.at(m_currentCommandIdx); switch (command->type()) { case AbstractCommand::ProcessCommandType: m_currentCommandExecutor = m_processCommandExecutor; break; case AbstractCommand::JavaScriptCommandType: m_currentCommandExecutor = m_jsCommandExecutor; break; default: qFatal("Missing implementation for command type %d", command->type()); } m_currentCommandExecutor->start(m_transformer, command.data()); } void ExecutorJob::onCommandFinished(const ErrorInfo &err) { QBS_ASSERT(m_transformer, return); if (m_error.hasError()) { // Canceled? setFinished(); } else if (err.hasError()) { m_error = err; setFinished(); } else { runNextCommand(); } } void ExecutorJob::setFinished() { const ErrorInfo err = m_error; reset(); emit finished(err); } void ExecutorJob::reset() { m_transformer = 0; m_currentCommandExecutor = 0; m_currentCommandIdx = -1; m_error.clear(); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/executorjob.h000066400000000000000000000056521266132464200227100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_EXECUTORJOB_H #define QBS_EXECUTORJOB_H #include #include #include #include namespace qbs { class CodeLocation; class ProcessResult; namespace Internal { class AbstractCommandExecutor; class ProductBuildData; class JsCommandExecutor; class Logger; class ProcessCommandExecutor; class ScriptEngine; class Transformer; class ExecutorJob : public QObject { Q_OBJECT public: ExecutorJob(const Logger &logger, QObject *parent); ~ExecutorJob(); void setMainThreadScriptEngine(ScriptEngine *engine); void setDryRun(bool enabled); void setEchoMode(CommandEchoMode echoMode); void run(Transformer *t); void cancel(); signals: void reportCommandDescription(const QString &highlight, const QString &message); void reportProcessResult(const qbs::ProcessResult &result); void finished(const qbs::ErrorInfo &error = ErrorInfo()); // !hasError() <=> command successful private slots: void runNextCommand(); void onCommandFinished(const qbs::ErrorInfo &err); private: void setFinished(); void reset(); AbstractCommandExecutor *m_currentCommandExecutor; ProcessCommandExecutor *m_processCommandExecutor; JsCommandExecutor *m_jsCommandExecutor; Transformer *m_transformer; int m_currentCommandIdx; ErrorInfo m_error; }; } // namespace Internal } // namespace qbs #endif // QBS_EXECUTORJOB_H qbs-src-1.4.5/src/lib/corelib/buildgraph/filedependency.cpp000066400000000000000000000047731266132464200236730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "filedependency.h" #include #include namespace qbs { namespace Internal { FileResourceBase::FileResourceBase() { } FileResourceBase::~FileResourceBase() { } void FileResourceBase::setTimestamp(const FileTime &t) { m_timestamp = t; } const FileTime &FileResourceBase::timestamp() const { return m_timestamp; } void FileResourceBase::setFilePath(const QString &filePath) { m_filePath = filePath; FileInfo::splitIntoDirectoryAndFileName(m_filePath, &m_dirPath, &m_fileName); } const QString &FileResourceBase::filePath() const { return m_filePath; } void FileResourceBase::load(PersistentPool &pool) { setFilePath(pool.idLoadString()); pool.stream() >> m_timestamp; } void FileResourceBase::store(PersistentPool &pool) const { pool.storeString(m_filePath); pool.stream() << m_timestamp; } FileDependency::FileDependency() { } FileDependency::~FileDependency() { } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/filedependency.h000066400000000000000000000047651266132464200233410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_FILEDEPENDENCY_H #define QBS_FILEDEPENDENCY_H #include #include namespace qbs { namespace Internal { class FileResourceBase : public virtual PersistentObject { protected: FileResourceBase(); public: ~FileResourceBase(); void setTimestamp(const FileTime &t); const FileTime ×tamp() const; void clearTimestamp() { m_timestamp.clear(); } void setFilePath(const QString &filePath); const QString &filePath() const; QString dirPath() const { return m_dirPath.toString(); } QString fileName() const { return m_fileName.toString(); } protected: void load(PersistentPool &pool); void store(PersistentPool &pool) const; private: FileTime m_timestamp; QString m_filePath; QStringRef m_dirPath; QStringRef m_fileName; }; class FileDependency : public FileResourceBase { public: FileDependency(); ~FileDependency(); }; } // namespace Internal } // namespace qbs #endif // QBS_FILEDEPENDENCY_H qbs-src-1.4.5/src/lib/corelib/buildgraph/forward_decls.h000066400000000000000000000044401266132464200231670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_BG_FORWARD_DECLS_H #define QBS_BG_FORWARD_DECLS_H #include namespace qbs { namespace Internal { class Artifact; class ArtifactSet; class ProjectBuildData; class ProductBuildData; class Node; class NodeSet; class Transformer; typedef QSharedPointer TransformerPtr; typedef QSharedPointer TransformerConstPtr; class RulesEvaluationContext; typedef QSharedPointer RulesEvaluationContextPtr; class AbstractCommand; typedef QSharedPointer AbstractCommandPtr; class ProcessCommand; typedef QSharedPointer ProcessCommandPtr; class JavaScriptCommand; typedef QSharedPointer JavaScriptCommandPtr; } // namespace Internal } // namespace qbs #endif // QBS_BG_FORWARD_DECLS_H qbs-src-1.4.5/src/lib/corelib/buildgraph/inputartifactscanner.cpp000066400000000000000000000373311266132464200251400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "inputartifactscanner.h" #include "artifact.h" #include "buildgraph.h" #include "productbuilddata.h" #include "projectbuilddata.h" #include "transformer.h" #include "depscanner.h" #include "rulesevaluationcontext.h" #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { InputArtifactScannerContext::InputArtifactScannerContext(ScanResultCache *scanResultCache) : scanResultCache(scanResultCache) { } InputArtifactScannerContext::~InputArtifactScannerContext() { } static void resolveWithIncludePath(const QString &includePath, const ScanResultCache::Dependency &dependency, const ResolvedProduct *product, ResolvedDependency *result) { QString absDirPath = dependency.dirPath().isEmpty() ? includePath : FileInfo::resolvePath(includePath, dependency.dirPath()); if (!dependency.isClean()) absDirPath = QDir::cleanPath(absDirPath); ResolvedProject *project = product->project.data(); FileDependency *fileDependencyArtifact = 0; Artifact *dependencyInProduct = 0; Artifact *dependencyInOtherProduct = 0; foreach (FileResourceBase *lookupResult, project->topLevelProject() ->buildData->lookupFiles(absDirPath, dependency.fileName())) { if ((fileDependencyArtifact = dynamic_cast(lookupResult))) continue; Artifact * const foundArtifact = dynamic_cast(lookupResult); if (foundArtifact->product == product) dependencyInProduct = foundArtifact; else dependencyInOtherProduct = foundArtifact; } // prioritize found artifacts if ((result->file = dependencyInProduct) || (result->file = dependencyInOtherProduct) || (result->file = fileDependencyArtifact)) { result->filePath = result->file->filePath(); return; } QString absFilePath = absDirPath + QLatin1Char('/') + dependency.fileName(); if (FileInfo::exists(absFilePath)) result->filePath = absFilePath; } static void resolveAbsolutePath(const ScanResultCache::Dependency &dependency, const ResolvedProduct *product, ResolvedDependency *result) { QString absDirPath = dependency.dirPath(); if (!dependency.isClean()) absDirPath = QDir::cleanPath(absDirPath); ResolvedProject *project = product->project.data(); FileDependency *fileDependencyArtifact = 0; Artifact *dependencyInProduct = 0; Artifact *dependencyInOtherProduct = 0; foreach (FileResourceBase *lookupResult, project->topLevelProject() ->buildData->lookupFiles(absDirPath, dependency.fileName())) { if ((fileDependencyArtifact = dynamic_cast(lookupResult))) continue; Artifact * const foundArtifact = dynamic_cast(lookupResult); if (foundArtifact->product == product) dependencyInProduct = foundArtifact; else dependencyInOtherProduct = foundArtifact; } // prioritize found artifacts if ((result->file = dependencyInProduct) || (result->file = dependencyInOtherProduct) || (result->file = fileDependencyArtifact)) { result->filePath = result->file->filePath(); return; } if (FileInfo::exists(dependency.filePath())) result->filePath = dependency.filePath(); } static void scanWithScannerPlugin(DependencyScanner *scanner, FileResourceBase *fileToBeScanned, ScanResultCache::Result *scanResult) { QStringList dependencies = scanner->collectDependencies(fileToBeScanned); foreach (const QString &s, dependencies) scanResult->deps += ScanResultCache::Dependency(s); scanResult->valid = true; } InputArtifactScanner::InputArtifactScanner(Artifact *artifact, InputArtifactScannerContext *ctx, const Logger &logger) : m_artifact(artifact), m_context(ctx), m_newDependencyAdded(false), m_logger(logger) { } void InputArtifactScanner::scan() { if (m_artifact->inputsScanned) return; if (m_logger.traceEnabled()) { m_logger.qbsTrace() << QString::fromLocal8Bit("[DEPSCAN] inputs for %1 [%2] in product '%3'") .arg(m_artifact->filePath(), m_artifact->fileTags().toStringList().join(QLatin1String(", ")), m_artifact->product->name); } m_artifact->inputsScanned = true; // clear file dependencies; they will be regenerated m_artifact->fileDependencies.clear(); // Remove all connections to children that were added by the dependency scanner. // They will be regenerated. foreach (Artifact *dependency, m_artifact->childrenAddedByScanner) disconnect(m_artifact, dependency, m_logger); ArtifactSet::const_iterator it = m_artifact->transformer->inputs.begin(); for (; it != m_artifact->transformer->inputs.end(); ++it) { Artifact *inputArtifact = *it; scanForFileDependencies(inputArtifact); } } void InputArtifactScanner::scanForFileDependencies(Artifact *inputArtifact) { if (m_logger.traceEnabled()) { m_logger.qbsTrace() << QString::fromLocal8Bit("[DEPSCAN] input artifact %1 [%2]") .arg(inputArtifact->filePath(), inputArtifact->fileTags().toStringList().join(QLatin1String(", "))); } InputArtifactScannerContext::CacheItem &cacheItem = m_context->cache[inputArtifact->properties]; QSet visitedFilePaths; QList filesToScan; filesToScan.append(inputArtifact); const QSet scanners = scannersForArtifact(inputArtifact); while (!filesToScan.isEmpty()) { FileResourceBase *fileToBeScanned = filesToScan.takeFirst(); const QString &filePathToBeScanned = fileToBeScanned->filePath(); if (visitedFilePaths.contains(filePathToBeScanned)) continue; visitedFilePaths.insert(filePathToBeScanned); foreach (DependencyScanner *scanner, scanners) { scanForScannerFileDependencies(scanner, inputArtifact, fileToBeScanned, scanner->recursive() ? &filesToScan : 0, cacheItem[scanner->key()]); } } } QSet InputArtifactScanner::scannersForArtifact(const Artifact *artifact) const { QSet scanners; ResolvedProduct *product = artifact->product.data(); QHash &scannerCache = m_context->scannersCache[product]; foreach (const FileTag &fileTag, artifact->fileTags()) { InputArtifactScannerContext::DependencyScannerCacheItem &cache = scannerCache[fileTag]; if (!cache.valid) { cache.valid = true; foreach (ScannerPlugin *scanner, ScannerPluginManager::scannersForFileTag(fileTag)) { PluginDependencyScanner *pluginScanner = new PluginDependencyScanner(scanner); cache.scanners += DependencyScannerPtr(pluginScanner); } foreach (const ResolvedScannerConstPtr &scanner, product->scanners) { if (scanner->inputs.contains(fileTag)) { cache.scanners += DependencyScannerPtr( new UserDependencyScanner(scanner, m_logger)); break; } } } foreach (const DependencyScannerPtr &scanner, cache.scanners) { scanners += scanner.data(); } } return scanners; } void InputArtifactScanner::scanForScannerFileDependencies(DependencyScanner *scanner, Artifact *inputArtifact, FileResourceBase *fileToBeScanned, QList *filesToScan, InputArtifactScannerContext::ScannerResolvedDependenciesCache &cache) { if (m_logger.traceEnabled()) { m_logger.qbsTrace() << QString::fromLocal8Bit("[DEPSCAN] file %1") .arg(fileToBeScanned->filePath()); } const bool cacheHit = cache.valid; if (!cacheHit) { cache.valid = true; cache.searchPaths = scanner->collectSearchPaths(inputArtifact); } if (m_logger.traceEnabled()) { m_logger.qbsTrace() << "[DEPSCAN] include paths (cache " << (cacheHit ? "hit)" : "miss)"); foreach (const QString &s, cache.searchPaths) m_logger.qbsTrace() << " " << s; } const QString &filePathToBeScanned = fileToBeScanned->filePath(); ScanResultCache::Result scanResult = m_context->scanResultCache->value(scanner->key(), filePathToBeScanned); if (!scanResult.valid) { try { scanWithScannerPlugin(scanner, fileToBeScanned, &scanResult); } catch (const ErrorInfo &error) { m_logger.printWarning(error); return; } m_context->scanResultCache->insert(scanner->key(), filePathToBeScanned, scanResult); } resolveScanResultDependencies(inputArtifact, scanResult, filesToScan, cache); } void InputArtifactScanner::resolveScanResultDependencies(const Artifact *inputArtifact, const ScanResultCache::Result &scanResult, QList *artifactsToScan, InputArtifactScannerContext::ScannerResolvedDependenciesCache &cache) { foreach (const ScanResultCache::Dependency &dependency, scanResult.deps) { const QString &dependencyFilePath = dependency.filePath(); InputArtifactScannerContext::ResolvedDependencyCacheItem &cachedResolvedDependencyItem = cache.resolvedDependenciesCache[dependency.dirPath()][dependency.fileName()]; ResolvedDependency &resolvedDependency = cachedResolvedDependencyItem.resolvedDependency; if (cachedResolvedDependencyItem.valid) { if (resolvedDependency.filePath.isEmpty()) goto unresolved; goto resolved; } cachedResolvedDependencyItem.valid = true; if (FileInfo::isAbsolute(dependencyFilePath)) { resolveAbsolutePath(dependency, inputArtifact->product.data(), &resolvedDependency); goto resolved; } // try include paths foreach (const QString &includePath, cache.searchPaths) { resolveWithIncludePath(includePath, dependency, inputArtifact->product.data(), &resolvedDependency); if (resolvedDependency.isValid()) goto resolved; } unresolved: if (m_logger.traceEnabled()) m_logger.qbsWarning() << "[DEPSCAN] unresolved dependency " << dependencyFilePath; continue; resolved: handleDependency(resolvedDependency); if (artifactsToScan && resolvedDependency.file) { if (Artifact *artifactDependency = dynamic_cast(resolvedDependency.file)) { // Do not scan artifacts that are being built. Otherwise we might read an incomplete // file or conflict with the writing process. if (artifactDependency->buildState != BuildGraphNode::Building) artifactsToScan->append(artifactDependency); } else { // Add file dependency to the next round of scanning. artifactsToScan->append(resolvedDependency.file); } } } } void InputArtifactScanner::handleDependency(ResolvedDependency &dependency) { const ResolvedProductPtr product = m_artifact->product; bool insertIntoProduct = true; QBS_CHECK(m_artifact->artifactType == Artifact::Generated); QBS_CHECK(product); Artifact *artifactDependency = dynamic_cast(dependency.file); FileDependency *fileDependency = artifactDependency ? 0 : dynamic_cast(dependency.file); QBS_CHECK(!dependency.file || artifactDependency || fileDependency); if (!dependency.file) { // The dependency is an existing file but does not exist in the build graph. if (m_logger.traceEnabled()) m_logger.qbsTrace() << "[DEPSCAN] add new file dependency " << dependency.filePath; fileDependency = new FileDependency(); dependency.file = fileDependency; fileDependency->setFilePath(dependency.filePath); product->topLevelProject()->buildData->insertFileDependency(fileDependency); } else if (fileDependency) { // The dependency exists in the project's list of file dependencies. if (m_logger.traceEnabled()) { m_logger.qbsTrace() << "[DEPSCAN] add existing file dependency " << dependency.filePath; } } else if (artifactDependency->product == product) { // The dependency is in our product. if (m_logger.traceEnabled()) { m_logger.qbsTrace() << "[DEPSCAN] add artifact dependency " << dependency.filePath << " (from this product)"; } insertIntoProduct = false; } else { // The dependency is in some other product. ResolvedProduct * const otherProduct = artifactDependency->product; if (m_logger.traceEnabled()) { m_logger.qbsTrace() << "[DEPSCAN] add artifact dependency " << dependency.filePath << " (from product " << otherProduct->uniqueName() << ')'; } insertIntoProduct = false; } if (m_artifact == dependency.file) return; if (fileDependency) { m_artifact->fileDependencies.insert(fileDependency); } else { if (m_artifact->children.contains(artifactDependency)) return; if (insertIntoProduct && !product->buildData->nodes.contains(artifactDependency)) insertArtifact(product, artifactDependency, m_logger); safeConnect(m_artifact, artifactDependency, m_logger); m_artifact->childrenAddedByScanner += artifactDependency; m_newDependencyAdded = true; } } InputArtifactScannerContext::DependencyScannerCacheItem::DependencyScannerCacheItem() : valid(false) { } InputArtifactScannerContext::DependencyScannerCacheItem::~DependencyScannerCacheItem() { } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/inputartifactscanner.h000066400000000000000000000107171266132464200246040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_INPUTARTIFACTSCANNER_H #define QBS_INPUTARTIFACTSCANNER_H #include "scanresultcache.h" #include #include #include #include class ScannerPlugin; namespace qbs { namespace Internal { class Artifact; class FileResourceBase; class PropertyMapInternal; class DependencyScanner; typedef QSharedPointer DependencyScannerPtr; class ResolvedDependency { public: ResolvedDependency() : file(0) {} bool isValid() const { return !filePath.isNull(); } QString filePath; FileResourceBase *file; }; class InputArtifactScannerContext { public: InputArtifactScannerContext(ScanResultCache *scanResultCache); ~InputArtifactScannerContext(); private: ScanResultCache *scanResultCache; struct ResolvedDependencyCacheItem { ResolvedDependencyCacheItem() : valid(false) {} bool valid; ResolvedDependency resolvedDependency; }; typedef QHash > ResolvedDependenciesCache; struct ScannerResolvedDependenciesCache { ScannerResolvedDependenciesCache() : valid(false) {} bool valid; QStringList searchPaths; ResolvedDependenciesCache resolvedDependenciesCache; }; struct DependencyScannerCacheItem { DependencyScannerCacheItem(); ~DependencyScannerCacheItem(); bool valid; QList scanners; }; typedef QHash CacheItem; QHash cache; QHash > scannersCache; friend class InputArtifactScanner; }; class InputArtifactScanner { public: InputArtifactScanner(Artifact *artifact, InputArtifactScannerContext *ctx, const Logger &logger); void scan(); bool newDependencyAdded() const { return m_newDependencyAdded; } private: void scanForFileDependencies(Artifact *inputArtifact); QSet scannersForArtifact(const Artifact *artifact) const; void scanForScannerFileDependencies(DependencyScanner *scanner, Artifact *inputArtifact, FileResourceBase *fileToBeScanned, QList *filesToScan, InputArtifactScannerContext::ScannerResolvedDependenciesCache &cache); void resolveScanResultDependencies(const Artifact *inputArtifact, const ScanResultCache::Result &scanResult, QList *artifactsToScan, InputArtifactScannerContext::ScannerResolvedDependenciesCache &cache); void handleDependency(ResolvedDependency &dependency); Artifact * const m_artifact; InputArtifactScannerContext *const m_context; bool m_newDependencyAdded; Logger m_logger; }; } // namespace Internal } // namespace qbs #endif // QBS_INPUTARTIFACTSCANNER_H qbs-src-1.4.5/src/lib/corelib/buildgraph/jscommandexecutor.cpp000066400000000000000000000154061266132464200244420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "jscommandexecutor.h" #include "artifact.h" #include "buildgraph.h" #include "command.h" #include "transformer.h" #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { struct JavaScriptCommandResult { bool success; QString errorMessage; CodeLocation errorLocation; }; class JsCommandExecutorThreadObject : public QObject { Q_OBJECT public: JsCommandExecutorThreadObject(const Logger &logger) : m_logger(logger) , m_scriptEngine(0) { } const JavaScriptCommandResult &result() const { return m_result; } Q_INVOKABLE void cancel() { QBS_ASSERT(m_scriptEngine, return); m_scriptEngine->abortEvaluation(); } signals: void finished(); public slots: void start(const JavaScriptCommand *cmd, Transformer *transformer) { try { doStart(cmd, transformer); } catch (const qbs::ErrorInfo &error) { setError(error.toString(), cmd->codeLocation()); } emit finished(); } private: void doStart(const JavaScriptCommand *cmd, Transformer *transformer) { m_result.success = true; m_result.errorMessage.clear(); ScriptEngine * const scriptEngine = provideScriptEngine(); QScriptValue scope = scriptEngine->newObject(); PrepareScriptObserver observer(scriptEngine); setupScriptEngineForFile(scriptEngine, transformer->rule->prepareScript->fileContext, scope); setupScriptEngineForProduct(scriptEngine, transformer->product(), transformer->rule->module, scope, &observer); transformer->setupInputs(scope); transformer->setupOutputs(scriptEngine, scope); for (QVariantMap::const_iterator it = cmd->properties().constBegin(); it != cmd->properties().constEnd(); ++it) { scope.setProperty(it.key(), scriptEngine->toScriptValue(it.value())); } QScriptContext *ctx = scriptEngine->currentContext(); ctx->pushScope(scope); scriptEngine->evaluate(cmd->sourceCode()); ctx->popScope(); transformer->propertiesRequestedInCommands += scriptEngine->propertiesRequestedInScript(); scriptEngine->clearRequestedProperties(); if (scriptEngine->hasUncaughtException()) { // ### We don't know the line number of the command's sourceCode property assignment. setError(scriptEngine->uncaughtException().toString(), cmd->codeLocation()); } } void setError(const QString &errorMessage, const CodeLocation &codeLocation) { m_result.success = false; m_result.errorMessage = errorMessage; m_result.errorLocation = codeLocation; } ScriptEngine *provideScriptEngine() { if (!m_scriptEngine) m_scriptEngine = new ScriptEngine(m_logger, this); return m_scriptEngine; } Logger m_logger; ScriptEngine *m_scriptEngine; JavaScriptCommandResult m_result; }; JsCommandExecutor::JsCommandExecutor(const Logger &logger, QObject *parent) : AbstractCommandExecutor(logger, parent) , m_thread(new QThread(this)) , m_objectInThread(new JsCommandExecutorThreadObject(logger)) , m_running(false) { m_objectInThread->moveToThread(m_thread); connect(m_objectInThread, SIGNAL(finished()), this, SLOT(onJavaScriptCommandFinished())); connect(this, SIGNAL(startRequested(const JavaScriptCommand*,Transformer*)), m_objectInThread, SLOT(start(const JavaScriptCommand*,Transformer*))); } JsCommandExecutor::~JsCommandExecutor() { waitForFinished(); delete m_objectInThread; m_thread->quit(); m_thread->wait(); } void JsCommandExecutor::waitForFinished() { if (!m_running) return; QEventLoop loop; loop.connect(m_objectInThread, SIGNAL(finished()), SLOT(quit())); loop.exec(); } void JsCommandExecutor::doStart() { QBS_ASSERT(!m_running, return); m_thread->start(); if (dryRun()) { QTimer::singleShot(0, this, SIGNAL(finished())); // Don't call back on the caller. return; } m_running = true; emit startRequested(jsCommand(), transformer()); } void JsCommandExecutor::cancel() { if (!dryRun()) QMetaObject::invokeMethod(m_objectInThread, "cancel", Qt::QueuedConnection); } void JsCommandExecutor::onJavaScriptCommandFinished() { m_running = false; const JavaScriptCommandResult &result = m_objectInThread->result(); ErrorInfo err; if (!result.success) { logger().qbsDebug() << "JS context:\n" << jsCommand()->properties(); logger().qbsDebug() << "JS code:\n" << jsCommand()->sourceCode(); err.append(tr("Error while executing JavaScriptCommand:"), result.errorLocation); err.append(result.errorMessage); } emit finished(err); } const JavaScriptCommand *JsCommandExecutor::jsCommand() const { return static_cast(command()); } } // namespace Internal } // namespace qbs #include "jscommandexecutor.moc" qbs-src-1.4.5/src/lib/corelib/buildgraph/jscommandexecutor.h000066400000000000000000000045441266132464200241100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_JSCOMMANDEXECUTOR_H #define QBS_JSCOMMANDEXECUTOR_H #include "abstractcommandexecutor.h" #include namespace qbs { class CodeLocation; namespace Internal { class JavaScriptCommand; class JsCommandExecutorThreadObject; class JsCommandExecutor : public AbstractCommandExecutor { Q_OBJECT public: explicit JsCommandExecutor(const Logger &logger, QObject *parent = 0); ~JsCommandExecutor(); signals: void startRequested(const JavaScriptCommand *cmd, Transformer *transformer); private slots: void onJavaScriptCommandFinished(); private: void doStart(); void cancel(); void waitForFinished(); const JavaScriptCommand *jsCommand() const; QThread *m_thread; JsCommandExecutorThreadObject *m_objectInThread; bool m_running; }; } // namespace Internal } // namespace qbs #endif // QBS_JSCOMMANDEXECUTOR_H qbs-src-1.4.5/src/lib/corelib/buildgraph/nodeset.cpp000066400000000000000000000053561266132464200223540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "nodeset.h" #include "artifact.h" #include "rulenode.h" #include // because of RulePtr #include #include namespace qbs { namespace Internal { NodeSet::NodeSet() : d(new NodeSetData) { } NodeSet &NodeSet::unite(const NodeSet &other) { d->m_data.insert(other.begin(), other.end()); return *this; } void NodeSet::remove(BuildGraphNode *node) { d->m_data.erase(node); } void NodeSet::load(PersistentPool &pool) { clear(); int i; pool.stream() >> i; for (; --i >= 0;) { int t; pool.stream() >> t; BuildGraphNode *node = 0; switch (static_cast(t)) { case BuildGraphNode::ArtifactNodeType: node = pool.idLoad(); break; case BuildGraphNode::RuleNodeType: node = pool.idLoad(); break; } QBS_CHECK(node); insert(node); } } void NodeSet::store(PersistentPool &pool) const { pool.stream() << count(); for (NodeSet::const_iterator it = constBegin(); it != constEnd(); ++it) { pool.stream() << int((*it)->type()); pool.store(*it); } } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/nodeset.h000066400000000000000000000067741266132464200220260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_NODESET_H #define QBS_NODESET_H #include #include #include namespace qbs { namespace Internal { class BuildGraphNode; class NodeSetData : public QSharedData { public: std::set m_data; }; class PersistentPool; /** * Set of build graph nodes. * This is faster than QSet when iterating over the container. */ class NodeSet { public: NodeSet(); NodeSet &unite(const NodeSet &other); typedef std::set::const_iterator const_iterator; typedef std::set::iterator iterator; typedef BuildGraphNode * value_type; iterator begin() { return d->m_data.begin(); } iterator end() { return d->m_data.end(); } const_iterator begin() const { return d->m_data.begin(); } const_iterator end() const { return d->m_data.end(); } const_iterator constBegin() const { return d->m_data.begin(); } const_iterator constEnd() const { return d->m_data.end(); } void insert(BuildGraphNode *node) { d->m_data.insert(node); } void operator+=(BuildGraphNode *node) { d->m_data.insert(node); } NodeSet &operator<<(BuildGraphNode *node) { d->m_data.insert(node); return *this; } void remove(BuildGraphNode *node); bool contains(BuildGraphNode *node) const { return d->m_data.find(node) != d->m_data.end(); } void clear() { d->m_data.clear(); } bool isEmpty() const { return d->m_data.empty(); } int count() const { return (int)d->m_data.size(); } void reserve(int) { // no-op } bool operator==(const NodeSet &other) const { return d->m_data == other.d->m_data; } bool operator!=(const NodeSet &other) const { return !(*this == other); } void load(PersistentPool &pool); void store(PersistentPool &pool) const; private: QSharedDataPointer d; }; } // namespace Internal } // namespace qbs #endif // QBS_NODESET_H qbs-src-1.4.5/src/lib/corelib/buildgraph/nodetreedumper.cpp000066400000000000000000000064031266132464200237270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "nodetreedumper.h" #include "artifact.h" #include "productbuilddata.h" #include "rulenode.h" #include #include #include namespace qbs { namespace Internal { static unsigned int indentWidth() { return 4; } NodeTreeDumper::NodeTreeDumper(QIODevice &outDevice) : m_outDevice(outDevice) { } void NodeTreeDumper::start(const QList &products) { m_indentation = 0; foreach (const ResolvedProductPtr &p, products) { if (!p->buildData) continue; m_currentProduct = p; foreach (Artifact * const root, p->buildData->rootArtifacts()) root->accept(this); m_visited.clear(); QBS_CHECK(m_indentation == 0); } } bool NodeTreeDumper::visit(Artifact *artifact) { m_outDevice.write(indentation()); m_outDevice.write(artifact->fileName().toLocal8Bit()); indent(); const bool wasVisited = m_visited.contains(artifact); m_visited.insert(artifact); return !wasVisited && artifact->product == m_currentProduct; } void NodeTreeDumper::endVisit(Artifact *artifact) { Q_UNUSED(artifact); doEndVisit(); } bool NodeTreeDumper::visit(RuleNode *rule) { m_outDevice.write(indentation()); m_outDevice.write(rule->toString().toLocal8Bit()); indent(); return true; } void NodeTreeDumper::endVisit(RuleNode *rule) { Q_UNUSED(rule); doEndVisit(); } void NodeTreeDumper::doEndVisit() { unindent(); } void NodeTreeDumper::indent() { m_outDevice.write("\n"); m_indentation += indentWidth(); } void NodeTreeDumper::unindent() { m_indentation -= indentWidth(); } QByteArray NodeTreeDumper::indentation() const { return QByteArray(m_indentation, ' '); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/nodetreedumper.h000066400000000000000000000046411266132464200233760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_NODETREEDUMPER_H #define QBS_NODETREEDUMPER_H #include "artifactset.h" #include "buildgraphvisitor.h" #include #include QT_BEGIN_NAMESPACE class QIODevice; QT_END_NAMESPACE namespace qbs { namespace Internal { class NodeTreeDumper : public BuildGraphVisitor { public: NodeTreeDumper(QIODevice &outDevice); void start(const QList &products); private: bool visit(Artifact *artifact) Q_DECL_OVERRIDE; void endVisit(Artifact *artifact) Q_DECL_OVERRIDE; bool visit(RuleNode *rule) Q_DECL_OVERRIDE; void endVisit(RuleNode *rule) Q_DECL_OVERRIDE; void doEndVisit(); void indent(); void unindent(); QByteArray indentation() const; QIODevice &m_outDevice; ResolvedProductPtr m_currentProduct; ArtifactSet m_visited; unsigned int m_indentation; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.4.5/src/lib/corelib/buildgraph/processcommandexecutor.cpp000066400000000000000000000264671266132464200255150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "processcommandexecutor.h" #include "artifact.h" #include "command.h" #include "transformer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { ProcessCommandExecutor::ProcessCommandExecutor(const Logger &logger, QObject *parent) : AbstractCommandExecutor(logger, parent) { connect(&m_process, SIGNAL(error(QProcess::ProcessError)), SLOT(onProcessError())); connect(&m_process, SIGNAL(finished(int)), SLOT(onProcessFinished(int))); } void ProcessCommandExecutor::doSetup() { const ProcessCommand * const cmd = processCommand(); const QString program = ExecutableFinder(transformer()->product(), transformer()->product()->buildEnvironment, logger()) .findExecutable(cmd->program(), cmd->workingDir()); m_program = program; m_arguments = cmd->arguments(); m_shellInvocation = shellQuote(QDir::toNativeSeparators(m_program), m_arguments); } void ProcessCommandExecutor::doStart() { QBS_ASSERT(m_process.state() == QProcess::NotRunning, return); const ProcessCommand * const cmd = processCommand(); QProcessEnvironment env = m_buildEnvironment; const QProcessEnvironment &additionalVariables = cmd->environment(); foreach (const QString &key, additionalVariables.keys()) env.insert(key, additionalVariables.value(key)); m_process.setProcessEnvironment(env); QStringList arguments = m_arguments; if (dryRun()) { QTimer::singleShot(0, this, SIGNAL(finished())); // Don't call back on the caller. return; } const QString workingDir = QDir::fromNativeSeparators(cmd->workingDir()); if (!workingDir.isEmpty()) { FileInfo fi(workingDir); if (!fi.exists() || !fi.isDir()) { emit finished(ErrorInfo(Tr::tr("The working directory '%1' for process '%2' " "is invalid.").arg(QDir::toNativeSeparators(workingDir), QDir::toNativeSeparators(m_program)), cmd->codeLocation())); return; } } // Automatically use response files, if the command line gets to long. if (!cmd->responseFileUsagePrefix().isEmpty()) { const int commandLineLength = m_shellInvocation.length(); if (cmd->responseFileThreshold() >= 0 && commandLineLength > cmd->responseFileThreshold()) { if (logger().debugEnabled()) { logger().qbsDebug() << QString::fromLocal8Bit("[EXEC] Using response file. " "Threshold is %1. Command line length %2.") .arg(cmd->responseFileThreshold()).arg(commandLineLength); } // The QTemporaryFile keeps a handle on the file, even if closed. // On Windows, some commands (e.g. msvc link.exe) won't accept that. // We need to delete the file manually, later. QTemporaryFile responseFile; responseFile.setAutoRemove(false); responseFile.setFileTemplate(QDir::tempPath() + QLatin1String("/qbsresp")); if (!responseFile.open()) { emit finished(ErrorInfo(Tr::tr("Cannot create response file '%1'.") .arg(responseFile.fileName()))); return; } for (int i = 0; i < cmd->arguments().count(); ++i) { responseFile.write(cmd->arguments().at(i).toLocal8Bit()); responseFile.write("\n"); } responseFile.close(); m_responseFileName = responseFile.fileName(); arguments.clear(); arguments += QDir::toNativeSeparators(cmd->responseFileUsagePrefix() + responseFile.fileName()); } } logger().qbsDebug() << "[EXEC] Running external process; full command line is: " << m_shellInvocation; logger().qbsTrace() << "[EXEC] Additional environment:" << additionalVariables.toStringList(); m_process.setWorkingDirectory(workingDir); m_process.start(m_program, arguments); } void ProcessCommandExecutor::cancel() { // We don't want this command to be reported as failing, since we explicitly terminated it. disconnect(this, SIGNAL(reportProcessResult(qbs::ProcessResult)), 0, 0); m_process.terminate(); if (!m_process.waitForFinished(1000)) m_process.kill(); } QString ProcessCommandExecutor::filterProcessOutput(const QByteArray &_output, const QString &filterFunctionSource) { const QString output = QString::fromLocal8Bit(_output); if (filterFunctionSource.isEmpty()) return output; QScriptValue scope = scriptEngine()->newObject(); for (QVariantMap::const_iterator it = command()->properties().constBegin(); it != command()->properties().constEnd(); ++it) { scope.setProperty(it.key(), scriptEngine()->toScriptValue(it.value())); } ScriptContextScopePusher scopePusher(scriptEngine()->currentContext(), scope); Q_UNUSED(scopePusher); QScriptValue filterFunction = scriptEngine()->evaluate(QLatin1String("var f = ") + filterFunctionSource + QLatin1String("; f")); if (!filterFunction.isFunction()) { logger().printWarning(ErrorInfo(Tr::tr("Error in filter function: %1.\n%2") .arg(filterFunctionSource, filterFunction.toString()))); return output; } QScriptValue outputArg = scriptEngine()->newArray(1); outputArg.setProperty(0, scriptEngine()->toScriptValue(output)); QScriptValue filteredOutput = filterFunction.call(scriptEngine()->undefinedValue(), outputArg); if (scriptEngine()->hasErrorOrException(filteredOutput)) { logger().printWarning(ErrorInfo(Tr::tr("Error when calling output filter function: %1") .arg(scriptEngine()->lastErrorString(filteredOutput)))); return output; } return filteredOutput.toString(); } void ProcessCommandExecutor::sendProcessOutput(bool success) { ProcessResult result; result.d->executableFilePath = m_program; result.d->arguments = m_arguments; result.d->workingDirectory = m_process.workingDirectory(); if (result.workingDirectory().isEmpty()) result.d->workingDirectory = QDir::currentPath(); result.d->exitCode = m_process.exitCode(); result.d->exitStatus = m_process.exitStatus(); result.d->success = success; QString tmp = filterProcessOutput(m_process.readAllStandardOutput(), processCommand()->stdoutFilterFunction()); if (!tmp.isEmpty()) { if (tmp.endsWith(QLatin1Char('\n'))) tmp.chop(1); result.d->stdOut = tmp.split(QLatin1Char('\n')); } tmp = filterProcessOutput(m_process.readAllStandardError(), processCommand()->stderrFilterFunction()); if (!tmp.isEmpty()) { if (tmp.endsWith(QLatin1Char('\n'))) tmp.chop(1); result.d->stdErr = tmp.split(QLatin1Char('\n')); } emit reportProcessResult(result); } void ProcessCommandExecutor::onProcessError() { switch (m_process.error()) { case QProcess::FailedToStart: { removeResponseFile(); const QString binary = QDir::toNativeSeparators(processCommand()->program()); QString errorPrefixString; #ifdef Q_OS_UNIX if (QFileInfo(binary).isExecutable()) { const QString interpreter(shellInterpreter(binary)); if (!interpreter.isEmpty()) { errorPrefixString = Tr::tr("%1: bad interpreter: ").arg(interpreter); } } #endif emit finished(ErrorInfo(Tr::tr("The process '%1' could not be started: %2. " "The full command line invocation was: %3") .arg(binary, errorPrefixString + m_process.errorString(), m_shellInvocation))); break; } case QProcess::Crashed: break; // Ignore. Will be handled by onProcessFinished(). default: logger().qbsWarning() << "QProcess error: " << m_process.errorString(); } } void ProcessCommandExecutor::onProcessFinished(int exitCode) { removeResponseFile(); const bool crashed = m_process.exitStatus() == QProcess::CrashExit; const bool errorOccurred = crashed || quint32(exitCode) > quint32(processCommand()->maxExitCode()); sendProcessOutput(!errorOccurred); if (Q_UNLIKELY(crashed)) emit finished(ErrorInfo(Tr::tr("Process crashed."))); else if (Q_UNLIKELY(errorOccurred)) emit finished(ErrorInfo(Tr::tr("Process failed with exit code %1.").arg(exitCode))); else emit finished(); } void ProcessCommandExecutor::doReportCommandDescription() { if (m_echoMode == CommandEchoModeCommandLine) { emit reportCommandDescription(command()->highlight(), m_shellInvocation); return; } AbstractCommandExecutor::doReportCommandDescription(); } void ProcessCommandExecutor::removeResponseFile() { if (m_responseFileName.isEmpty()) return; QFile::remove(m_responseFileName); m_responseFileName.clear(); } const ProcessCommand *ProcessCommandExecutor::processCommand() const { return static_cast(command()); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/processcommandexecutor.h000066400000000000000000000055271266132464200251540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROCESSCOMMANDEXECUTOR_H #define QBS_PROCESSCOMMANDEXECUTOR_H #include "abstractcommandexecutor.h" #include #include #include namespace qbs { class ProcessResult; namespace Internal { class ProcessCommand; class ProcessCommandExecutor : public AbstractCommandExecutor { Q_OBJECT public: explicit ProcessCommandExecutor(const Internal::Logger &logger, QObject *parent = 0); void setProcessEnvironment(const QProcessEnvironment &processEnvironment) { m_buildEnvironment = processEnvironment; } signals: void reportProcessResult(const qbs::ProcessResult &result); private slots: void onProcessError(); void onProcessFinished(int exitCode); private: void doSetup(); void doReportCommandDescription(); void doStart(); void cancel(); void startProcessCommand(); QString filterProcessOutput(const QByteArray &output, const QString &filterFunctionSource); void sendProcessOutput(bool success); void removeResponseFile(); const ProcessCommand *processCommand() const; private: QString m_program; QStringList m_arguments; QString m_shellInvocation; QProcess m_process; QProcessEnvironment m_buildEnvironment; QString m_responseFileName; }; } // namespace Internal } // namespace qbs #endif // QBS_PROCESSCOMMANDEXECUTOR_H qbs-src-1.4.5/src/lib/corelib/buildgraph/productbuilddata.cpp000066400000000000000000000116661266132464200242460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "productbuilddata.h" #include "artifact.h" #include "command.h" #include "projectbuilddata.h" #include #include #include #include #include namespace qbs { namespace Internal { ProductBuildData::~ProductBuildData() { qDeleteAll(nodes); } ArtifactSet ProductBuildData::rootArtifacts() const { return ArtifactSet::fromNodeSet(roots); } static void loadArtifactSetByFileTag(PersistentPool &pool, ProductBuildData::ArtifactSetByFileTag &s) { int elemCount; pool.stream() >> elemCount; for (int i = 0; i < elemCount; ++i) { QVariant fileTag; pool.stream() >> fileTag; ArtifactSet artifacts; pool.loadContainer(artifacts); s.insert(FileTag::fromSetting(fileTag), artifacts); } } void ProductBuildData::load(PersistentPool &pool) { nodes.load(pool); roots.load(pool); int count; pool.stream() >> count; rescuableArtifactData.reserve(count); for (int i = 0; i < count; ++i) { const QString filePath = pool.idLoadString(); RescuableArtifactData elem; elem.load(pool); rescuableArtifactData.insert(filePath, elem); } loadArtifactSetByFileTag(pool, artifactsByFileTag); pool.stream() >> count; for (int i = 0; i < count; ++i) { const RulePtr r = pool.idLoadS(); ArtifactSet s; pool.loadContainer(s); artifactsWithChangedInputsPerRule.insert(r, s); } } static void storeArtifactSetByFileTag(PersistentPool &pool, const ProductBuildData::ArtifactSetByFileTag &s) { pool.stream() << s.count(); ProductBuildData::ArtifactSetByFileTag::ConstIterator it; for (it = s.constBegin(); it != s.constEnd(); ++it) { pool.stream() << it.key().toSetting(); pool.storeContainer(it.value()); } } void ProductBuildData::store(PersistentPool &pool) const { nodes.store(pool); roots.store(pool); pool.stream() << rescuableArtifactData.count(); for (AllRescuableArtifactData::ConstIterator it = rescuableArtifactData.constBegin(); it != rescuableArtifactData.constEnd(); ++it) { pool.storeString(it.key()); it.value().store(pool); } storeArtifactSetByFileTag(pool, artifactsByFileTag); pool.stream() << artifactsWithChangedInputsPerRule.count(); for (ArtifactSetByRule::ConstIterator it = artifactsWithChangedInputsPerRule.constBegin(); it != artifactsWithChangedInputsPerRule.constEnd(); ++it) { pool.store(it.key()); pool.storeContainer(it.value()); } } void addArtifactToSet(Artifact *artifact, ProductBuildData::ArtifactSetByFileTag &container) { foreach (const FileTag &tag, artifact->fileTags()) container[tag] += artifact; } void removeArtifactFromSetByFileTag(Artifact *artifact, const FileTag &fileTag, ProductBuildData::ArtifactSetByFileTag &container) { ProductBuildData::ArtifactSetByFileTag::iterator it = container.find(fileTag); if (it == container.end()) return; it->remove(artifact); if (it->isEmpty()) container.erase(it); } void removeArtifactFromSet(Artifact *artifact, ProductBuildData::ArtifactSetByFileTag &container) { foreach (const FileTag &t, artifact->fileTags()) removeArtifactFromSetByFileTag(artifact, t, container); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/productbuilddata.h000066400000000000000000000062271266132464200237100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PRODUCTBUILDDATA_H #define QBS_PRODUCTBUILDDATA_H #include "artifactset.h" #include "nodeset.h" #include "rescuableartifactdata.h" #include #include #include #include #include namespace qbs { namespace Internal { class Logger; class ProductBuildData : public PersistentObject { public: ~ProductBuildData(); ArtifactSet rootArtifacts() const; NodeSet nodes; NodeSet roots; // After change tracking, this is the relevant data of artifacts that were in the build data // of the restored product, and will potentially be re-created by our rules. // If and when that happens, the relevant data will be copied over to the newly created // artifact. AllRescuableArtifactData rescuableArtifactData; // Do not store, initialized in executor. Higher prioritized artifacts are built first. unsigned int buildPriority; typedef QHash ArtifactSetByFileTag; ArtifactSetByFileTag artifactsByFileTag; typedef QHash ArtifactSetByRule; ArtifactSetByRule artifactsWithChangedInputsPerRule; private: void load(PersistentPool &pool); void store(PersistentPool &pool) const; }; void addArtifactToSet(Artifact *artifact, ProductBuildData::ArtifactSetByFileTag &container); void removeArtifactFromSetByFileTag(Artifact *artifact, const FileTag &fileTag, ProductBuildData::ArtifactSetByFileTag &container); void removeArtifactFromSet(Artifact *artifact, ProductBuildData::ArtifactSetByFileTag &container); } // namespace Internal } // namespace qbs #endif // QBS_PRODUCTBUILDDATA_H qbs-src-1.4.5/src/lib/corelib/buildgraph/productinstaller.cpp000066400000000000000000000214251266132464200243040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "productinstaller.h" #include "artifact.h" #include "productbuilddata.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { ProductInstaller::ProductInstaller(const TopLevelProjectPtr &project, const QList &products, const InstallOptions &options, ProgressObserver *observer, const Logger &logger) : m_project(project), m_products(products), m_options(options), m_observer(observer), m_logger(logger) { if (!m_options.installRoot().isEmpty()) { QFileInfo installRootFileInfo(m_options.installRoot()); QBS_ASSERT(installRootFileInfo.isAbsolute(), /* just complain */); if (m_options.removeExistingInstallation()) { const QString cfp = installRootFileInfo.canonicalFilePath(); if (cfp == QFileInfo(QDir::rootPath()).canonicalFilePath()) throw ErrorInfo(Tr::tr("Refusing to remove root directory.")); if (cfp == QFileInfo(QDir::homePath()).canonicalFilePath()) throw ErrorInfo(Tr::tr("Refusing to remove home directory.")); } return; } if (m_options.installIntoSysroot()) { if (m_options.removeExistingInstallation()) throw ErrorInfo(Tr::tr("Refusing to remove sysroot.")); } initInstallRoot(project.data(), m_options); } void ProductInstaller::install() { if (m_options.removeExistingInstallation()) removeInstallRoot(); QList artifactsToInstall; foreach (const ResolvedProductConstPtr &product, m_products) { QBS_CHECK(product->buildData); foreach (const Artifact *artifact, ArtifactSet::fromNodeSet(product->buildData->nodes)) { if (artifact->properties->qbsPropertyValue(QLatin1String("install")).toBool()) artifactsToInstall += artifact; } } m_observer->initialize(Tr::tr("Installing"), artifactsToInstall.count()); foreach (const Artifact * const a, artifactsToInstall) { copyFile(a); m_observer->incrementProgressValue(); } } QString ProductInstaller::targetFilePath(const TopLevelProject *project, const QString &productSourceDir, const QString &sourceFilePath, const PropertyMapConstPtr &properties, InstallOptions &options) { if (!properties->qbsPropertyValue(QLatin1String("install")).toBool()) return QString(); const QString relativeInstallDir = properties->qbsPropertyValue(QLatin1String("installDir")).toString(); const QString installPrefix = properties->qbsPropertyValue(QLatin1String("installPrefix")).toString(); const QString installSourceBase = properties->qbsPropertyValue(QLatin1String("installSourceBase")).toString(); initInstallRoot(project, options); QString targetDir = options.installRoot(); targetDir.append(QLatin1Char('/')).append(installPrefix) .append(QLatin1Char('/')).append(relativeInstallDir); targetDir = QDir::cleanPath(targetDir); QString targetFilePath; if (installSourceBase.isEmpty()) { // This has the same effect as if installSourceBase would equal the directory of the file. targetFilePath = FileInfo::fileName(sourceFilePath); } else { const QString localAbsBasePath = FileInfo::resolvePath(QDir::cleanPath(productSourceDir), QDir::cleanPath(installSourceBase)); targetFilePath = sourceFilePath; if (!targetFilePath.startsWith(localAbsBasePath)) { throw ErrorInfo(Tr::tr("Cannot install '%1', because it doesn't start with the" " value of qbs.installSourceBase '%2'.").arg(sourceFilePath, localAbsBasePath)); } targetFilePath.remove(0, localAbsBasePath.length() + 1); } targetFilePath.prepend(targetDir + QLatin1Char('/')); return targetFilePath; } void ProductInstaller::initInstallRoot(const TopLevelProject *project, InstallOptions &options) { if (!options.installRoot().isEmpty()) return; options.setInstallRoot(effectiveInstallRoot(options, project)); } void ProductInstaller::removeInstallRoot() { const QString nativeInstallRoot = QDir::toNativeSeparators(m_options.installRoot()); if (m_options.dryRun()) { m_logger.qbsInfo() << Tr::tr("Would remove install root '%1'.").arg(nativeInstallRoot); return; } m_logger.qbsDebug() << QString::fromLocal8Bit("Removing install root '%1'.") .arg(nativeInstallRoot); QString errorMessage; if (!removeDirectoryWithContents(m_options.installRoot(), &errorMessage)) { const QString fullErrorMessage = Tr::tr("Cannot remove install root '%1': %2") .arg(QDir::toNativeSeparators(m_options.installRoot()), errorMessage); handleError(fullErrorMessage); } } void ProductInstaller::copyFile(const Artifact *artifact) { if (m_observer->canceled()) { throw ErrorInfo(Tr::tr("Installation canceled for configuration '%1'.") .arg(m_products.first()->project->topLevelProject()->id())); } const QString targetFilePath = this->targetFilePath(m_project.data(), artifact->product->sourceDirectory, artifact->filePath(), artifact->properties, m_options); const QString targetDir = FileInfo::path(targetFilePath); const QString nativeFilePath = QDir::toNativeSeparators(artifact->filePath()); const QString nativeTargetDir = QDir::toNativeSeparators(targetDir); if (m_options.dryRun()) { m_logger.qbsDebug() << Tr::tr("Would copy file '%1' into target directory '%2'.") .arg(nativeFilePath, nativeTargetDir); return; } m_logger.qbsDebug() << QString::fromLocal8Bit("Copying file '%1' into target directory '%2'.") .arg(nativeFilePath, nativeTargetDir); if (!QDir::root().mkpath(targetDir)) { handleError(Tr::tr("Directory '%1' could not be created.").arg(nativeTargetDir)); return; } QFileInfo fi(artifact->filePath()); if (fi.isDir() && !(HostOsInfo::isAnyUnixHost() && fi.isSymLink())) { m_logger.qbsWarning() << Tr::tr("Recursively copying directory '%1' into target directory " "'%2'. This behavior is deprecated and will change in qbs " "1.5. Install the individual file artifacts instead.") .arg(nativeFilePath, nativeTargetDir); } QString errorMessage; if (!copyFileRecursion(artifact->filePath(), targetFilePath, true, &errorMessage)) handleError(Tr::tr("Installation error: %1").arg(errorMessage)); } void ProductInstaller::handleError(const QString &message) { if (!m_options.keepGoing()) throw ErrorInfo(message); m_logger.qbsWarning() << message; } } // namespace Intern } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/productinstaller.h000066400000000000000000000052661266132464200237560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PRODUCT_INSTALLER_H #define QBS_PRODUCT_INSTALLER_H #include "forward_decls.h" #include #include #include #include namespace qbs { namespace Internal { class ProgressObserver; class ProductInstaller { public: ProductInstaller(const TopLevelProjectPtr &project, const QList &products, const InstallOptions &options, ProgressObserver *observer, const Logger &logger); void install(); static QString targetFilePath(const TopLevelProject *project, const QString &productSourceDir, const QString &sourceFilePath, const PropertyMapConstPtr &properties, InstallOptions &options); static void initInstallRoot(const TopLevelProject *project, InstallOptions &options); void removeInstallRoot(); void copyFile(const Artifact *artifact); private: void handleError(const QString &message); const TopLevelProjectConstPtr m_project; const QList m_products; InstallOptions m_options; ProgressObserver * const m_observer; Logger m_logger; }; } // namespace Internal } // namespace qbs #endif // Header guard qbs-src-1.4.5/src/lib/corelib/buildgraph/projectbuilddata.cpp000066400000000000000000000512031266132464200242230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "projectbuilddata.h" #include "artifact.h" #include "buildgraph.h" #include "buildgraphvisitor.h" #include "productbuilddata.h" #include "command.h" #include "rulegraph.h" #include "rulenode.h" #include "rulesevaluationcontext.h" #include "transformer.h" #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { static QSet findDependentProducts(const ResolvedProductPtr &product) { QSet result; foreach (const ResolvedProductPtr &parent, product->topLevelProject()->allProducts()) { if (parent->dependencies.contains(product)) result += parent; } return result; } class FindLeafRules : public BuildGraphVisitor { public: FindLeafRules() { } const QSet &apply(const ResolvedProductPtr &product) { m_result.clear(); m_product = product; QBS_CHECK(product->buildData); foreach (BuildGraphNode *n, product->buildData->nodes) n->accept(this); return m_result; } private: virtual bool visit(Artifact *) { return false; } virtual bool visit(RuleNode *node) { if (!hasChildRuleInThisProduct(node)) m_result << node; return false; } bool hasChildRuleInThisProduct(const RuleNode *node) const { foreach (BuildGraphNode *c, node->children) { if (c->product == m_product && c->type() == BuildGraphNode::RuleNodeType) return true; } return false; } ResolvedProductPtr m_product; QSet m_result; }; class FindRootRules : public BuildGraphVisitor { public: FindRootRules() { } const QList &apply(const ResolvedProductPtr &product) { m_result.clear(); foreach (BuildGraphNode *n, product->buildData->roots) n->accept(this); return m_result; } private: bool visit(Artifact *) { return false; } bool visit(RuleNode *node) { m_result << node; return false; } QList m_result; }; ProjectBuildData::ProjectBuildData(const ProjectBuildData *other) : isDirty(true), m_doCleanupInDestructor(true) { // This is needed for temporary duplication of build data when doing change tracking. if (other) { *this = *other; m_doCleanupInDestructor = false; } } ProjectBuildData::~ProjectBuildData() { if (!m_doCleanupInDestructor) return; qDeleteAll(fileDependencies); } QString ProjectBuildData::deriveBuildGraphFilePath(const QString &buildDir, const QString &projectId) { return buildDir + QLatin1Char('/') + projectId + QLatin1String(".bg"); } void ProjectBuildData::insertIntoLookupTable(FileResourceBase *fileres) { QList &lst = m_artifactLookupTable[fileres->fileName()][fileres->dirPath()]; if (!lst.contains(fileres)) lst.append(fileres); } void ProjectBuildData::removeFromLookupTable(FileResourceBase *fileres) { m_artifactLookupTable[fileres->fileName()][fileres->dirPath()].removeOne(fileres); } QList ProjectBuildData::lookupFiles(const QString &filePath) const { QString dirPath, fileName; FileInfo::splitIntoDirectoryAndFileName(filePath, &dirPath, &fileName); return lookupFiles(dirPath, fileName); } QList ProjectBuildData::lookupFiles(const QString &dirPath, const QString &fileName) const { return m_artifactLookupTable.value(fileName).value(dirPath); } QList ProjectBuildData::lookupFiles(const Artifact *artifact) const { return lookupFiles(artifact->dirPath(), artifact->fileName()); } void ProjectBuildData::insertFileDependency(FileDependency *dependency) { fileDependencies += dependency; insertIntoLookupTable(dependency); } static void disconnectArtifactChildren(Artifact *artifact, const Logger &logger) { if (logger.traceEnabled()) { logger.qbsTrace() << QString::fromLocal8Bit("[BG] disconnectChildren: '%1'") .arg(relativeArtifactFileName(artifact)); } foreach (BuildGraphNode * const child, artifact->children) child->parents.remove(artifact); artifact->children.clear(); artifact->childrenAddedByScanner.clear(); } static void disconnectArtifactParents(Artifact *artifact, const Logger &logger) { if (logger.traceEnabled()) { logger.qbsTrace() << QString::fromLocal8Bit("[BG] disconnectParents: '%1'") .arg(relativeArtifactFileName(artifact)); } foreach (BuildGraphNode * const parent, artifact->parents) { parent->children.remove(artifact); Artifact *parentArtifact = dynamic_cast(parent); if (parentArtifact) { QBS_CHECK(parentArtifact->transformer); parentArtifact->childrenAddedByScanner.remove(artifact); parentArtifact->transformer->inputs.remove(artifact); parentArtifact->product->registerArtifactWithChangedInputs(parentArtifact); } } artifact->parents.clear(); } static void disconnectArtifact(Artifact *artifact, const Logger &logger) { disconnectArtifactChildren(artifact, logger); disconnectArtifactParents(artifact, logger); } /*! * Removes the artifact and all the artifacts that depend exclusively on it. * Example: if you remove a cpp artifact then the obj artifact is removed but * not the resulting application (if there's more then one cpp artifact). */ void ProjectBuildData::removeArtifactAndExclusiveDependents(Artifact *artifact, const Logger &logger, bool removeFromProduct, ArtifactSet *removedArtifacts) { if (removedArtifacts) removedArtifacts->insert(artifact); foreach (Artifact *parent, ArtifactSet::fromNodeSet(artifact->parents)) { bool removeParent = false; disconnect(parent, artifact, logger); if (parent->children.isEmpty()) { removeParent = true; } else if (parent->transformer) { parent->product->registerArtifactWithChangedInputs(parent); parent->transformer->inputs.remove(artifact); removeParent = parent->transformer->inputs.isEmpty(); } if (removeParent) { removeArtifactAndExclusiveDependents(parent, logger, removeFromProduct, removedArtifacts); } else { parent->clearTimestamp(); } } const bool removeFromDisk = artifact->artifactType == Artifact::Generated; removeArtifact(artifact, logger, removeFromDisk, removeFromProduct); } static void removeFromRuleNodes(Artifact *artifact, const Logger &logger) { foreach (const ResolvedProductPtr &product, artifact->product->topLevelProject()->allProducts()) { if (!product->buildData) continue; foreach (BuildGraphNode *n, product->buildData->nodes) { if (n->type() != BuildGraphNode::RuleNodeType) continue; RuleNode * const ruleNode = static_cast(n); if (logger.traceEnabled()) { logger.qbsTrace() << "[BG] remove old input " << artifact->filePath() << " from rule " << ruleNode->rule()->toString(); } ruleNode->removeOldInputArtifact(artifact); } } } void ProjectBuildData::removeArtifact(Artifact *artifact, const Logger &logger, bool removeFromDisk, bool removeFromProduct) { if (logger.traceEnabled()) logger.qbsTrace() << "[BG] remove artifact " << relativeArtifactFileName(artifact); if (removeFromDisk) removeGeneratedArtifactFromDisk(artifact, logger); removeFromLookupTable(artifact); removeFromRuleNodes(artifact, logger); disconnectArtifact(artifact, logger); if (artifact->transformer) { artifact->product->unregisterArtifactWithChangedInputs(artifact); artifact->transformer->outputs.remove(artifact); } if (removeFromProduct) { artifact->product->buildData->nodes.remove(artifact); artifact->product->buildData->roots.remove(artifact); removeArtifactFromSet(artifact, artifact->product->buildData->artifactsByFileTag); } isDirty = true; } void ProjectBuildData::load(PersistentPool &pool) { int count; pool.stream() >> count; fileDependencies.clear(); fileDependencies.reserve(count); for (; --count >= 0;) { FileDependency *fileDependency = pool.idLoad(); insertFileDependency(fileDependency); } } void ProjectBuildData::store(PersistentPool &pool) const { pool.storeContainer(fileDependencies); } BuildDataResolver::BuildDataResolver(const Logger &logger) : m_logger(logger) { } void BuildDataResolver::resolveBuildData(const TopLevelProjectPtr &resolvedProject, const RulesEvaluationContextPtr &evalContext) { QBS_CHECK(!resolvedProject->buildData); m_project = resolvedProject; resolvedProject->buildData.reset(new ProjectBuildData); resolvedProject->buildData->evaluationContext = evalContext; const QList allProducts = resolvedProject->allProducts(); evalContext->initializeObserver(Tr::tr("Setting up build graph for configuration %1") .arg(resolvedProject->id()), allProducts.count() + 1); foreach (ResolvedProductPtr rProduct, allProducts) { if (rProduct->enabled) resolveProductBuildData(rProduct); evalContext->incrementProgressValue(); } evalContext->incrementProgressValue(); doSanityChecks(resolvedProject, m_logger); } void BuildDataResolver::resolveProductBuildDataForExistingProject(const TopLevelProjectPtr &project, const QList &freshProducts) { m_project = project; foreach (const ResolvedProductPtr &product, freshProducts) { if (product->enabled) resolveProductBuildData(product); } // Connect the leaf rules of all dependent products to the root rules of the dependency. foreach (const ResolvedProductPtr &product, freshProducts) { if (!product->enabled) continue; QBS_CHECK(product->buildData); const QList rootRules = FindRootRules().apply(product); QSet dependents = findDependentProducts(product); foreach (const ResolvedProductPtr &dependentProduct, dependents) { if (!dependentProduct->enabled) continue; foreach (RuleNode *leaf, FindLeafRules().apply(dependentProduct)) { foreach (RuleNode *root, rootRules) { loggedConnect(leaf, root, m_logger); } } } } } class CreateRuleNodes : public RuleGraphVisitor { public: CreateRuleNodes(const ResolvedProductPtr &product, const Logger &logger) : m_product(product), m_logger(logger) { } const QSet &leaves() const { return m_leaves; } private: const ResolvedProductPtr &m_product; const Logger &m_logger; QHash m_nodePerRule; QSet m_rulesOnPath; QList m_rulePath; QSet m_leaves; void visit(const RuleConstPtr &parentRule, const RuleConstPtr &rule) { if (m_rulesOnPath.contains(rule.data())) { QString pathstr; foreach (const Rule *r, m_rulePath) { pathstr += QLatin1Char('\n') + r->toString() + QLatin1Char('\t') + r->prepareScript->location.toString(); } throw ErrorInfo(Tr::tr("Cycle detected in rule dependencies: %1").arg(pathstr)); } m_rulesOnPath.insert(rule.data()); m_rulePath.append(rule.data()); RuleNode *node = m_nodePerRule.value(rule); if (!node) { node = new RuleNode; m_leaves.insert(node); m_nodePerRule.insert(rule, node); node->product = m_product; node->setRule(rule); m_product->buildData->nodes += node; if (m_logger.debugEnabled()) { m_logger.qbsDebug() << "[BG] create " << node->toString() << " for product " << m_product->uniqueName(); } } if (parentRule) { RuleNode *parent = m_nodePerRule.value(parentRule); QBS_CHECK(parent); loggedConnect(parent, node, m_logger); m_leaves.remove(parent); } else { m_product->buildData->roots += node; } } void endVisit(const RuleConstPtr &rule) { m_rulesOnPath.remove(rule.data()); m_rulePath.removeLast(); } }; void BuildDataResolver::resolveProductBuildData(const ResolvedProductPtr &product) { if (product->buildData) return; evalContext()->checkForCancelation(); product->buildData.reset(new ProductBuildData); ProductBuildData::ArtifactSetByFileTag artifactsPerFileTag; foreach (ResolvedProductPtr dependency, product->dependencies) { if (Q_UNLIKELY(!dependency->enabled)) { ErrorInfo e; e.append(Tr::tr("Product '%1' depends on '%2',") .arg(product->name, dependency->name), product->location); e.append(Tr::tr("but product '%1' is disabled.").arg(dependency->name), dependency->location); throw e; } resolveProductBuildData(dependency); } //add qbsFile artifact Artifact *qbsFileArtifact = lookupArtifact(product, product->location.filePath()); if (!qbsFileArtifact) { qbsFileArtifact = new Artifact; qbsFileArtifact->artifactType = Artifact::SourceFile; qbsFileArtifact->setFilePath(product->location.filePath()); qbsFileArtifact->properties = product->moduleProperties; insertArtifact(product, qbsFileArtifact, m_logger); } qbsFileArtifact->addFileTag("qbs"); artifactsPerFileTag["qbs"].insert(qbsFileArtifact); // read sources foreach (const SourceArtifactConstPtr &sourceArtifact, product->allEnabledFiles()) { QString filePath = sourceArtifact->absoluteFilePath; if (lookupArtifact(product, filePath)) continue; // ignore duplicate artifacts Artifact *artifact = createArtifact(product, sourceArtifact, m_logger); foreach (const FileTag &fileTag, artifact->fileTags()) artifactsPerFileTag[fileTag].insert(artifact); } // read manually added transformers typedef QPair TrafoPair; QList trafos; foreach (const ResolvedTransformerConstPtr &rtrafo, product->transformers) { ArtifactSet inputArtifacts; foreach (const QString &inputFileName, rtrafo->inputs) { Artifact *artifact = lookupArtifact(product, inputFileName); if (Q_UNLIKELY(!artifact)) throw ErrorInfo(Tr::tr("Cannot find artifact '%0' in the list of source files.") .arg(inputFileName)); inputArtifacts += artifact; } TransformerPtr transformer = Transformer::create(); trafos += TrafoPair(rtrafo, transformer); transformer->inputs = inputArtifacts; const RulePtr rule = Rule::create(); ResolvedModulePtr module = ResolvedModule::create(); module->name = rtrafo->module->name; rule->module = module; rule->prepareScript = rtrafo->transform; foreach (const SourceArtifactConstPtr &sourceArtifact, rtrafo->outputs) { Artifact *outputArtifact = createArtifact(product, sourceArtifact, m_logger); outputArtifact->artifactType = Artifact::Generated; outputArtifact->transformer = transformer; transformer->outputs += outputArtifact; product->buildData->roots += outputArtifact; foreach (Artifact *inputArtifact, inputArtifacts) safeConnect(outputArtifact, inputArtifact, m_logger); foreach (const FileTag &fileTag, outputArtifact->fileTags()) artifactsPerFileTag[fileTag].insert(outputArtifact); RuleArtifactPtr ruleArtifact = RuleArtifact::create(); ruleArtifact->filePath = outputArtifact->filePath(); ruleArtifact->fileTags = outputArtifact->fileTags(); rule->artifacts += ruleArtifact; } transformer->rule = rule; RulesEvaluationContext::Scope s(evalContext().data()); setupScriptEngineForFile(engine(), transformer->rule->prepareScript->fileContext, scope()); QScriptValue prepareScriptContext = engine()->newObject(); PrepareScriptObserver observer(engine()); setupScriptEngineForProduct(engine(), product, transformer->rule->module, prepareScriptContext, &observer); transformer->setupInputs(prepareScriptContext); transformer->setupOutputs(engine(), prepareScriptContext); transformer->createCommands(rtrafo->transform, evalContext(), ScriptEngine::argumentList(transformer->rule->prepareScript->argumentNames, prepareScriptContext)); if (Q_UNLIKELY(transformer->commands.isEmpty())) throw ErrorInfo(Tr::tr("There is a transformer without commands."), rtrafo->transform->location); } // Handle Transformer.explicitlyDependsOn after all transformer outputs have been created. foreach (const TrafoPair &p, trafos) { const ResolvedTransformerConstPtr &rtrafo = p.first; const TransformerConstPtr &trafo = p.second; foreach (const FileTag &tag, rtrafo->explicitlyDependsOn) { foreach (Artifact *output, trafo->outputs) { foreach (Artifact *dependency, artifactsPerFileTag.value(tag)) { loggedConnect(output, dependency, m_logger); } } } } RuleGraph ruleGraph; ruleGraph.build(product->rules, product->fileTags); CreateRuleNodes crn(product, m_logger); ruleGraph.accept(&crn); // Connect the leaf rules of this product to the root rules of all product dependencies. foreach (const ResolvedProductConstPtr &dep, product->dependencies) { if (!dep->buildData) continue; foreach (BuildGraphNode *depRoot, dep->buildData->roots) { RuleNode *depRootRule = dynamic_cast(depRoot); if (!depRootRule) continue; foreach (RuleNode *leafRule, crn.leaves()) loggedConnect(leafRule, depRootRule, m_logger); } } } RulesEvaluationContextPtr BuildDataResolver::evalContext() const { return m_project->buildData->evaluationContext; } ScriptEngine *BuildDataResolver::engine() const { return evalContext()->engine(); } QScriptValue BuildDataResolver::scope() const { return evalContext()->scope(); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/projectbuilddata.h000066400000000000000000000100041266132464200236620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROJECTBUILDDATA_H #define QBS_PROJECTBUILDDATA_H #include "forward_decls.h" #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class ArtifactSet; class BuildGraphNode; class FileDependency; class FileResourceBase; class ScriptEngine; class ProjectBuildData : public PersistentObject { public: ProjectBuildData(const ProjectBuildData *other = 0); ~ProjectBuildData(); static QString deriveBuildGraphFilePath(const QString &buildDir, const QString &projectId); void insertIntoLookupTable(FileResourceBase *fileres); void removeFromLookupTable(FileResourceBase *fileres); QList lookupFiles(const QString &filePath) const; QList lookupFiles(const QString &dirPath, const QString &fileName) const; QList lookupFiles(const Artifact *artifact) const; void insertFileDependency(FileDependency *dependency); void removeArtifactAndExclusiveDependents(Artifact *artifact, const Logger &logger, bool removeFromProduct = true, ArtifactSet *removedArtifacts = 0); void removeArtifact(Artifact *artifact, const Logger &logger, bool removeFromDisk = true, bool removeFromProduct = true); QSet fileDependencies; // do not serialize: RulesEvaluationContextPtr evaluationContext; bool isDirty; private: void load(PersistentPool &pool); void store(PersistentPool &pool) const; typedef QHash > ResultsPerDirectory; typedef QHash ArtifactLookupTable; ArtifactLookupTable m_artifactLookupTable; bool m_doCleanupInDestructor; }; class BuildDataResolver { public: BuildDataResolver(const Logger &logger); void resolveBuildData(const TopLevelProjectPtr &resolvedProject, const RulesEvaluationContextPtr &evalContext); void resolveProductBuildDataForExistingProject(const TopLevelProjectPtr &project, const QList &freshProducts); private: void resolveProductBuildData(const ResolvedProductPtr &product); RulesEvaluationContextPtr evalContext() const; ScriptEngine *engine() const; QScriptValue scope() const; TopLevelProjectPtr m_project; Logger m_logger; }; } // namespace Internal } // namespace qbs #endif // QBS_PROJECTBUILDDATA_H qbs-src-1.4.5/src/lib/corelib/buildgraph/qtmocscanner.cpp000066400000000000000000000204511266132464200234010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "qtmocscanner.h" #include "artifact.h" #include "productbuilddata.h" #include "scanresultcache.h" #include #include #include #include #include #include #include namespace qbs { namespace Internal { QtMocScanner::QtMocScanner(const ResolvedProductPtr &product, QScriptValue targetScriptValue, const Logger &logger) : m_product(product) , m_targetScriptValue(targetScriptValue) , m_logger(logger) , m_scanResultCache(new ScanResultCache) , m_cppScanner(0) , m_hppScanner(0) { QScriptEngine *engine = targetScriptValue.engine(); QScriptValue scannerObj = engine->newObject(); targetScriptValue.setProperty(QLatin1String("QtMocScanner"), scannerObj); QScriptValue applyFunction = engine->newFunction(&js_apply, this); scannerObj.setProperty(QLatin1String("apply"), applyFunction); } QtMocScanner::~QtMocScanner() { m_targetScriptValue.setProperty(QLatin1String("QtMocScanner"), QScriptValue()); delete m_scanResultCache; } static ScanResultCache::Result runScanner(ScannerPlugin *scanner, const Artifact *artifact, ScanResultCache *scanResultCache) { const QString &filepath = artifact->filePath(); ScanResultCache::Result scanResult = scanResultCache->value(scanner, filepath); if (!scanResult.valid) { scanResult.valid = true; void *opaq = scanner->open(filepath.utf16(), ScanForDependenciesFlag | ScanForFileTagsFlag); if (!opaq || !scanner->additionalFileTags) return scanResult; int length = 0; const char **szFileTagsFromScanner = scanner->additionalFileTags(opaq, &length); if (szFileTagsFromScanner) { for (int i = length; --i >= 0;) scanResult.additionalFileTags += szFileTagsFromScanner[i]; } QString baseDirOfInFilePath = artifact->dirPath(); forever { int flags = 0; const char *szOutFilePath = scanner->next(opaq, &length, &flags); if (szOutFilePath == 0) break; QString includedFilePath = QString::fromLocal8Bit(szOutFilePath, length); if (includedFilePath.isEmpty()) continue; bool isLocalInclude = (flags & SC_LOCAL_INCLUDE_FLAG); if (isLocalInclude) { QString localFilePath = FileInfo::resolvePath(baseDirOfInFilePath, includedFilePath); if (FileInfo::exists(localFilePath)) includedFilePath = localFilePath; } scanResult.deps += ScanResultCache::Dependency(includedFilePath); } scanner->close(opaq); scanResultCache->insert(scanner, filepath, scanResult); } return scanResult; } void QtMocScanner::findIncludedMocCppFiles() { if (!m_includedMocCppFiles.isEmpty()) return; if (m_logger.traceEnabled()) m_logger.qbsTrace() << "[QtMocScanner] looking for included moc_XXX.cpp files"; foreach (Artifact *artifact, m_product->lookupArtifactsByFileTag("cpp")) { const ScanResultCache::Result scanResult = runScanner(m_cppScanner, artifact, m_scanResultCache); foreach (const ScanResultCache::Dependency &dependency, scanResult.deps) { QString includedFileName = dependency.fileName(); if (includedFileName.startsWith(QLatin1String("moc_")) && includedFileName.endsWith(QLatin1String(".cpp"))) { if (m_logger.traceEnabled()) m_logger.qbsTrace() << "[QtMocScanner] " << artifact->fileName() << " includes " << includedFileName; includedFileName.remove(0, 4); includedFileName.chop(4); m_includedMocCppFiles.insert(includedFileName, artifact->fileName()); } } } } QScriptValue QtMocScanner::js_apply(QScriptContext *ctx, QScriptEngine *engine, void *data) { QtMocScanner *that = reinterpret_cast(data); QScriptValue input = ctx->argument(0); return that->apply(engine, attachedPointer(input)); } static QScriptValue scannerCountError(QScriptEngine *engine, int scannerCount, const QString &fileTag) { return engine->currentContext()->throwError( Tr::tr("There are %1 scanners for the file tag %2. " "Expected is exactly one.").arg(scannerCount).arg(fileTag)); } QScriptValue QtMocScanner::apply(QScriptEngine *engine, const Artifact *artifact) { if (!m_cppScanner) { QList scanners = ScannerPluginManager::scannersForFileTag("cpp"); if (scanners.count() != 1) return scannerCountError(engine, scanners.count(), QLatin1String("cpp")); m_cppScanner = scanners.first(); scanners = ScannerPluginManager::scannersForFileTag("hpp"); if (scanners.count() != 1) return scannerCountError(engine, scanners.count(), QLatin1String("hpp")); m_hppScanner = scanners.first(); } findIncludedMocCppFiles(); if (m_logger.traceEnabled()) m_logger.qbsTrace() << "[QtMocScanner] scanning " << artifact->toString(); bool hasQObjectMacro = false; bool mustCompile = false; bool hasPluginMetaDataMacro = false; const bool isHeaderFile = artifact->fileTags().contains("hpp"); ScannerPlugin * const scanner = isHeaderFile ? m_hppScanner : m_cppScanner; const ScanResultCache::Result scanResult = runScanner(scanner, artifact, m_scanResultCache); if (!scanResult.additionalFileTags.isEmpty()) { if (isHeaderFile) { if (scanResult.additionalFileTags.contains("moc_hpp")) hasQObjectMacro = true; if (scanResult.additionalFileTags.contains("moc_hpp_plugin")) { hasQObjectMacro = true; hasPluginMetaDataMacro = true; } if (!m_includedMocCppFiles.contains(FileInfo::completeBaseName(artifact->fileName()))) mustCompile = true; } else { if (scanResult.additionalFileTags.contains("moc_cpp")) hasQObjectMacro = true; } } if (m_logger.traceEnabled()) { m_logger.qbsTrace() << "[QtMocScanner] hasQObjectMacro: " << hasQObjectMacro << " mustCompile: " << mustCompile << " hasPluginMetaDataMacro: " << hasPluginMetaDataMacro; } QScriptValue obj = engine->newObject(); obj.setProperty(QLatin1String("hasQObjectMacro"), hasQObjectMacro); obj.setProperty(QLatin1String("mustCompile"), mustCompile); obj.setProperty(QLatin1String("hasPluginMetaDataMacro"), hasPluginMetaDataMacro); return obj; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/qtmocscanner.h000066400000000000000000000050361266132464200230500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_QTMOCSCANNER_H #define QBS_QTMOCSCANNER_H #include #include #include #include #include QT_BEGIN_NAMESPACE class QScriptContext; QT_END_NAMESPACE class ScannerPlugin; namespace qbs { namespace Internal { class Artifact; class ScanResultCache; class QtMocScanner { public: explicit QtMocScanner(const ResolvedProductPtr &product, QScriptValue targetScriptValue, const Logger &logger); ~QtMocScanner(); private: void findIncludedMocCppFiles(); static QScriptValue js_apply(QScriptContext *ctx, QScriptEngine *engine, void *data); QScriptValue apply(QScriptEngine *engine, const Artifact *artifact); const ResolvedProductPtr &m_product; QScriptValue m_targetScriptValue; const Logger &m_logger; ScanResultCache *m_scanResultCache; QHash m_includedMocCppFiles; ScannerPlugin *m_cppScanner; ScannerPlugin *m_hppScanner; }; } // namespace Internal } // namespace qbs #endif // QBS_QTMOCSCANNER_H qbs-src-1.4.5/src/lib/corelib/buildgraph/rescuableartifactdata.cpp000066400000000000000000000050431266132464200252210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "rescuableartifactdata.h" #include "command.h" #include namespace qbs { namespace Internal { RescuableArtifactData::~RescuableArtifactData() { } void RescuableArtifactData::load(PersistentPool &pool) { pool.stream() >> timeStamp; int c; pool.stream() >> c; for (int i = 0; i < c; ++i) { ChildData cd; cd.productName = pool.idLoadString(); cd.productProfile = pool.idLoadString(); cd.childFilePath = pool.idLoadString(); pool.stream() >> cd.addedByScanner; children << cd; } commands = loadCommandList(pool); } void RescuableArtifactData::store(PersistentPool &pool) const { pool.stream() << timeStamp; pool.stream() << children.count(); foreach (const ChildData &cd, children) { pool.storeString(cd.productName); pool.storeString(cd.productProfile); pool.storeString(cd.childFilePath); pool.stream() << cd.addedByScanner; } storeCommandList(commands, pool); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/rescuableartifactdata.h000066400000000000000000000047701266132464200246740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_RESCUABLEARTIFACTDATA_H #define QBS_RESCUABLEARTIFACTDATA_H #include "forward_decls.h" #include #include #include namespace qbs { namespace Internal { class PersistentPool; class RescuableArtifactData { public: ~RescuableArtifactData(); void load(PersistentPool &pool); void store(PersistentPool &pool) const; struct ChildData { ChildData(const QString &n = QString(), const QString &p = QString(), const QString &c = QString(), bool byScanner = false) : productName(n), productProfile(p), childFilePath(c), addedByScanner(byScanner) {} QString productName; QString productProfile; QString childFilePath; bool addedByScanner; }; FileTime timeStamp; QList children; QList commands; }; typedef QHash AllRescuableArtifactData; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.4.5/src/lib/corelib/buildgraph/rulegraph.cpp000066400000000000000000000116411266132464200226760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "rulegraph.h" #include #include #include namespace qbs { namespace Internal { RuleGraph::RuleGraph() { } void RuleGraph::build(const QSet &rules, const FileTags &productFileTags) { QMap > inputFileTagToRule; m_rules.reserve(rules.count()); foreach (const RulePtr &rule, rules) { foreach (const FileTag &fileTag, rule->collectedOutputFileTags()) m_outputFileTagToRule[fileTag].append(rule.data()); insert(rule); } m_parents.resize(rules.count()); m_children.resize(rules.count()); foreach (const RuleConstPtr &rule, m_rules) { FileTags inFileTags = rule->inputs; inFileTags += rule->auxiliaryInputs; inFileTags += rule->explicitlyDependsOn; foreach (const FileTag &fileTag, inFileTags) { inputFileTagToRule[fileTag].append(rule.data()); foreach (const Rule * const producingRule, m_outputFileTagToRule.value(fileTag)) { if (!producingRule->collectedOutputFileTags().matches( rule->excludedAuxiliaryInputs)) { connect(rule.data(), producingRule); } } } } QList productRules; foreach (const FileTag &productFileTag, productFileTags) { QList rules = m_outputFileTagToRule.value(productFileTag); productRules += rules; //### check: the rule graph must be a in valid shape! } foreach (const Rule *r, productRules) m_rootRules += r->ruleGraphId; } void RuleGraph::accept(RuleGraphVisitor *visitor) const { const RuleConstPtr nullParent; foreach (int rootIndex, m_rootRules) traverse(visitor, nullParent, m_rules.at(rootIndex)); } void RuleGraph::dump() const { QByteArray indent; printf("---rule graph dump:\n"); QSet rootRules; foreach (const RuleConstPtr &rule, m_rules) if (m_parents[rule->ruleGraphId].isEmpty()) rootRules += rule->ruleGraphId; foreach (int idx, rootRules) { dump_impl(indent, idx); } } void RuleGraph::dump_impl(QByteArray &indent, int rootIndex) const { const RuleConstPtr r = m_rules[rootIndex]; printf("%s", indent.constData()); printf("%s", qPrintable(r->toString())); printf("\n"); indent.append(" "); foreach (int childIndex, m_children[rootIndex]) dump_impl(indent, childIndex); indent.chop(2); } int RuleGraph::insert(const RulePtr &rule) { rule->ruleGraphId = m_rules.count(); m_rules.append(rule); return rule->ruleGraphId; } void RuleGraph::connect(const Rule *creatingRule, const Rule *consumingRule) { int maxIndex = qMax(creatingRule->ruleGraphId, consumingRule->ruleGraphId); if (m_parents.count() <= maxIndex) { const int c = maxIndex + 1; m_parents.resize(c); m_children.resize(c); } m_parents[consumingRule->ruleGraphId].append(creatingRule->ruleGraphId); m_children[creatingRule->ruleGraphId].append(consumingRule->ruleGraphId); } void RuleGraph::traverse(RuleGraphVisitor *visitor, const RuleConstPtr &parentRule, const RuleConstPtr &rule) const { visitor->visit(parentRule, rule); foreach (int childIndex, m_children.at(rule->ruleGraphId)) traverse(visitor, rule, m_rules.at(childIndex)); visitor->endVisit(rule); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/rulegraph.h000066400000000000000000000052651266132464200223500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_RULEGRAPH_H #define QBS_RULEGRAPH_H #include #include #include #include #include #include #include namespace qbs { namespace Internal { class RuleGraphVisitor { public: virtual void visit(const RuleConstPtr &parentRule, const RuleConstPtr &rule) = 0; virtual void endVisit(const RuleConstPtr &rule) { Q_UNUSED(rule); } }; class RuleGraph { public: RuleGraph(); void build(const QSet &rules, const FileTags &productFileTag); void accept(RuleGraphVisitor *visitor) const; void dump() const; private: void dump_impl(QByteArray &indent, int rootIndex) const; int insert(const RulePtr &rule); void connect(const Rule *creatingRule, const Rule *consumingRule); void traverse(RuleGraphVisitor *visitor, const RuleConstPtr &parentRule, const RuleConstPtr &rule) const; private: QMap > m_outputFileTagToRule; QVector m_rules; QVector< QVector > m_parents; QVector< QVector > m_children; QSet m_rootRules; }; } // namespace Internal } // namespace qbs #endif // QBS_RULEGRAPH_H qbs-src-1.4.5/src/lib/corelib/buildgraph/rulenode.cpp000066400000000000000000000141441266132464200225230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "rulenode.h" #include "artifact.h" #include "buildgraph.h" #include "buildgraphvisitor.h" #include "productbuilddata.h" #include "projectbuilddata.h" #include "rulesapplicator.h" #include "transformer.h" #include #include #include #include namespace qbs { namespace Internal { RuleNode::RuleNode() { } RuleNode::~RuleNode() { } void RuleNode::accept(BuildGraphVisitor *visitor) { if (visitor->visit(this)) acceptChildren(visitor); visitor->endVisit(this); } QString RuleNode::toString() const { return QLatin1String("RULE ") + m_rule->toString(); } void RuleNode::apply(const Logger &logger, const ArtifactSet &changedInputs, ApplicationResult *result) { ArtifactSet allCompatibleInputs = currentInputArtifacts(); const ArtifactSet addedInputs = allCompatibleInputs - m_oldInputArtifacts; const ArtifactSet removedInputs = m_oldInputArtifacts - allCompatibleInputs; result->upToDate = changedInputs.isEmpty() && addedInputs.isEmpty() && removedInputs.isEmpty(); if (logger.traceEnabled()) { logger.qbsTrace() << "[BG] consider " << (m_rule->isDynamic() ? "dynamic " : "") << (m_rule->multiplex ? "multiplex " : "") << "rule node " << m_rule->toString() << "\n\tchanged: " << changedInputs.toString() << "\n\tcompatible: " << allCompatibleInputs.toString() << "\n\tadded: " << addedInputs.toString() << "\n\tremoved: " << removedInputs.toString(); } ArtifactSet inputs = changedInputs; if (product->isMarkedForReapplication(m_rule)) { QBS_CHECK(m_rule->multiplex); result->upToDate = false; product->unmarkForReapplication(m_rule); if (logger.traceEnabled()) logger.qbsTrace() << "[BG] rule is marked for reapplication " << m_rule->toString(); } if (m_rule->multiplex) inputs = allCompatibleInputs; else inputs += addedInputs; if (result->upToDate) return; if (!removedInputs.isEmpty()) { ArtifactSet outputArtifactsToRemove; foreach (Artifact *artifact, removedInputs) { foreach (Artifact *parent, ArtifactSet::fromNodeSet(artifact->parents)) { if (parent->transformer->rule != m_rule) { // parent was not created by our rule. continue; } // parent must always have a transformer, because it's generated. QBS_CHECK(parent->transformer); // artifact is a former input of m_rule and parent was created by m_rule // the inputs of the transformer must contain artifact QBS_CHECK(parent->transformer->inputs.contains(artifact)); outputArtifactsToRemove += parent; } } RulesApplicator::handleRemovedRuleOutputs(inputs, outputArtifactsToRemove, logger); } if (!inputs.isEmpty()) { RulesApplicator applicator(product, logger); applicator.applyRuleInEvaluationContext(m_rule, inputs); result->createdNodes = applicator.createdArtifacts(); result->invalidatedNodes = applicator.invalidatedArtifacts(); m_oldInputArtifacts.unite(inputs); } } void RuleNode::load(PersistentPool &pool) { BuildGraphNode::load(pool); m_rule = pool.idLoadS(); pool.loadContainer(m_oldInputArtifacts); } void RuleNode::store(PersistentPool &pool) const { BuildGraphNode::store(pool); pool.store(m_rule); pool.storeContainer(m_oldInputArtifacts); } ArtifactSet RuleNode::currentInputArtifacts() const { ArtifactSet s; foreach (const FileTag &t, m_rule->inputs) { foreach (Artifact *artifact, product->lookupArtifactsByFileTag(t)) { if (artifact->transformer && artifact->transformer->rule == m_rule) { // Do not add compatible artifacts as inputs that were created by this rule. // This can e.g. happen for the ["cpp", "hpp"] -> ["hpp", "cpp", "unmocable"] rule. continue; } s += artifact; } } foreach (const ResolvedProductConstPtr &dep, product->dependencies) { if (!dep->buildData) continue; if (m_rule->inputsFromDependencies.isEmpty()) continue; foreach (Artifact * const a, ArtifactSet::fromNodeSet(dep->buildData->nodes)) { if (a->fileTags().matches(m_rule->inputsFromDependencies)) s += a; } } return s; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/rulenode.h000066400000000000000000000051651266132464200221730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_RULENODE_H #define QBS_RULENODE_H #include "artifactset.h" #include "buildgraphnode.h" #include "forward_decls.h" #include namespace qbs { namespace Internal { class Logger; class RuleNode : public BuildGraphNode { public: RuleNode(); ~RuleNode(); void setRule(const RuleConstPtr &rule) { m_rule = rule; } const RuleConstPtr &rule() const { return m_rule; } Type type() const { return RuleNodeType; } void accept(BuildGraphVisitor *visitor); QString toString() const; struct ApplicationResult { bool upToDate; NodeSet createdNodes; NodeSet invalidatedNodes; }; void apply(const Logger &logger, const ArtifactSet &changedInputs, ApplicationResult *result); void removeOldInputArtifact(Artifact *artifact) { m_oldInputArtifacts.remove(artifact); } protected: void load(PersistentPool &pool); void store(PersistentPool &pool) const; private: ArtifactSet currentInputArtifacts() const; RuleConstPtr m_rule; ArtifactSet m_oldInputArtifacts; }; } // namespace Internal } // namespace qbs #endif // QBS_RULENODE_H qbs-src-1.4.5/src/lib/corelib/buildgraph/rulesapplicator.cpp000066400000000000000000000544061266132464200241240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "rulesapplicator.h" #include "artifact.h" #include "buildgraph.h" #include "emptydirectoriesremover.h" #include "productbuilddata.h" #include "projectbuilddata.h" #include "qtmocscanner.h" #include "rulesevaluationcontext.h" #include "transformer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { RulesApplicator::RulesApplicator(const ResolvedProductPtr &product, const Logger &logger) : m_product(product) , m_mocScanner(0) , m_logger(logger) { } RulesApplicator::~RulesApplicator() { delete m_mocScanner; } void RulesApplicator::applyRuleInEvaluationContext(const RuleConstPtr &rule, const ArtifactSet &inputArtifacts) { m_createdArtifacts.clear(); m_invalidatedArtifacts.clear(); RulesEvaluationContext::Scope s(m_product->topLevelProject()->buildData->evaluationContext.data()); applyRule(rule, inputArtifacts); } void RulesApplicator::applyRule(const RuleConstPtr &rule, const ArtifactSet &inputArtifacts) { if (inputArtifacts.isEmpty()) return; m_rule = rule; m_completeInputSet = inputArtifacts; if (rule->name == QLatin1String("QtCoreMocRule")) { delete m_mocScanner; m_mocScanner = new QtMocScanner(m_product, scope(), m_logger); } QScriptValue prepareScriptContext = engine()->newObject(); PrepareScriptObserver observer(engine()); setupScriptEngineForFile(engine(), m_rule->prepareScript->fileContext, scope()); setupScriptEngineForProduct(engine(), m_product, m_rule->module, prepareScriptContext, &observer); if (m_rule->multiplex) { // apply the rule once for a set of inputs doApply(inputArtifacts, prepareScriptContext); } else { // apply the rule once for each input foreach (Artifact * const inputArtifact, inputArtifacts) { ArtifactSet lst; lst += inputArtifact; doApply(lst, prepareScriptContext); } } } void RulesApplicator::handleRemovedRuleOutputs(const ArtifactSet &inputArtifacts, ArtifactSet outputArtifactsToRemove, const Logger &logger) { ArtifactSet artifactsToRemove; const TopLevelProject *project = 0; foreach (Artifact *removedArtifact, outputArtifactsToRemove) { if (logger.traceEnabled()) { logger.qbsTrace() << "[BG] dynamic rule removed output artifact " << removedArtifact->toString(); } if (!project) project = removedArtifact->product->topLevelProject(); project->buildData->removeArtifactAndExclusiveDependents(removedArtifact, logger, true, &artifactsToRemove); } // parents of removed artifacts must update their transformers foreach (Artifact *removedArtifact, artifactsToRemove) { foreach (Artifact *parent, removedArtifact->parentArtifacts()) parent->product->registerArtifactWithChangedInputs(parent); } EmptyDirectoriesRemover(project, logger).removeEmptyParentDirectories(artifactsToRemove); foreach (Artifact *artifact, artifactsToRemove) { QBS_CHECK(!inputArtifacts.contains(artifact)); delete artifact; } } static void copyProperty(const QString &name, const QScriptValue &src, QScriptValue dst) { dst.setProperty(name, src.property(name)); } static QStringList toStringList(const ArtifactSet &artifacts) { QStringList lst; foreach (const Artifact *artifact, artifacts) { const QString str = artifact->filePath() + QLatin1String(" [") + artifact->fileTags().toStringList().join(QLatin1String(", ")) + QLatin1Char(']'); lst << str; } return lst; } void RulesApplicator::doApply(const ArtifactSet &inputArtifacts, QScriptValue &prepareScriptContext) { evalContext()->checkForCancelation(); if (m_logger.debugEnabled()) { m_logger.qbsDebug() << QString::fromLatin1("[BG] apply rule ") << m_rule->toString() << QString::fromLatin1(" ") << toStringList(inputArtifacts).join(QLatin1String(",\n ")); } QList > ruleArtifactArtifactMap; QList outputArtifacts; m_transformer = Transformer::create(); m_transformer->rule = m_rule; m_transformer->inputs = inputArtifacts; // create the output artifacts from the set of input artifacts Transformer::setupInputs(prepareScriptContext, inputArtifacts, m_rule->module->name); copyProperty(QLatin1String("inputs"), prepareScriptContext, scope()); copyProperty(QLatin1String("input"), prepareScriptContext, scope()); copyProperty(QLatin1String("product"), prepareScriptContext, scope()); copyProperty(QLatin1String("project"), prepareScriptContext, scope()); if (m_rule->isDynamic()) { outputArtifacts = runOutputArtifactsScript(inputArtifacts, ScriptEngine::argumentList(m_rule->outputArtifactsScript->argumentNames, scope())); ArtifactSet newOutputs = ArtifactSet::fromNodeList(outputArtifacts); const ArtifactSet oldOutputs = collectOldOutputArtifacts(inputArtifacts); handleRemovedRuleOutputs(m_completeInputSet, oldOutputs - newOutputs, m_logger); } else { QSet outputFilePaths; foreach (const RuleArtifactConstPtr &ruleArtifact, m_rule->artifacts) { Artifact * const outputArtifact = createOutputArtifactFromRuleArtifact(ruleArtifact, inputArtifacts, &outputFilePaths); if (!outputArtifact) continue; outputArtifacts << outputArtifact; ruleArtifactArtifactMap << qMakePair(ruleArtifact.data(), outputArtifact); } } if (outputArtifacts.isEmpty()) return; foreach (Artifact *outputArtifact, outputArtifacts) { // connect artifacts that match the file tags in explicitlyDependsOn foreach (const FileTag &fileTag, m_rule->explicitlyDependsOn) foreach (Artifact *dependency, m_product->lookupArtifactsByFileTag(fileTag)) loggedConnect(outputArtifact, dependency, m_logger); outputArtifact->product->unregisterArtifactWithChangedInputs(outputArtifact); } if (inputArtifacts != m_transformer->inputs) m_transformer->setupInputs(prepareScriptContext); // change the transformer outputs according to the bindings in Artifact QScriptValue scriptValue; if (!ruleArtifactArtifactMap.isEmpty()) engine()->currentContext()->pushScope(prepareScriptContext); for (int i = ruleArtifactArtifactMap.count(); --i >= 0;) { const RuleArtifact *ra = ruleArtifactArtifactMap.at(i).first; if (ra->bindings.isEmpty()) continue; // expose attributes of this artifact Artifact *outputArtifact = ruleArtifactArtifactMap.at(i).second; outputArtifact->properties = outputArtifact->properties->clone(); scope().setProperty(QLatin1String("fileName"), engine()->toScriptValue(outputArtifact->filePath())); scope().setProperty(QLatin1String("fileTags"), toScriptValue(engine(), outputArtifact->fileTags().toStringList())); QVariantMap artifactModulesCfg = outputArtifact->properties->value() .value(QLatin1String("modules")).toMap(); for (int i=0; i < ra->bindings.count(); ++i) { const RuleArtifact::Binding &binding = ra->bindings.at(i); scriptValue = engine()->evaluate(binding.code); if (Q_UNLIKELY(engine()->hasErrorOrException(scriptValue))) { QString msg = QLatin1String("evaluating rule binding '%1': %2"); throw ErrorInfo(msg.arg(binding.name.join(QLatin1Char('.')), engine()->lastErrorString(scriptValue)), binding.location); } setConfigProperty(artifactModulesCfg, binding.name, scriptValue.toVariant()); } QVariantMap outputArtifactConfig = outputArtifact->properties->value(); outputArtifactConfig.insert(QLatin1String("modules"), artifactModulesCfg); outputArtifact->properties->setValue(outputArtifactConfig); } if (!ruleArtifactArtifactMap.isEmpty()) engine()->currentContext()->popScope(); m_transformer->setupOutputs(engine(), prepareScriptContext); m_transformer->createCommands(m_rule->prepareScript, evalContext(), ScriptEngine::argumentList(m_rule->prepareScript->argumentNames, prepareScriptContext)); if (Q_UNLIKELY(m_transformer->commands.isEmpty())) throw ErrorInfo(Tr::tr("There is a rule without commands: %1.") .arg(m_rule->toString()), m_rule->prepareScript->location); } ArtifactSet RulesApplicator::collectOldOutputArtifacts(const ArtifactSet &inputArtifacts) const { ArtifactSet result; foreach (Artifact *a, inputArtifacts) { foreach (Artifact *p, a->parentArtifacts()) { QBS_CHECK(p->transformer); if (p->transformer->rule == m_rule && p->transformer->inputs.contains(a)) result += p; } } return result; } Artifact *RulesApplicator::createOutputArtifactFromRuleArtifact( const RuleArtifactConstPtr &ruleArtifact, const ArtifactSet &inputArtifacts, QSet *outputFilePaths) { QScriptValue scriptValue = engine()->evaluate(ruleArtifact->filePath); if (Q_UNLIKELY(engine()->hasErrorOrException(scriptValue))) { throw ErrorInfo(Tr::tr("Error in Rule.Artifact fileName at %1: %2") .arg(ruleArtifact->location.toString(), engine()->lastErrorString(scriptValue))); } QString outputPath = FileInfo::resolvePath(m_product->buildDirectory(), scriptValue.toString()); if (Q_UNLIKELY(outputFilePaths->contains(outputPath))) { throw ErrorInfo(Tr::tr("Rule %1 already created '%2'.") .arg(m_rule->toString(), outputPath)); } outputFilePaths->insert(outputPath); return createOutputArtifact(outputPath, ruleArtifact->fileTags, ruleArtifact->alwaysUpdated, inputArtifacts); } Artifact *RulesApplicator::createOutputArtifact(const QString &filePath, const FileTags &fileTags, bool alwaysUpdated, const ArtifactSet &inputArtifacts) { QString outputPath = filePath; // don't let the output artifact "escape" its build dir outputPath.replace(QLatin1String(".."), QLatin1String("dotdot")); outputPath = resolveOutPath(outputPath); Artifact *outputArtifact = lookupArtifact(m_product, outputPath); if (outputArtifact) { if (outputArtifact->transformer && outputArtifact->transformer->rule != m_rule) { QString e = Tr::tr("Conflicting rules for producing %1 %2 \n") .arg(outputArtifact->filePath(), QLatin1Char('[') + outputArtifact->fileTags().toStringList().join(QLatin1String(", ")) + QLatin1Char(']')); QString str = QLatin1Char('[') + m_rule->inputs.toStringList().join(QLatin1String(", ")) + QLatin1String("] -> [") + outputArtifact->fileTags().toStringList() .join(QLatin1String(", ")) + QLatin1Char(']'); e += QString::fromLatin1(" while trying to apply: %1:%2:%3 %4\n") .arg(m_rule->prepareScript->location.filePath()) .arg(m_rule->prepareScript->location.line()) .arg(m_rule->prepareScript->location.column()) .arg(str); e += QString::fromLatin1(" was already defined in: %1:%2:%3 %4\n") .arg(outputArtifact->transformer->rule->prepareScript->location.filePath()) .arg(outputArtifact->transformer->rule->prepareScript->location.line()) .arg(outputArtifact->transformer->rule->prepareScript->location.column()) .arg(str); throw ErrorInfo(e); } outputArtifact->clearTimestamp(); m_invalidatedArtifacts += outputArtifact; } else { outputArtifact = new Artifact; outputArtifact->artifactType = Artifact::Generated; outputArtifact->setFilePath(outputPath); insertArtifact(m_product, outputArtifact, m_logger); m_createdArtifacts += outputArtifact; } outputArtifact->setFileTags( fileTags.isEmpty() ? m_product->fileTagsForFileName(outputArtifact->fileName()) : fileTags); outputArtifact->alwaysUpdated = alwaysUpdated; outputArtifact->properties = m_product->moduleProperties; for (int i = 0; i < m_product->artifactProperties.count(); ++i) { const ArtifactPropertiesConstPtr &props = m_product->artifactProperties.at(i); if (outputArtifact->fileTags().matches(props->fileTagsFilter())) { outputArtifact->properties = props->propertyMap(); break; } } // Let a positive value of qbs.install imply the file tag "installable". if (outputArtifact->properties->qbsPropertyValue(QLatin1String("install")).toBool()) outputArtifact->addFileTag("installable"); foreach (Artifact *inputArtifact, inputArtifacts) { QBS_CHECK(outputArtifact != inputArtifact); loggedConnect(outputArtifact, inputArtifact, m_logger); } outputArtifact->transformer = m_transformer; m_transformer->outputs.insert(outputArtifact); QBS_CHECK(m_rule->multiplex || m_transformer->inputs.count() == 1); return outputArtifact; } QList RulesApplicator::runOutputArtifactsScript(const ArtifactSet &inputArtifacts, const QScriptValueList &args) { QList lst; QScriptValue fun = engine()->evaluate(m_rule->outputArtifactsScript->sourceCode); if (!fun.isFunction()) throw ErrorInfo(QLatin1String("Function expected."), m_rule->outputArtifactsScript->location); QScriptValue res = fun.call(QScriptValue(), args); if (res.isError() || engine()->hasUncaughtException()) throw ErrorInfo(Tr::tr("Error while calling Rule.outputArtifacts: %1").arg(res.toString()), m_rule->outputArtifactsScript->location); if (!res.isArray()) throw ErrorInfo(Tr::tr("Rule.outputArtifacts must return an array of objects."), m_rule->outputArtifactsScript->location); const quint32 c = res.property(QLatin1String("length")).toUInt32(); for (quint32 i = 0; i < c; ++i) lst += createOutputArtifactFromScriptValue(res.property(i), inputArtifacts); return lst; } class ArtifactBindingsExtractor { typedef QPair NameValuePair; QList m_propertyValues; static QSet getArtifactItemPropertyNames() { QSet s; foreach (const PropertyDeclaration &pd, BuiltinDeclarations::instance().declarationsForType( QLatin1String("Artifact")).properties()) { s.insert(pd.name()); } s.insert(QLatin1String("explicitlyDependsOn")); return s; } void extractPropertyValues(const QScriptValue &obj, QStringList fullName = QStringList()) { QScriptValueIterator svit(obj); while (svit.hasNext()) { svit.next(); const QString name = svit.name(); if (fullName.isEmpty()) { // Ignore property names that are part of the Artifact item. static const QSet artifactItemPropertyNames = getArtifactItemPropertyNames(); if (artifactItemPropertyNames.contains(name)) continue; } const QScriptValue value = svit.value(); fullName.append(name); if (value.isObject() && !value.isArray() && !value.isError() && !value.isRegExp()) extractPropertyValues(value, fullName); else m_propertyValues.append(NameValuePair(fullName, value.toVariant())); fullName.removeLast(); } } public: ArtifactBindingsExtractor() { } void apply(Artifact *outputArtifact, const QScriptValue &obj) { extractPropertyValues(obj); if (m_propertyValues.isEmpty()) return; outputArtifact->properties = outputArtifact->properties->clone(); QVariantMap artifactCfg = outputArtifact->properties->value(); foreach (const NameValuePair &nvp, m_propertyValues) { const QStringList valuePath = findValuePath(artifactCfg, nvp.first); if (valuePath.isEmpty()) { throw ErrorInfo(Tr::tr("Cannot set module property %1 on artifact %2.") .arg(nvp.first.join(QLatin1Char('.')), outputArtifact->filePath())); } setConfigProperty(artifactCfg, valuePath, nvp.second); } outputArtifact->properties->setValue(artifactCfg); } QStringList findValuePath(const QVariantMap &cfg, const QStringList &nameParts) { QStringList tmp = nameParts; const QString propertyName = tmp.takeLast(); const QString moduleName = tmp.join(QLatin1Char('.')); const QStringList modulePath = findModulePath(cfg, moduleName); if (modulePath.isEmpty()) return modulePath; return QStringList(modulePath) << propertyName; } QStringList findModulePath(const QVariantMap &cfg, const QString &moduleName) { typedef QPair MapAndPath; QQueue q; q.enqueue(MapAndPath(cfg.value(QLatin1String("modules")).toMap(), QStringList(QLatin1String("modules")))); do { const MapAndPath current = q.takeFirst(); const QVariantMap &mod = current.first; for (QVariantMap::const_iterator it = mod.constBegin(); it != mod.constEnd(); ++it) { const QVariantMap m = it.value().toMap(); const QStringList currentPath = QStringList(current.second) << it.key(); if (it.key() == moduleName) return currentPath; q.enqueue(MapAndPath(m.value(QLatin1String("modules")).toMap(), QStringList(currentPath) << QLatin1String("modules"))); } } while (!q.isEmpty()); return QStringList(); } }; Artifact *RulesApplicator::createOutputArtifactFromScriptValue(const QScriptValue &obj, const ArtifactSet &inputArtifacts) { if (!obj.isObject()) { throw ErrorInfo(Tr::tr("Elements of the Rule.outputArtifacts array must be " "of Object type."), m_rule->outputArtifactsScript->location); } const QString filePath = FileInfo::resolvePath(m_product->buildDirectory(), obj.property(QLatin1String("filePath")).toVariant().toString()); const FileTags fileTags = FileTags::fromStringList( obj.property(QLatin1String("fileTags")).toVariant().toStringList()); const QVariant alwaysUpdatedVar = obj.property(QLatin1String("alwaysUpdated")).toVariant(); const bool alwaysUpdated = alwaysUpdatedVar.isValid() ? alwaysUpdatedVar.toBool() : true; Artifact *output = createOutputArtifact(filePath, fileTags, alwaysUpdated, inputArtifacts); const FileTags explicitlyDependsOn = FileTags::fromStringList( obj.property(QLatin1String("explicitlyDependsOn")).toVariant().toStringList()); foreach (const FileTag &tag, explicitlyDependsOn) { foreach (Artifact *dependency, m_product->lookupArtifactsByFileTag(tag)) { loggedConnect(output, dependency, m_logger); } } ArtifactBindingsExtractor().apply(output, obj); return output; } QString RulesApplicator::resolveOutPath(const QString &path) const { QString buildDir = m_product->topLevelProject()->buildDirectory; QString result = FileInfo::resolvePath(buildDir, path); result = QDir::cleanPath(result); return result; } RulesEvaluationContextPtr RulesApplicator::evalContext() const { return m_product->topLevelProject()->buildData->evaluationContext; } ScriptEngine *RulesApplicator::engine() const { return evalContext()->engine(); } QScriptValue RulesApplicator::scope() const { return evalContext()->scope(); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/rulesapplicator.h000066400000000000000000000073441266132464200235700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_RULESAPPLICATOR_H #define QBS_RULESAPPLICATOR_H #include "artifactset.h" #include "forward_decls.h" #include "nodeset.h" #include #include #include #include #include #include namespace qbs { namespace Internal { class BuildGraphNode; class QtMocScanner; class ScriptEngine; class RulesApplicator { public: RulesApplicator(const ResolvedProductPtr &product, const Logger &logger); ~RulesApplicator(); void applyRuleInEvaluationContext(const RuleConstPtr &rule, const ArtifactSet &inputArtifacts); const NodeSet &createdArtifacts() const { return m_createdArtifacts; } const NodeSet &invalidatedArtifacts() const { return m_invalidatedArtifacts; } void applyRule(const RuleConstPtr &rule, const ArtifactSet &inputArtifacts); static void handleRemovedRuleOutputs(const ArtifactSet &inputArtifacts, ArtifactSet artifactsToRemove, const Logger &logger); private: void doApply(const ArtifactSet &inputArtifacts, QScriptValue &prepareScriptContext); ArtifactSet collectOldOutputArtifacts(const ArtifactSet &inputArtifacts) const; Artifact *createOutputArtifactFromRuleArtifact(const RuleArtifactConstPtr &ruleArtifact, const ArtifactSet &inputArtifacts, QSet *outputFilePaths); Artifact *createOutputArtifact(const QString &filePath, const FileTags &fileTags, bool alwaysUpdated, const ArtifactSet &inputArtifacts); QList runOutputArtifactsScript(const ArtifactSet &inputArtifacts, const QScriptValueList &args); Artifact *createOutputArtifactFromScriptValue(const QScriptValue &obj, const ArtifactSet &inputArtifacts); QString resolveOutPath(const QString &path) const; RulesEvaluationContextPtr evalContext() const; ScriptEngine *engine() const; QScriptValue scope() const; const ResolvedProductPtr m_product; NodeSet m_createdArtifacts; NodeSet m_invalidatedArtifacts; RuleConstPtr m_rule; ArtifactSet m_completeInputSet; TransformerPtr m_transformer; QtMocScanner *m_mocScanner; Logger m_logger; }; } // namespace Internal } // namespace qbs #endif // QBS_RULESAPPLICATOR_H qbs-src-1.4.5/src/lib/corelib/buildgraph/rulesevaluationcontext.cpp000066400000000000000000000073121266132464200255340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "rulesevaluationcontext.h" #include "artifact.h" #include "command.h" #include "transformer.h" #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { RulesEvaluationContext::RulesEvaluationContext(const Logger &logger) : m_engine(new ScriptEngine(logger)), m_observer(0), m_initScopeCalls(0) { m_prepareScriptScope = m_engine->newObject(); ProcessCommand::setupForJavaScript(m_prepareScriptScope); JavaScriptCommand::setupForJavaScript(m_prepareScriptScope); } RulesEvaluationContext::~RulesEvaluationContext() { delete m_engine; } bool RulesEvaluationContext::isActive() const { return m_initScopeCalls > 0; } void RulesEvaluationContext::initializeObserver(const QString &description, int maximumProgress) { if (m_observer) m_observer->initialize(description, maximumProgress); } void RulesEvaluationContext::incrementProgressValue() { if (m_observer) m_observer->incrementProgressValue(); } void RulesEvaluationContext::checkForCancelation() { if (Q_UNLIKELY(m_observer && m_observer->canceled())) throw ErrorInfo(Tr::tr("Build canceled.")); } void RulesEvaluationContext::initScope() { if (m_initScopeCalls++ > 0) return; m_engine->setProperty("lastSetupProject", QVariant()); m_engine->setProperty("lastSetupProduct", QVariant()); m_engine->clearImportsCache(); m_engine->pushContext(); m_scope = m_engine->newObject(); m_scope.setPrototype(m_prepareScriptScope); m_engine->currentContext()->pushScope(m_scope); } void RulesEvaluationContext::cleanupScope() { QBS_CHECK(m_initScopeCalls > 0); if (--m_initScopeCalls > 0) return; m_scope = QScriptValue(); m_engine->currentContext()->popScope(); m_engine->popContext(); } RulesEvaluationContext::Scope::Scope(RulesEvaluationContext *evalContext) : m_evalContext(evalContext) { evalContext->initScope(); } RulesEvaluationContext::Scope::~Scope() { m_evalContext->cleanupScope(); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/rulesevaluationcontext.h000066400000000000000000000054741266132464200252100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_RULESEVALUATIONCONTEXT_H #define QBS_RULESEVALUATIONCONTEXT_H #include #include #include #include #include namespace qbs { namespace Internal { class Logger; class ProgressObserver; class ScriptEngine; class RulesEvaluationContext { public: RulesEvaluationContext(const Logger &logger); ~RulesEvaluationContext(); class Scope { public: Scope(RulesEvaluationContext *evalContext); ~Scope(); private: RulesEvaluationContext * const m_evalContext; }; ScriptEngine *engine() const { return m_engine; } QScriptValue scope() const { return m_scope; } bool isActive() const; void setObserver(ProgressObserver *observer) { m_observer = observer; } ProgressObserver *observer() const { return m_observer; } void initializeObserver(const QString &description, int maximumProgress); void incrementProgressValue(); void checkForCancelation(); private: friend class Scope; void initScope(); void cleanupScope(); ScriptEngine * const m_engine; ProgressObserver *m_observer; unsigned int m_initScopeCalls; QScriptValue m_scope; QScriptValue m_prepareScriptScope; }; } // namespace Internal } // namespace qbs #endif // QBS_RULESEVALUATIONCONTEXT_H qbs-src-1.4.5/src/lib/corelib/buildgraph/scanresultcache.cpp000066400000000000000000000046001266132464200240510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "scanresultcache.h" #include namespace qbs { namespace Internal { ScanResultCache::Dependency::Dependency(const QString &filePath) { FileInfo::splitIntoDirectoryAndFileName(filePath, &m_dirPath, &m_fileName); m_isClean = !m_dirPath.contains(QLatin1Char('.')) && !m_dirPath.contains(QLatin1String("//")); } ScanResultCache::Result ScanResultCache::value(const void *scanner, const QString &fileName) const { return m_data[scanner][fileName]; } void ScanResultCache::insert(const void *scanner, const QString &fileName, const ScanResultCache::Result &value) { m_data[scanner].insert(fileName, value); } void ScanResultCache::remove(const QString &fileName) { ScanResultCacheData::iterator i = m_data.begin(); while (i != m_data.end()) { i.value().remove(fileName); ++i; } } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/scanresultcache.h000066400000000000000000000054421266132464200235230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_SCANRESULTCACHE_H #define QBS_SCANRESULTCACHE_H #include #include #include #include namespace qbs { namespace Internal { class ScanResultCache { public: class Dependency { public: Dependency() : m_isClean(true) {} Dependency(const QString &filePath); QString filePath() const { return m_dirPath.isEmpty() ? m_fileName : m_dirPath + QLatin1Char('/') + m_fileName; } const QString &dirPath() const { return m_dirPath; } const QString &fileName() const { return m_fileName; } bool isClean() const { return m_isClean; } private: QString m_dirPath; QString m_fileName; bool m_isClean; }; class Result { public: Result() : valid(false) {} QVector deps; FileTags additionalFileTags; bool valid; }; Result value(const void* scanner, const QString &fileName) const; void insert(const void* scanner, const QString &fileName, const Result &value); void remove(const QString &fileName); private: typedef QHash > ScanResultCacheData; ScanResultCacheData m_data; }; } // namespace qbs } // namespace qbs #endif // QBS_SCANRESULTCACHE_H qbs-src-1.4.5/src/lib/corelib/buildgraph/timestampsupdater.cpp000066400000000000000000000061021266132464200244540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "timestampsupdater.h" #include "artifact.h" #include "artifactvisitor.h" #include "productbuilddata.h" #include "projectbuilddata.h" #include #include #include #include #include namespace qbs { namespace Internal { class TimestampsUpdateVisitor : public ArtifactVisitor { public: TimestampsUpdateVisitor() : ArtifactVisitor(Artifact::Generated), m_now(FileTime::currentTime()) {} void visitProduct(const ResolvedProductConstPtr &product) { QBS_CHECK(product->buildData); ArtifactVisitor::visitProduct(product); // For target artifacts, we have to update the on-disk timestamp, because // the executor will look at it. foreach (Artifact * const targetArtifact, product->targetArtifacts()) { if (FileInfo(targetArtifact->filePath()).exists()) QFile(targetArtifact->filePath()).open(QIODevice::WriteOnly | QIODevice::Append); } } private: void doVisit(Artifact *artifact) { if (FileInfo(artifact->filePath()).exists()) artifact->setTimestamp(m_now); } FileTime m_now; }; void TimestampsUpdater::updateTimestamps(const TopLevelProjectPtr &project, const QList &products, const Logger &logger) { TimestampsUpdateVisitor v; foreach (const ResolvedProductPtr &product, products) v.visitProduct(product); project->buildData->isDirty = !products.isEmpty(); project->store(logger); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/timestampsupdater.h000066400000000000000000000036421266132464200241270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef TIMESTAMPSUPDATER_H #define TIMESTAMPSUPDATER_H #include #include namespace qbs { namespace Internal { class Logger; class TimestampsUpdater { public: void updateTimestamps(const TopLevelProjectPtr &project, const QList &products, const Logger &logger); }; } // namespace Internal } // namespace qbs #endif // TIMESTAMPSUPDATER_H qbs-src-1.4.5/src/lib/corelib/buildgraph/transformer.cpp000066400000000000000000000310061266132464200232440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "transformer.h" #include "artifact.h" #include "command.h" #include "rulesevaluationcontext.h" #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { Transformer::Transformer() { } Transformer::~Transformer() { } static QScriptValue js_baseName(QScriptContext *ctx, QScriptEngine *engine, void *arg) { Q_UNUSED(ctx); Q_UNUSED(engine); Artifact *artifact = reinterpret_cast(arg); return QScriptValue(FileInfo::baseName(artifact->filePath())); } static QScriptValue js_completeBaseName(QScriptContext *ctx, QScriptEngine *engine, void *arg) { Q_UNUSED(ctx); Q_UNUSED(engine); Artifact *artifact = reinterpret_cast(arg); return QScriptValue(FileInfo::completeBaseName(artifact->filePath())); } static QScriptValue js_baseDir(QScriptContext *ctx, QScriptEngine *engine, void *arg) { Q_UNUSED(ctx); Q_UNUSED(engine); Artifact *artifact = reinterpret_cast(arg); QString basedir; if (artifact->artifactType == Artifact::SourceFile) { QDir sourceDir(artifact->product->sourceDirectory); basedir = FileInfo::path(sourceDir.relativeFilePath(artifact->filePath())); } else { QDir buildDir(artifact->product->buildDirectory()); basedir = FileInfo::path(buildDir.relativeFilePath(artifact->filePath())); } return basedir; } static void setArtifactProperty(QScriptValue &obj, const QString &name, QScriptEngine::FunctionWithArgSignature func, Artifact *artifact) { obj.setProperty(name, obj.engine()->newFunction(func, (void *)artifact), QScriptValue::PropertyGetter); } QScriptValue Transformer::translateFileConfig(QScriptEngine *scriptEngine, Artifact *artifact, const QString &defaultModuleName) { QScriptValue obj = scriptEngine->newObject(); attachPointerTo(obj, artifact); ModuleProperties::init(obj, artifact); obj.setProperty(QLatin1String("fileName"), artifact->fileName()); obj.setProperty(QLatin1String("filePath"), artifact->filePath()); setArtifactProperty(obj, QLatin1String("baseName"), js_baseName, artifact); setArtifactProperty(obj, QLatin1String("completeBaseName"), js_completeBaseName, artifact); setArtifactProperty(obj, QLatin1String("baseDir"), js_baseDir, artifact); const QStringList fileTags = artifact->fileTags().toStringList(); obj.setProperty(QLatin1String("fileTags"), scriptEngine->toScriptValue(fileTags)); if (!defaultModuleName.isEmpty()) obj.setProperty(QLatin1String("moduleName"), defaultModuleName); return obj; } static bool compareByFilePath(const Artifact *a1, const Artifact *a2) { return a1->filePath() < a2->filePath(); } QScriptValue Transformer::translateInOutputs(QScriptEngine *scriptEngine, const ArtifactSet &artifacts, const QString &defaultModuleName) { typedef QMap > TagArtifactsMap; TagArtifactsMap tagArtifactsMap; foreach (Artifact *artifact, artifacts) foreach (const FileTag &fileTag, artifact->fileTags()) tagArtifactsMap[fileTag.toString()].append(artifact); for (TagArtifactsMap::Iterator it = tagArtifactsMap.begin(); it != tagArtifactsMap.end(); ++it) std::sort(it.value().begin(), it.value().end(), compareByFilePath); QScriptValue jsTagFiles = scriptEngine->newObject(); for (TagArtifactsMap::const_iterator tag = tagArtifactsMap.constBegin(); tag != tagArtifactsMap.constEnd(); ++tag) { const QList &artifacts = tag.value(); QScriptValue jsFileConfig = scriptEngine->newArray(artifacts.count()); int i=0; foreach (Artifact *artifact, artifacts) { jsFileConfig.setProperty(i++, translateFileConfig(scriptEngine, artifact, defaultModuleName)); } jsTagFiles.setProperty(tag.key(), jsFileConfig); } return jsTagFiles; } ResolvedProductPtr Transformer::product() const { if (outputs.isEmpty()) return ResolvedProductPtr(); return (*outputs.begin())->product; } void Transformer::setupInputs(QScriptValue targetScriptValue, const ArtifactSet &inputs, const QString &defaultModuleName) { QScriptEngine *const scriptEngine = targetScriptValue.engine(); QScriptValue scriptValue = translateInOutputs(scriptEngine, inputs, defaultModuleName); targetScriptValue.setProperty(QLatin1String("inputs"), scriptValue); QScriptValue inputScriptValue; if (inputs.count() == 1) { Artifact *input = *inputs.begin(); const FileTags &fileTags = input->fileTags(); QBS_ASSERT(!fileTags.isEmpty(), return); QScriptValue inputsForFileTag = scriptValue.property(fileTags.begin()->toString()); inputScriptValue = inputsForFileTag.property(0); } targetScriptValue.setProperty(QLatin1String("input"), inputScriptValue); } void Transformer::setupInputs(QScriptValue targetScriptValue) { setupInputs(targetScriptValue, inputs, rule->module->name); } void Transformer::setupOutputs(QScriptEngine *scriptEngine, QScriptValue targetScriptValue) { const QString &defaultModuleName = rule->module->name; QScriptValue scriptValue = translateInOutputs(scriptEngine, outputs, defaultModuleName); targetScriptValue.setProperty(QLatin1String("outputs"), scriptValue); QScriptValue outputScriptValue; if (outputs.count() == 1) { Artifact *output = *outputs.begin(); const FileTags &fileTags = output->fileTags(); QBS_ASSERT(!fileTags.isEmpty(), return); QScriptValue outputsForFileTag = scriptValue.property(fileTags.begin()->toString()); outputScriptValue = outputsForFileTag.property(0); } targetScriptValue.setProperty(QLatin1String("output"), outputScriptValue); } static AbstractCommandPtr createCommandFromScriptValue(const QScriptValue &scriptValue, const CodeLocation &codeLocation) { AbstractCommandPtr cmdBase; if (scriptValue.isUndefined() || !scriptValue.isValid()) return cmdBase; QString className = scriptValue.property(QLatin1String("className")).toString(); if (className == QLatin1String("Command")) cmdBase = ProcessCommand::create(); else if (className == QLatin1String("JavaScriptCommand")) cmdBase = JavaScriptCommand::create(); if (cmdBase) cmdBase->fillFromScriptValue(&scriptValue, codeLocation); return cmdBase; } void Transformer::createCommands(const ScriptFunctionConstPtr &script, const RulesEvaluationContextPtr &evalContext, const QScriptValueList &args) { ScriptEngine * const engine = evalContext->engine(); if (!script->scriptFunction.isValid() || script->scriptFunction.engine() != engine) { script->scriptFunction = engine->evaluate(script->sourceCode); if (Q_UNLIKELY(!script->scriptFunction.isFunction())) throw ErrorInfo(Tr::tr("Invalid prepare script."), script->location); } QScriptValue scriptValue = script->scriptFunction.call(QScriptValue(), args); propertiesRequestedInPrepareScript = engine->propertiesRequestedInScript(); propertiesRequestedFromArtifactInPrepareScript = engine->propertiesRequestedFromArtifact(); engine->clearRequestedProperties(); if (Q_UNLIKELY(engine->hasErrorOrException(scriptValue))) throw ErrorInfo(Tr::tr("evaluating prepare script: ") + engine->lastErrorString(scriptValue), CodeLocation(script->location.filePath(), script->location.line() + engine->uncaughtExceptionLineNumber() - 1)); commands.clear(); if (scriptValue.isArray()) { const int count = scriptValue.property(QLatin1String("length")).toInt32(); for (qint32 i = 0; i < count; ++i) { QScriptValue item = scriptValue.property(i); if (item.isValid() && !item.isUndefined()) { const AbstractCommandPtr cmd = createCommandFromScriptValue(item, script->location); if (cmd) commands += cmd; } } } else { const AbstractCommandPtr cmd = createCommandFromScriptValue(scriptValue, script->location); if (cmd) commands += cmd; } } static void restorePropertyList(PersistentPool &pool, PropertySet &list) { int count; pool.stream() >> count; list.reserve(count); while (--count >= 0) { Property p; p.moduleName = pool.idLoadString(); p.propertyName = pool.idLoadString(); int k; pool.stream() >> p.value >> k; p.kind = static_cast(k); list += p; } } void Transformer::load(PersistentPool &pool) { rule = pool.idLoadS(); pool.loadContainer(inputs); pool.loadContainer(outputs); restorePropertyList(pool, propertiesRequestedInPrepareScript); restorePropertyList(pool, propertiesRequestedInCommands); int count; pool.stream() >> count; propertiesRequestedFromArtifactInPrepareScript.reserve(count); while (--count >= 0) { const QString artifactName = pool.idLoadString(); int listCount; pool.stream() >> listCount; PropertySet list; list.reserve(listCount); while (--listCount >= 0) { Property p; p.moduleName = pool.idLoadString(); p.propertyName = pool.idLoadString(); pool.stream() >> p.value; p.kind = Property::PropertyInModule; list += p; } propertiesRequestedFromArtifactInPrepareScript.insert(artifactName, list); } commands = loadCommandList(pool); } static void storePropertyList(PersistentPool &pool, const PropertySet &list) { pool.stream() << list.count(); foreach (const Property &p, list) { pool.storeString(p.moduleName); pool.storeString(p.propertyName); pool.stream() << p.value << static_cast(p.kind); } } void Transformer::store(PersistentPool &pool) const { pool.store(rule); pool.storeContainer(inputs); pool.storeContainer(outputs); storePropertyList(pool, propertiesRequestedInPrepareScript); storePropertyList(pool, propertiesRequestedInCommands); pool.stream() << propertiesRequestedFromArtifactInPrepareScript.count(); for (QHash::ConstIterator it = propertiesRequestedFromArtifactInPrepareScript.constBegin(); it != propertiesRequestedFromArtifactInPrepareScript.constEnd(); ++it) { pool.storeString(it.key()); const PropertySet &properties = it.value(); pool.stream() << properties.count(); foreach (const Property &p, properties) { pool.storeString(p.moduleName); pool.storeString(p.propertyName); pool.stream() << p.value; // kind is always PropertyInModule } } storeCommandList(commands, pool); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/transformer.h000066400000000000000000000066241266132464200227210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_TRANSFORMER_H #define QBS_TRANSFORMER_H #include "artifactset.h" #include "forward_decls.h" #include #include #include #include #include namespace qbs { namespace Internal { class Artifact; class AbstractCommand; class Rule; class ScriptEngine; class Transformer : public PersistentObject { public: static TransformerPtr create() { return TransformerPtr(new Transformer); } ~Transformer(); ArtifactSet inputs; // Subset of "children of all outputs". ArtifactSet outputs; RuleConstPtr rule; QList commands; PropertySet propertiesRequestedInPrepareScript; PropertySet propertiesRequestedInCommands; QHash propertiesRequestedFromArtifactInPrepareScript; static QScriptValue translateFileConfig(QScriptEngine *scriptEngine, Artifact *artifact, const QString &defaultModuleName); static QScriptValue translateInOutputs(QScriptEngine *scriptEngine, const ArtifactSet &artifacts, const QString &defaultModuleName); ResolvedProductPtr product() const; static void setupInputs(QScriptValue targetScriptValue, const ArtifactSet &inputs, const QString &defaultModuleName); void setupInputs(QScriptValue targetScriptValue); void setupOutputs(QScriptEngine *scriptEngine, QScriptValue targetScriptValue); void createCommands(const ScriptFunctionConstPtr &script, const RulesEvaluationContextPtr &evalContext, const QScriptValueList &args); private: Transformer(); void load(PersistentPool &pool); void store(PersistentPool &pool) const; }; } // namespace Internal } // namespace qbs #endif // QBS_TRANSFORMER_H qbs-src-1.4.5/src/lib/corelib/buildgraph/tst_buildgraph.cpp000066400000000000000000000105731266132464200237230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "tst_buildgraph.h" #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { const TopLevelProjectPtr project = TopLevelProject::create(); TestBuildGraph::TestBuildGraph(ILogSink *logSink) : m_logSink(logSink) { project->buildData.reset(new ProjectBuildData); } void TestBuildGraph::initTestCase() { } void TestBuildGraph::cleanupTestCase() { } bool TestBuildGraph::cycleDetected(const ResolvedProductConstPtr &product) { try { CycleDetector(Logger(m_logSink)).visitProduct(product); return false; } catch (const ErrorInfo &) { return true; } } ResolvedProductConstPtr TestBuildGraph::productWithDirectCycle() { const ResolvedProductPtr product = ResolvedProduct::create(); product->project = project; product->buildData.reset(new ProductBuildData); Artifact * const root = new Artifact; root->product = product; Artifact * const child = new Artifact; child->product = product; product->buildData->roots.insert(root); product->buildData->nodes << root << child; qbs::Internal::connect(root, child); qbs::Internal::connect(child, root); return product; } ResolvedProductConstPtr TestBuildGraph::productWithLessDirectCycle() { const ResolvedProductPtr product = ResolvedProduct::create(); product->project = project; product->buildData.reset(new ProductBuildData); Artifact * const root = new Artifact; Artifact * const child = new Artifact; Artifact * const grandchild = new Artifact; root->product = product; child->product = product; grandchild->product = product; product->buildData->roots << root; product->buildData->nodes << root << child << grandchild; qbs::Internal::connect(root, child); qbs::Internal::connect(child, grandchild); qbs::Internal::connect(grandchild, root); return product; } // root appears as a child, but in a different tree ResolvedProductConstPtr TestBuildGraph::productWithNoCycle() { const ResolvedProductPtr product = ResolvedProduct::create(); product->project = project; product->buildData.reset(new ProductBuildData); Artifact * const root = new Artifact; Artifact * const root2 = new Artifact; root->product = product; root2->product = product; product->buildData->roots << root << root2; product->buildData->nodes << root << root2; qbs::Internal::connect(root2, root); return product; } void TestBuildGraph::testCycle() { QVERIFY(cycleDetected(productWithDirectCycle())); QVERIFY(cycleDetected(productWithLessDirectCycle())); QVERIFY(!cycleDetected(productWithNoCycle())); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/buildgraph/tst_buildgraph.h000066400000000000000000000044341266132464200233670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef TST_BUILDGRAPH_H #define TST_BUILDGRAPH_H #include #include #include #include #include #include namespace qbs { namespace Internal { class QBS_EXPORT TestBuildGraph : public QObject { Q_OBJECT public: TestBuildGraph(ILogSink *logSink); private slots: void initTestCase(); void cleanupTestCase(); void testCycle(); private: ResolvedProductConstPtr productWithDirectCycle(); ResolvedProductConstPtr productWithLessDirectCycle(); ResolvedProductConstPtr productWithNoCycle(); bool cycleDetected(const ResolvedProductConstPtr &product); ILogSink * const m_logSink; }; } // namespace Internal } // namespace qbs #endif // TST_BUILDGRAPH_H qbs-src-1.4.5/src/lib/corelib/corelib.pro000066400000000000000000000015031266132464200202150ustar00rootroot00000000000000TARGET = qbscore include(../library.pri) QT += script qbs_enable_unit_tests:QT += testlib qbs_enable_project_file_updates: QT += gui INCLUDEPATH += $$PWD CONFIG += depend_includepath DEFINES += QT_CREATOR QML_BUILD_STATIC_LIB # needed for QmlJS DEFINES += SRCDIR=\\\"$$PWD\\\" include(api/api.pri) include(buildgraph/buildgraph.pri) include(generators/generators.pri) include(jsextensions/jsextensions.pri) include(language/language.pri) include(logging/logging.pri) include(parser/parser.pri) include(tools/tools.pri) win32:LIBS += -lpsapi freebsd:LIBS += -lutil HEADERS += \ qbs.h !qbs_no_dev_install { qbs_h.files = qbs.h qbs_h.path = $${QBS_INSTALL_PREFIX}/include/qbs use_pri.files = use_installed_corelib.pri ../../../qbs_version.pri use_pri.path = $${qbs_h.path} INSTALLS += qbs_h use_pri } qbs-src-1.4.5/src/lib/corelib/corelib.qbs000066400000000000000000000305231266132464200202060ustar00rootroot00000000000000import qbs 1.0 import QbsFunctions QbsLibrary { Depends { name: "cpp" } Depends { name: "Qt"; submodules: ["script", "xml"] } Depends { condition: project.enableProjectFileUpdates; name: "Qt.gui" } Depends { condition: project.enableUnitTests; name: "Qt.test" } name: "qbscore" cpp.includePaths: base.concat([ ".", "../.." // for the plugin headers ]) property stringList projectFileUpdateDefines: project.enableProjectFileUpdates ? ["QBS_ENABLE_PROJECT_FILE_UPDATES"] : [] cpp.defines: base.concat([ "QBS_VERSION=\"" + version + "\"", "QT_CREATOR", "QML_BUILD_STATIC_LIB", // needed for QmlJS "SRCDIR=\"" + path + "\"" ]).concat(projectFileUpdateDefines) Properties { condition: qbs.targetOS.contains("windows") cpp.dynamicLibraries: base.concat(["Psapi"]) } Properties { condition: qbs.targetOS.contains("freebsd") cpp.dynamicLibraries: base.concat(["util"]) } cpp.dynamicLibraries: base Properties { condition: qbs.targetOS.contains("darwin") cpp.frameworks: "Foundation" } Group { name: product.name files: ["qbs.h"] qbs.install: project.installApiHeaders qbs.installDir: headerInstallPrefix } Group { name: "project file updating" condition: project.enableProjectFileUpdates prefix: "api/" files: [ "changeset.cpp", "changeset.h", "projectfileupdater.cpp", "projectfileupdater.h", "qmljsrewriter.cpp", "qmljsrewriter.h", ] } Group { name: "api" prefix: name + '/' files: [ "internaljobs.cpp", "internaljobs.h", "jobs.cpp", "languageinfo.cpp", "project.cpp", "project_p.h", "projectdata.cpp", "projectdata_p.h", "propertymap_p.h", "rulecommand.cpp", "rulecommand_p.h", "runenvironment.cpp", ] } Group { name: "public api headers" qbs.install: project.installApiHeaders qbs.installDir: headerInstallPrefix + "/api" prefix: "api/" files: [ "jobs.h", "languageinfo.h", "project.h", "projectdata.h", "rulecommand.h", "runenvironment.h" ] } Group { name: "buildgraph" prefix: name + '/' files: [ "abstractcommandexecutor.cpp", "abstractcommandexecutor.h", "artifact.cpp", "artifact.h", "artifactcleaner.cpp", "artifactcleaner.h", "artifactset.cpp", "artifactset.h", "artifactvisitor.cpp", "artifactvisitor.h", "buildgraph.cpp", "buildgraph.h", "buildgraphnode.cpp", "buildgraphnode.h", "buildgraphloader.cpp", "buildgraphloader.h", "buildgraphvisitor.h", "command.cpp", "command.h", "cycledetector.cpp", "cycledetector.h", "depscanner.cpp", "depscanner.h", "emptydirectoriesremover.cpp", "emptydirectoriesremover.h", "executor.cpp", "executor.h", "executorjob.cpp", "executorjob.h", "filedependency.cpp", "filedependency.h", "inputartifactscanner.cpp", "inputartifactscanner.h", "jscommandexecutor.cpp", "jscommandexecutor.h", "nodeset.cpp", "nodeset.h", "nodetreedumper.cpp", "nodetreedumper.h", "processcommandexecutor.cpp", "processcommandexecutor.h", "productbuilddata.cpp", "productbuilddata.h", "productinstaller.cpp", "productinstaller.h", "projectbuilddata.cpp", "projectbuilddata.h", "qtmocscanner.cpp", "qtmocscanner.h", "rescuableartifactdata.cpp", "rescuableartifactdata.h", "rulegraph.cpp", "rulegraph.h", "rulenode.cpp", "rulenode.h", "rulesapplicator.cpp", "rulesapplicator.h", "rulesevaluationcontext.cpp", "rulesevaluationcontext.h", "scanresultcache.cpp", "scanresultcache.h", "timestampsupdater.cpp", "timestampsupdater.h", "transformer.cpp", "transformer.h" ] } Group { name: "public buildgraph headers" qbs.install: project.installApiHeaders qbs.installDir: headerInstallPrefix + "/buildgraph" files: "buildgraph/forward_decls.h" } Group { name: "jsextensions" prefix: name + '/' files: [ "file.cpp", "file.h", "jsextensions.cpp", "jsextensions.h", "moduleproperties.cpp", "moduleproperties.h", "process.cpp", "process.h", "temporarydir.cpp", "temporarydir.h", "textfile.cpp", "textfile.h", "domxml.cpp", "domxml.h" ] } Group { name: "jsextensions (Darwin-specific)" prefix: "jsextensions/" condition: qbs.targetOS.contains("darwin") files: [ "propertylist.h", "propertylist.mm", "propertylistutils.h", "propertylistutils.mm" ] } Group { name: "language" prefix: name + '/' files: [ "artifactproperties.cpp", "artifactproperties.h", "asttools.cpp", "asttools.h", "builtindeclarations.cpp", "builtindeclarations.h", "builtinvalue.cpp", "builtinvalue.h", "deprecationinfo.h", "evaluationdata.h", "evaluator.cpp", "evaluator.h", "evaluatorscriptclass.cpp", "evaluatorscriptclass.h", "filecontext.cpp", "filecontext.h", "filecontextbase.cpp", "filecontextbase.h", "filetags.cpp", "filetags.h", "functiondeclaration.h", "identifiersearch.cpp", "identifiersearch.h", "item.cpp", "item.h", "itemdeclaration.cpp", "itemdeclaration.h", "itemobserver.h", "itempool.cpp", "itempool.h", "itemreader.cpp", "itemreader.h", "itemreaderastvisitor.cpp", "itemreaderastvisitor.h", "itemreadervisitorstate.cpp", "itemreadervisitorstate.h", "jsimports.h", "language.cpp", "language.h", "loader.cpp", "loader.h", "moduleloader.cpp", "moduleloader.h", "modulemerger.cpp", "modulemerger.h", "preparescriptobserver.cpp", "preparescriptobserver.h", "projectresolver.cpp", "projectresolver.h", "property.h", "propertydeclaration.cpp", "propertydeclaration.h", "propertymapinternal.cpp", "propertymapinternal.h", "qualifiedid.cpp", "qualifiedid.h", "resolvedfilecontext.cpp", "resolvedfilecontext.h", "scriptengine.cpp", "scriptengine.h", "scriptpropertyobserver.h", "value.cpp", "value.h" ] } Group { name: "public language headers" qbs.install: project.installApiHeaders qbs.installDir: headerInstallPrefix + "/language" files: "language/forward_decls.h" } Group { name: "logging" prefix: name + '/' files: [ "ilogsink.cpp", "logger.cpp", "logger.h", "translator.h" ] } Group { name: "public logging headers" qbs.install: project.installApiHeaders qbs.installDir: headerInstallPrefix + "/logging" files: "logging/ilogsink.h" } Group { name: "parser" prefix: name + '/' files: [ "qmlerror.cpp", "qmlerror.h", "qmljsast.cpp", "qmljsast_p.h", "qmljsastfwd_p.h", "qmljsastvisitor.cpp", "qmljsastvisitor_p.h", "qmljsengine_p.cpp", "qmljsengine_p.h", "qmljsglobal_p.h", "qmljsgrammar.cpp", "qmljsgrammar_p.h", "qmljskeywords_p.h", "qmljslexer.cpp", "qmljslexer_p.h", "qmljsmemorypool_p.h", "qmljsparser.cpp", "qmljsparser_p.h" ] } Group { name: "tools" prefix: name + '/' files: [ "architectures.cpp", "buildgraphlocker.cpp", "buildgraphlocker.h", "buildoptions.cpp", "cleanoptions.cpp", "codelocation.cpp", "commandechomode.cpp", "error.cpp", "executablefinder.cpp", "executablefinder.h", "fileinfo.cpp", "fileinfo.h", "filetime.h", "generateoptions.cpp", "hostosinfo.h", "id.cpp", "id.h", "installoptions.cpp", "persistence.cpp", "persistence.h", "persistentobject.h", "preferences.cpp", "processresult.cpp", "processresult_p.h", "processutils.cpp", "processutils.h", "profile.cpp", "progressobserver.cpp", "progressobserver.h", "projectgeneratormanager.cpp", "propertyfinder.cpp", "propertyfinder.h", "qbsassert.cpp", "qbsassert.h", "qttools.cpp", "qttools.h", "scannerpluginmanager.cpp", "scannerpluginmanager.h", "scripttools.cpp", "scripttools.h", "settings.cpp", "settingsmodel.cpp", "setupprojectparameters.cpp", "shellutils.cpp", "shellutils.h", "version.cpp", "version.h", "weakpointer.h" ] } Group { name: "public tools headers" prefix: "tools/" files: [ "architectures.h", "buildoptions.h", "cleanoptions.h", "codelocation.h", "commandechomode.h", "error.h", "generateoptions.h", "installoptions.h", "preferences.h", "processresult.h", "profile.h", "projectgeneratormanager.h", "qbs_export.h", "settings.h", "settingsmodel.h", "setupprojectparameters.h", ] qbs.install: project.installApiHeaders qbs.installDir: headerInstallPrefix + "/tools" } Group { condition: qbs.targetOS.contains("windows") name: "tools (Windows)" prefix: "tools/" files: [ "filetime_win.cpp" ] } Group { condition: qbs.targetOS.contains("unix") name: "tools (Unix)" prefix: "tools/" files: [ "filetime_unix.cpp" ] } Group { name: "use_installed.pri" files: [ "use_installed_corelib.pri", "../../../qbs_version.pri" ] qbs.install: project.installApiHeaders qbs.installDir: headerInstallPrefix } Group { condition: project.enableUnitTests name: "tests" cpp.defines: outer.filter(function(def) { return def !== "QT_NO_CAST_FROM_ASCII"; }) files: [ "buildgraph/tst_buildgraph.cpp", "buildgraph/tst_buildgraph.h", "language/tst_language.cpp", "language/tst_language.h", "tools/tst_tools.h", "tools/tst_tools.cpp" ] } Export { Depends { name: "Qt"; submodules: ["script", "xml"] } cpp.defines: product.projectFileUpdateDefines } } qbs-src-1.4.5/src/lib/corelib/generators/000077500000000000000000000000001266132464200202265ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/generators/generator.h000066400000000000000000000054651266132464200223770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef GENERATORPLUGIN_H #define GENERATORPLUGIN_H #include #include #include namespace qbs { /*! * \class ProjectGenerator * \brief The \c ProjectGenerator class is an abstract base class for generators which generate * arbitrary output given a resolved Qbs project. */ class ProjectGenerator { public: virtual ~ProjectGenerator() { } /*! * Returns the name of the generator used to create the external build system files. */ virtual QString generatorName() const = 0; virtual void generate(const InstallOptions &installOptions) = 0; QList projects() const { return m_projects; } void addProject(const Project &project) { m_projects << project; } void addProjects(const QList &projects) { m_projects << projects; } void removeProject(const Project &project) { m_projects.removeOne(project); } void clearProjects() { m_projects.clear(); } protected: ProjectGenerator() { } private: QList m_projects; }; } // namespace qbs #ifdef __cplusplus extern "C" { #endif typedef qbs::ProjectGenerator **(*getGenerators_f)(); #ifdef __cplusplus } #endif #endif // GENERATORPLUGIN_H qbs-src-1.4.5/src/lib/corelib/generators/generators.pri000066400000000000000000000000431266132464200231100ustar00rootroot00000000000000HEADERS += \ $$PWD/generator.h qbs-src-1.4.5/src/lib/corelib/jsextensions/000077500000000000000000000000001266132464200206115ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/jsextensions/domxml.cpp000066400000000000000000000304211266132464200226150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 BogDan Vatra ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "domxml.h" #include #include namespace qbs { namespace Internal { void initializeJsExtensionXml(QScriptValue extensionObject) { QScriptEngine *engine = extensionObject.engine(); QScriptValue obj = engine->newQMetaObject(&XmlDomDocument::staticMetaObject, engine->newFunction(&XmlDomDocument::ctor)); extensionObject.setProperty(QLatin1String("XmlDomDocument"), obj); obj = engine->newQMetaObject(&XmlDomNode::staticMetaObject, engine->newFunction(&XmlDomNode::ctor)); extensionObject.setProperty(QLatin1String("XmlDomElement"), obj); } QScriptValue XmlDomDocument::ctor(QScriptContext *context, QScriptEngine *engine) { XmlDomDocument *xml = 0; switch (context->argumentCount()) { case 0: xml = new XmlDomDocument(context); break; case 1: xml = new XmlDomDocument(context, context->argument(0).toString()); break; default: return context->throwError(QLatin1String("DomXml(QString file = QLatin1String(\"\"))")); } QScriptValue obj = engine->newQObject(xml, QScriptEngine::ScriptOwnership); return obj; } QScriptValue XmlDomDocument::documentElement() { return engine()->newQObject(new XmlDomNode(m_domDocument.documentElement()), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomDocument::createElement(const QString &tagName) { return engine()->newQObject(new XmlDomNode(m_domDocument.createElement(tagName)), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomDocument::createCDATASection(const QString &value) { return engine()->newQObject(new XmlDomNode(m_domDocument.createCDATASection(value)), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomDocument::createTextNode(const QString &value) { return engine()->newQObject(new XmlDomNode(m_domDocument.createTextNode(value)), QScriptEngine::ScriptOwnership); } bool XmlDomDocument::setContent(const QString &content) { return m_domDocument.setContent(content); } QString XmlDomDocument::toString(int indent) { return m_domDocument.toString(indent); } void XmlDomDocument::save(const QString &filePath, int indent) { QFile f(filePath); if (!f.open(QIODevice::WriteOnly)) { context()->throwError(QString::fromLatin1("unable to open '%1'") .arg(filePath)); return; } QByteArray buff(m_domDocument.toByteArray(indent)); if (buff.size() != f.write(buff)) { context()->throwError(f.errorString()); f.close(); return; } f.close(); if (f.error() != QFile::NoError) context()->throwError(f.errorString()); } void XmlDomDocument::load(const QString &filePath) { QFile f(filePath); if (!f.open(QIODevice::ReadOnly)) { context()->throwError(QString::fromLatin1("unable to open '%1'") .arg(filePath)); return; } QString errorMsg; if (!m_domDocument.setContent(&f, &errorMsg)) { context()->throwError(errorMsg); return; } } XmlDomDocument::XmlDomDocument(QScriptContext *context, const QString &name):m_domDocument(name) { Q_UNUSED(context) m_domNode = m_domDocument; } QScriptValue XmlDomNode::ctor(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(context) return engine->newQObject(new XmlDomNode(), QScriptEngine::ScriptOwnership); } bool XmlDomNode::isElement() const { return m_domNode.isElement(); } bool XmlDomNode::isCDATASection() const { return m_domNode.isCDATASection(); } bool XmlDomNode::isText() const { return m_domNode.isText(); } QString XmlDomNode::attribute(const QString &name, const QString &defValue) { QDomElement el = m_domNode.toElement(); if (el.isNull()) { context()->throwError(QString::fromLatin1("Node '%1' is not an element node").arg(m_domNode.nodeName())); return defValue; } return el.attribute(name, defValue); } void XmlDomNode::setAttribute(const QString &name, const QString &value) { QDomElement el = m_domNode.toElement(); if (el.isNull()) { context()->throwError(QString::fromLatin1("Node '%1' is not an element node").arg(m_domNode.nodeName())); return; } el.setAttribute(name, value); } bool XmlDomNode::hasAttribute(const QString &name) const { QDomElement el = m_domNode.toElement(); if (el.isNull()) { context()->throwError(QString::fromLatin1("Node '%1' is not an element node").arg(m_domNode.nodeName())); return false; } return el.hasAttribute(name); } QString XmlDomNode::tagName() const { QDomElement el = m_domNode.toElement(); if (el.isNull()) { context()->throwError(QString::fromLatin1("Node '%1' is not an element node").arg(m_domNode.nodeName())); return QString(); } return el.tagName(); } void XmlDomNode::setTagName(const QString &name) { QDomElement el = m_domNode.toElement(); if (el.isNull()) { context()->throwError(QString::fromLatin1("Node '%1' is not an element node").arg(m_domNode.nodeName())); return; } el.setTagName(name); } QString XmlDomNode::text() const { QDomElement el = m_domNode.toElement(); if (el.isNull()) { context()->throwError(QString::fromLatin1("Node '%1' is not an element node").arg(m_domNode.nodeName())); return QString(); } return el.text(); } QString XmlDomNode::data() const { if (m_domNode.isText()) return m_domNode.toText().data(); if (m_domNode.isCDATASection()) return m_domNode.toCDATASection().data(); if (m_domNode.isCharacterData()) return m_domNode.toCharacterData().data(); context()->throwError(QString::fromLatin1("Node '%1' is not a character data node").arg(m_domNode.nodeName())); return QString(); } void XmlDomNode::setData(const QString &v) const { if (m_domNode.isText()) return m_domNode.toText().setData(v); if (m_domNode.isCDATASection()) return m_domNode.toCDATASection().setData(v); if (m_domNode.isCharacterData()) return m_domNode.toCharacterData().setData(v); context()->throwError(QString::fromLatin1("Node '%1' is not a character data node").arg(m_domNode.nodeName())); return; } void XmlDomNode::clear() { m_domNode.clear(); } bool XmlDomNode::hasAttributes() const { return m_domNode.hasAttributes(); } bool XmlDomNode::hasChildNodes() const { return m_domNode.hasChildNodes(); } QScriptValue XmlDomNode::parentNode() const { return engine()->newQObject(new XmlDomNode(m_domNode.parentNode()), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomNode::firstChild(const QString &tagName) { if (tagName.isEmpty()) return engine()->newQObject(new XmlDomNode(m_domNode.firstChild()), QScriptEngine::ScriptOwnership); return engine()->newQObject(new XmlDomNode(m_domNode.firstChildElement(tagName)), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomNode::lastChild(const QString &tagName) const { if (tagName.isEmpty()) return engine()->newQObject(new XmlDomNode(m_domNode.lastChild()), QScriptEngine::ScriptOwnership); return engine()->newQObject(new XmlDomNode(m_domNode.lastChildElement(tagName)), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomNode::previousSibling(const QString &tagName) const { if (tagName.isEmpty()) return engine()->newQObject(new XmlDomNode(m_domNode.previousSibling()), QScriptEngine::ScriptOwnership); return engine()->newQObject(new XmlDomNode(m_domNode.previousSiblingElement(tagName)), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomNode::nextSibling(const QString &tagName) const { if (tagName.isEmpty()) return engine()->newQObject(new XmlDomNode(m_domNode.nextSibling()), QScriptEngine::ScriptOwnership); return engine()->newQObject(new XmlDomNode(m_domNode.nextSiblingElement(tagName)), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomNode::appendChild(QScriptValue newChild) { XmlDomNode *newNode = qobject_cast(newChild.toQObject()); if (!newNode) { context()->throwError(QString::fromLatin1("First argument is not a XmlDomNode object")); return QScriptValue(); } return engine()->newQObject(new XmlDomNode(m_domNode.appendChild(newNode->m_domNode)), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomNode::insertBefore(const QScriptValue &newChild, const QScriptValue &refChild) { XmlDomNode *newNode = qobject_cast(newChild.toQObject()); if (!newNode) { context()->throwError(QString::fromLatin1("First argument is not a XmlDomNode object")); return QScriptValue(); } XmlDomNode *refNode = qobject_cast(refChild.toQObject()); if (!refNode) { context()->throwError(QString::fromLatin1("Second argument is not a XmlDomNode object")); return QScriptValue(); } return engine()->newQObject(new XmlDomNode(m_domNode.insertBefore(newNode->m_domNode, refNode->m_domNode)), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomNode::insertAfter(const QScriptValue &newChild, const QScriptValue &refChild) { XmlDomNode *newNode = qobject_cast(newChild.toQObject()); if (!newNode) { context()->throwError(QString::fromLatin1("First argument is not a XmlDomNode object")); return QScriptValue(); } XmlDomNode *refNode = qobject_cast(refChild.toQObject()); if (!refNode) { context()->throwError(QString::fromLatin1("Second argument is not a XmlDomNode object")); return QScriptValue(); } return engine()->newQObject(new XmlDomNode(m_domNode.insertAfter(newNode->m_domNode, refNode->m_domNode)), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomNode::replaceChild(const QScriptValue &newChild, const QScriptValue &oldChild) { XmlDomNode *newNode = qobject_cast(newChild.toQObject()); if (!newNode) { context()->throwError(QString::fromLatin1("First argument is not a XmlDomNode object")); return QScriptValue(); } XmlDomNode *oldNode = qobject_cast(oldChild.toQObject()); if (!oldNode) { context()->throwError(QString::fromLatin1("Second argument is not a XmlDomNode object")); return QScriptValue(); } return engine()->newQObject(new XmlDomNode(m_domNode.replaceChild(newNode->m_domNode, oldNode->m_domNode)), QScriptEngine::ScriptOwnership); } QScriptValue XmlDomNode::removeChild(const QScriptValue &oldChild) { XmlDomNode *oldNode = qobject_cast(oldChild.toQObject()); if (!oldNode) { context()->throwError(QString::fromLatin1("First argument is not a XmlDomNode object")); return QScriptValue(); } return engine()->newQObject(new XmlDomNode(m_domNode.removeChild(oldNode->m_domNode)), QScriptEngine::ScriptOwnership); } XmlDomNode::XmlDomNode(const QDomNode &other) { m_domNode = other; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/jsextensions/domxml.h000066400000000000000000000107351266132464200222700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 BogDan Vatra ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef DOMXML_H #define DOMXML_H #include #include #include #include #include #include namespace qbs { namespace Internal { class XmlDomDocument; void initializeJsExtensionXml(QScriptValue extensionObject); class XmlDomNode: public QObject, public QScriptable { Q_OBJECT public: static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine); Q_INVOKABLE bool isElement() const; Q_INVOKABLE bool isCDATASection() const; Q_INVOKABLE bool isText() const; Q_INVOKABLE QString attribute(const QString & name, const QString & defValue = QString()); Q_INVOKABLE void setAttribute(const QString & name, const QString & value); Q_INVOKABLE bool hasAttribute(const QString & name) const; Q_INVOKABLE QString tagName() const; Q_INVOKABLE void setTagName(const QString & name); Q_INVOKABLE QString text() const; Q_INVOKABLE QString data() const; Q_INVOKABLE void setData(const QString &v) const; Q_INVOKABLE void clear(); Q_INVOKABLE bool hasAttributes() const; Q_INVOKABLE bool hasChildNodes() const; Q_INVOKABLE QScriptValue parentNode() const; Q_INVOKABLE QScriptValue firstChild(const QString & tagName = QString()); Q_INVOKABLE QScriptValue lastChild(const QString & tagName = QString()) const; Q_INVOKABLE QScriptValue previousSibling(const QString & tagName = QString()) const; Q_INVOKABLE QScriptValue nextSibling(const QString & tagName = QString()) const; Q_INVOKABLE QScriptValue appendChild(QScriptValue newChild); Q_INVOKABLE QScriptValue insertBefore(const QScriptValue& newChild, const QScriptValue& refChild); Q_INVOKABLE QScriptValue insertAfter(const QScriptValue& newChild, const QScriptValue& refChild); Q_INVOKABLE QScriptValue replaceChild(const QScriptValue& newChild, const QScriptValue& oldChild); Q_INVOKABLE QScriptValue removeChild(const QScriptValue& oldChild); protected: friend class XmlDomDocument; XmlDomNode(const QDomNode &other = QDomNode()); QDomNode m_domNode; }; class XmlDomDocument: public XmlDomNode { Q_OBJECT public: static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine); Q_INVOKABLE QScriptValue documentElement(); Q_INVOKABLE QScriptValue createElement(const QString & tagName); Q_INVOKABLE QScriptValue createCDATASection(const QString & value); Q_INVOKABLE QScriptValue createTextNode(const QString & value); Q_INVOKABLE bool setContent(const QString & content); Q_INVOKABLE QString toString(int indent = 1); Q_INVOKABLE void save(const QString & filePath, int indent = 1); Q_INVOKABLE void load(const QString & filePath); protected: XmlDomDocument(QScriptContext *context, const QString &name = QString()); private: QDomDocument m_domDocument; }; } // namespace Internal } // namespace qbs Q_DECLARE_METATYPE(qbs::Internal::XmlDomDocument *) Q_DECLARE_METATYPE(qbs::Internal::XmlDomNode *) #endif // DOMXML_H qbs-src-1.4.5/src/lib/corelib/jsextensions/file.cpp000066400000000000000000000146561266132464200222500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "file.h" #include #include #include #include #include #include namespace qbs { namespace Internal { class File { friend void initializeJsExtensionFile(QScriptValue extensionObject); private: static QScriptValue js_ctor(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_copy(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_exists(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_lastModified(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_makePath(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_remove(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_canonicalFilePath(QScriptContext *context, QScriptEngine *engine); }; void initializeJsExtensionFile(QScriptValue extensionObject) { QScriptEngine *engine = extensionObject.engine(); QScriptValue fileObj = engine->newFunction(File::js_ctor); fileObj.setProperty(QLatin1String("copy"), engine->newFunction(File::js_copy)); fileObj.setProperty(QLatin1String("exists"), engine->newFunction(File::js_exists)); fileObj.setProperty(QLatin1String("lastModified"), engine->newFunction(File::js_lastModified)); fileObj.setProperty(QLatin1String("makePath"), engine->newFunction(File::js_makePath)); fileObj.setProperty(QLatin1String("remove"), engine->newFunction(File::js_remove)); fileObj.setProperty(QLatin1String("canonicalFilePath"), engine->newFunction(File::js_canonicalFilePath)); extensionObject.setProperty(QLatin1String("File"), fileObj); } QScriptValue File::js_ctor(QScriptContext *context, QScriptEngine *engine) { // Add instance variables here etc., if needed. Q_UNUSED(context); Q_UNUSED(engine); return true; } QScriptValue File::js_copy(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 2)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("copy expects 2 arguments")); } const QString sourceFile = context->argument(0).toString(); const QString targetFile = context->argument(1).toString(); QString errorMessage; if (Q_UNLIKELY(!copyFileRecursion(sourceFile, targetFile, false, &errorMessage))) return context->throwError(errorMessage); return true; } QScriptValue File::js_exists(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("exist expects 1 argument")); } const QString filePath = context->argument(0).toString(); const bool exists = FileInfo::exists(filePath); ScriptEngine * const se = static_cast(engine); se->addFileExistsResult(filePath, exists); return exists; } QScriptValue File::js_remove(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("remove expects 1 argument")); } QString fileName = context->argument(0).toString(); QString errorMessage; if (Q_UNLIKELY(!removeFileRecursion(QFileInfo(fileName), &errorMessage))) return context->throwError(errorMessage); return true; } QScriptValue File::js_lastModified(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("File.lastModified() expects an argument")); } const QString filePath = context->argument(0).toString(); const FileTime timestamp = FileInfo(filePath).lastModified(); ScriptEngine * const se = static_cast(engine); se->addFileLastModifiedResult(filePath, timestamp); return static_cast(timestamp.m_fileTime); } QScriptValue File::js_makePath(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("makePath expects 1 argument")); } return QDir::root().mkpath(context->argument(0).toString()); } QScriptValue File::js_canonicalFilePath(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(engine); if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("canonicalFilePath expects 1 argument")); } return QFileInfo(context->argument(0).toString()).canonicalFilePath(); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/jsextensions/file.h000066400000000000000000000033661266132464200217110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_FILE_H #define QBS_FILE_H #include #include namespace qbs { namespace Internal { void initializeJsExtensionFile(QScriptValue extensionObject); } // namespace Internal } // namespace qbs #endif // QBS_FILE_H qbs-src-1.4.5/src/lib/corelib/jsextensions/jsextensions.cpp000066400000000000000000000060121266132464200240500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "jsextensions.h" #include "domxml.h" #include "file.h" #include "process.h" #include "propertylist.h" #include "temporarydir.h" #include "textfile.h" #include namespace qbs { namespace Internal { void JsExtensions::setupExtensions(const QStringList &names, QScriptValue scope) { foreach (const QString &name, names) initializers().value(name)(scope); } QScriptValue JsExtensions::loadExtension(QScriptEngine *engine, const QString &name) { if (!hasExtension(name)) return QScriptValue(); QScriptValue extensionObj = engine->newObject(); initializers().value(name)(extensionObj); return extensionObj.property(name); } bool JsExtensions::hasExtension(const QString &name) { return initializers().contains(name); } JsExtensions::InitializerMap JsExtensions::initializers() { if (m_initializers.isEmpty()) { m_initializers.insert(QLatin1String("File"), &initializeJsExtensionFile); m_initializers.insert(QLatin1String("Process"), &initializeJsExtensionProcess); m_initializers.insert(QLatin1String("Xml"), &initializeJsExtensionXml); m_initializers.insert(QLatin1String("TemporaryDir"), &initializeJsExtensionTemporaryDir); m_initializers.insert(QLatin1String("TextFile"), &initializeJsExtensionTextFile); m_initializers.insert(QLatin1String("PropertyList"), &initializeJsExtensionPropertyList); } return m_initializers; } JsExtensions::InitializerMap JsExtensions::m_initializers; } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/jsextensions/jsextensions.h000066400000000000000000000042471266132464200235250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_JSEXTENSIONS_H #define QBS_JSEXTENSIONS_H #include #include QT_BEGIN_NAMESPACE class QScriptEngine; class QScriptValue; QT_END_NAMESPACE namespace qbs { namespace Internal { class JsExtensions { public: static void setupExtensions(const QStringList &names, QScriptValue scope); static QScriptValue loadExtension(QScriptEngine *engine, const QString &name); static bool hasExtension(const QString &name); private: typedef QHash InitializerMap; static InitializerMap initializers(); static InitializerMap m_initializers; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.4.5/src/lib/corelib/jsextensions/jsextensions.pri000066400000000000000000000010671266132464200240650ustar00rootroot00000000000000QT += xml HEADERS += \ $$PWD/file.h \ $$PWD/temporarydir.h \ $$PWD/textfile.h \ $$PWD/process.h \ $$PWD/moduleproperties.h \ $$PWD/domxml.h \ $$PWD/jsextensions.h SOURCES += \ $$PWD/file.cpp \ $$PWD/temporarydir.cpp \ $$PWD/textfile.cpp \ $$PWD/process.cpp \ $$PWD/moduleproperties.cpp \ $$PWD/domxml.cpp \ $$PWD/jsextensions.cpp mac { HEADERS += $$PWD/propertylist.h $$PWD/propertylistutils.h OBJECTIVE_SOURCES += $$PWD/propertylist.mm $$PWD/propertylistutils.mm LIBS += -framework Foundation } qbs-src-1.4.5/src/lib/corelib/jsextensions/moduleproperties.cpp000066400000000000000000000146631266132464200247310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "moduleproperties.h" #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { static QString ptrKey() { return QLatin1String("__internalPtr"); } static QString typeKey() { return QLatin1String("__type"); } static QString productType() { return QLatin1String("product"); } static QString artifactType() { return QLatin1String("artifact"); } void ModuleProperties::init(QScriptValue productObject, const ResolvedProductConstPtr &product) { init(productObject, product.data(), productType()); } void ModuleProperties::init(QScriptValue artifactObject, const Artifact *artifact) { init(artifactObject, artifact, artifactType()); } void ModuleProperties::init(QScriptValue objectWithProperties, const void *ptr, const QString &type) { QScriptEngine * const engine = objectWithProperties.engine(); objectWithProperties.setProperty(QLatin1String("moduleProperties"), engine->newFunction(ModuleProperties::js_moduleProperties, 2)); objectWithProperties.setProperty(QLatin1String("moduleProperty"), engine->newFunction(ModuleProperties::js_moduleProperty, 2)); objectWithProperties.setProperty(ptrKey(), engine->toScriptValue(quintptr(ptr))); objectWithProperties.setProperty(typeKey(), type); } QScriptValue ModuleProperties::js_moduleProperties(QScriptContext *context, QScriptEngine *engine) { try { return moduleProperties(context, engine, false); } catch (const ErrorInfo &e) { return context->throwError(e.toString()); } } QScriptValue ModuleProperties::js_moduleProperty(QScriptContext *context, QScriptEngine *engine) { try { return moduleProperties(context, engine, true); } catch (const ErrorInfo &e) { return context->throwError(e.toString()); } } QScriptValue ModuleProperties::moduleProperties(QScriptContext *context, QScriptEngine *engine, bool oneValue) { if (Q_UNLIKELY(context->argumentCount() < 2)) { return context->throwError(QScriptContext::SyntaxError, Tr::tr("Function moduleProperties() expects 2 arguments")); } const QScriptValue objectWithProperties = context->thisObject(); const QScriptValue typeScriptValue = objectWithProperties.property(typeKey()); if (Q_UNLIKELY(!typeScriptValue.isString())) { return context->throwError(QScriptContext::TypeError, QLatin1String("Internal error: __type not set up")); } const QScriptValue ptrScriptValue = objectWithProperties.property(ptrKey()); if (Q_UNLIKELY(!ptrScriptValue.isNumber())) { return context->throwError(QScriptContext::TypeError, QLatin1String("Internal error: __internalPtr not set up")); } const void *ptr = reinterpret_cast(qscriptvalue_cast(ptrScriptValue)); PropertyMapConstPtr properties; const Artifact *artifact = 0; if (typeScriptValue.toString() == productType()) { properties = static_cast(ptr)->moduleProperties; } else if (typeScriptValue.toString() == artifactType()) { artifact = static_cast(ptr); properties = artifact->properties; } else { return context->throwError(QScriptContext::TypeError, QLatin1String("Internal error: invalid type")); } ScriptEngine * const qbsEngine = static_cast(engine); const QString moduleName = context->argument(0).toString(); const QString propertyName = context->argument(1).toString(); QVariant value; if (qbsEngine->isPropertyCacheEnabled()) value = qbsEngine->retrieveFromPropertyCache(moduleName, propertyName, oneValue, properties); if (!value.isValid()) { if (oneValue) value = PropertyFinder().propertyValue(properties->value(), moduleName, propertyName); else value = PropertyFinder().propertyValues(properties->value(), moduleName, propertyName); const Property p(moduleName, propertyName, value); if (artifact) qbsEngine->addPropertyRequestedFromArtifact(artifact, p); else qbsEngine->addPropertyRequestedInScript(p); // Cache the variant value. We must not cache the QScriptValue here, because it's a // reference and the user might change the actual object. if (qbsEngine->isPropertyCacheEnabled()) qbsEngine->addToPropertyCache(moduleName, propertyName, oneValue, properties, value); } return engine->toScriptValue(value); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/jsextensions/moduleproperties.h000066400000000000000000000046471266132464200243770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_MODULEPROPERTIES_H #define QBS_MODULEPROPERTIES_H #include #include #include #include namespace qbs { namespace Internal { class ModuleProperties { public: static void init(QScriptValue productObject, const ResolvedProductConstPtr &product); static void init(QScriptValue artifactObject, const Artifact *artifact); private: static void init(QScriptValue objectWithProperties, const void *ptr, const QString &type); static QScriptValue js_moduleProperties(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_moduleProperty(QScriptContext *context, QScriptEngine *engine); static QScriptValue moduleProperties(QScriptContext *context, QScriptEngine *engine, bool oneValue); }; } // namespace Internal } // namespace qbs #endif // QBS_MODULEPROPERTIES_H qbs-src-1.4.5/src/lib/corelib/jsextensions/process.cpp000066400000000000000000000156211266132464200230000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "process.h" #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { void initializeJsExtensionProcess(QScriptValue extensionObject) { QScriptEngine *engine = extensionObject.engine(); QScriptValue obj = engine->newQMetaObject(&Process::staticMetaObject, engine->newFunction(&Process::ctor)); extensionObject.setProperty(QLatin1String("Process"), obj); } QScriptValue Process::ctor(QScriptContext *context, QScriptEngine *engine) { Process *t; switch (context->argumentCount()) { case 0: t = new Process(context); break; default: return context->throwError(QLatin1String("Process()")); } QScriptValue obj = engine->newQObject(t, QScriptEngine::ScriptOwnership); // Get environment QVariant v = engine->property("_qbs_procenv"); if (v.isNull()) { // The build environment is not initialized yet. // This can happen if one uses Process on the RHS of a binding like Group.name. t->m_environment = static_cast(engine)->environment(); } else { t->m_environment = QProcessEnvironment(*reinterpret_cast(v.value())); } return obj; } Process::~Process() { delete m_textStream; delete m_qProcess; } Process::Process(QScriptContext *context) { Q_UNUSED(context); Q_ASSERT(thisObject().engine() == engine()); m_qProcess = new QProcess; m_textStream = new QTextStream(m_qProcess); } QString Process::getEnv(const QString &name) { Q_ASSERT(thisObject().engine() == engine()); return m_environment.value(name); } void Process::setEnv(const QString &name, const QString &value) { Q_ASSERT(thisObject().engine() == engine()); m_environment.insert(name, value); } QString Process::workingDirectory() { Q_ASSERT(thisObject().engine() == engine()); return m_workingDirectory; } void Process::setWorkingDirectory(const QString &dir) { Q_ASSERT(thisObject().engine() == engine()); m_workingDirectory = dir; } bool Process::start(const QString &program, const QStringList &arguments) { Q_ASSERT(thisObject().engine() == engine()); if (!m_workingDirectory.isEmpty()) m_qProcess->setWorkingDirectory(m_workingDirectory); m_qProcess->setProcessEnvironment(m_environment); m_qProcess->start(findExecutable(program), arguments); return m_qProcess->waitForStarted(); } int Process::exec(const QString &program, const QStringList &arguments, bool throwOnError) { Q_ASSERT(thisObject().engine() == engine()); if (!start(findExecutable(program), arguments)) { if (throwOnError) { context()->throwError(Tr::tr("Error running '%1': %2") .arg(program, m_qProcess->errorString())); } return -1; } m_qProcess->closeWriteChannel(); m_qProcess->waitForFinished(-1); if (throwOnError) { if (m_qProcess->error() != QProcess::UnknownError) { context()->throwError(Tr::tr("Error running '%1': %2") .arg(program, m_qProcess->errorString())); } else if (m_qProcess->exitCode() != 0) { QString errorMessage = Tr::tr("Process '%1' finished with exit code %2.") .arg(program).arg(m_qProcess->exitCode()); const QString stdErr = readStdErr(); if (!stdErr.isEmpty()) errorMessage.append(Tr::tr(" The standard error output was:\n")).append(stdErr); context()->throwError(errorMessage); } } if (m_qProcess->error() != QProcess::UnknownError) return -1; return m_qProcess->exitCode(); } void Process::close() { Q_ASSERT(thisObject().engine() == engine()); delete m_textStream; m_textStream = 0; delete m_qProcess; m_qProcess = 0; } bool Process::waitForFinished(int msecs) { Q_ASSERT(thisObject().engine() == engine()); if (m_qProcess->state() == QProcess::NotRunning) return true; return m_qProcess->waitForFinished(msecs); } void Process::terminate() { m_qProcess->terminate(); } void Process::kill() { m_qProcess->kill(); } void Process::setCodec(const QString &codec) { Q_ASSERT(thisObject().engine() == engine()); m_textStream->setCodec(qPrintable(codec)); } QString Process::readLine() { return m_textStream->readLine(); } QString Process::readStdOut() { return m_textStream->readAll(); } QString Process::readStdErr() { return m_textStream->codec()->toUnicode(m_qProcess->readAllStandardError()); } int Process::exitCode() const { return m_qProcess->exitCode(); } Logger Process::logger() const { ScriptEngine *scriptEngine = static_cast(engine()); return scriptEngine->logger(); } QString Process::findExecutable(const QString &filePath) const { ExecutableFinder exeFinder(ResolvedProductPtr(), m_environment, logger()); return exeFinder.findExecutable(filePath, m_workingDirectory); } void Process::write(const QString &str) { (*m_textStream) << str; } void Process::writeLine(const QString &str) { (*m_textStream) << str; if (HostOsInfo::isWindowsHost()) (*m_textStream) << '\r'; (*m_textStream) << '\n'; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/jsextensions/process.h000066400000000000000000000063721266132464200224500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROCESS_H #define QBS_PROCESS_H #include #include #include #include #include QT_BEGIN_NAMESPACE class QProcess; class QTextStream; QT_END_NAMESPACE namespace qbs { namespace Internal { void initializeJsExtensionProcess(QScriptValue extensionObject); class Process : public QObject, public QScriptable { Q_OBJECT public: static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine); Process(QScriptContext *context); ~Process(); Q_INVOKABLE QString getEnv(const QString &name); Q_INVOKABLE void setEnv(const QString &name, const QString &value); Q_INVOKABLE void setCodec(const QString &codec); Q_INVOKABLE QString workingDirectory(); Q_INVOKABLE void setWorkingDirectory(const QString &dir); Q_INVOKABLE bool start(const QString &program, const QStringList &arguments); Q_INVOKABLE int exec(const QString &program, const QStringList &arguments, bool throwOnError = false); Q_INVOKABLE void close(); Q_INVOKABLE bool waitForFinished(int msecs = 30000); Q_INVOKABLE void terminate(); Q_INVOKABLE void kill(); Q_INVOKABLE QString readLine(); Q_INVOKABLE QString readStdOut(); Q_INVOKABLE QString readStdErr(); Q_INVOKABLE void write(const QString &str); Q_INVOKABLE void writeLine(const QString &str); Q_INVOKABLE int exitCode() const; private: Logger logger() const; QString findExecutable(const QString &filePath) const; QProcess *m_qProcess; QProcessEnvironment m_environment; QString m_workingDirectory; QTextStream *m_textStream; }; } // namespace Internal } // namespace qbs Q_DECLARE_METATYPE(qbs::Internal::Process *) #endif // QBS_PROCESS_H qbs-src-1.4.5/src/lib/corelib/jsextensions/propertylist.h000066400000000000000000000064251266132464200235510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROPERTYLIST_H #define QBS_PROPERTYLIST_H #include #ifndef Q_OS_MAC #include namespace qbs { namespace Internal { // provide a fake initializer for other platforms void initializeJsExtensionPropertyList(QScriptValue extensionObject) { // provide a fake object QScriptEngine *engine = extensionObject.engine(); extensionObject.setProperty(QLatin1String("PropertyList"), engine->newObject()); } } // namespace Internal } // namespace qbs #else // Q_OS_MAC #include #include #include #include #include namespace qbs { namespace Internal { void initializeJsExtensionPropertyList(QScriptValue extensionObject); class PropertyListPrivate; class PropertyList : public QObject, public QScriptable { Q_OBJECT public: static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine); PropertyList(QScriptContext *context); ~PropertyList(); Q_INVOKABLE bool isEmpty() const; Q_INVOKABLE void clear(); Q_INVOKABLE void readFromObject(const QScriptValue &value); Q_INVOKABLE void readFromString(const QString &input); Q_INVOKABLE void readFromFile(const QString &filePath); Q_INVOKABLE void writeToFile(const QString &filePath, const QString &plistFormat); Q_INVOKABLE QScriptValue format() const; Q_INVOKABLE QScriptValue toObject() const; Q_INVOKABLE QString toString(const QString &plistFormat) const; Q_INVOKABLE QString toXMLString() const; Q_INVOKABLE QString toJSON(const QString &style = QString()) const; private: PropertyListPrivate *d; }; } // namespace Internal } // namespace qbs Q_DECLARE_METATYPE(qbs::Internal::PropertyList *) #endif // Q_OS_MAC #endif // QBS_PROPERTYLIST_H qbs-src-1.4.5/src/lib/corelib/jsextensions/propertylist.mm000066400000000000000000000313241266132464200237270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "propertylist.h" #include #include #include #include #include // Same values as CoreFoundation and Foundation APIs enum { QPropertyListOpenStepFormat = 1, QPropertyListXMLFormat_v1_0 = 100, QPropertyListBinaryFormat_v1_0 = 200, QPropertyListJSONFormat = 1000 // If this conflicts someday, just change it :) }; namespace qbs { namespace Internal { class PropertyListPrivate { public: PropertyListPrivate(); QVariant propertyListObject; int propertyListFormat; void readFromData(QScriptContext *context, QByteArray data); QByteArray writeToData(QScriptContext *context, const QString &format); }; void initializeJsExtensionPropertyList(QScriptValue extensionObject) { QScriptEngine *engine = extensionObject.engine(); QScriptValue obj = engine->newQMetaObject(&PropertyList::staticMetaObject, engine->newFunction(&PropertyList::ctor)); extensionObject.setProperty(QLatin1String("PropertyList"), obj); } QScriptValue PropertyList::ctor(QScriptContext *context, QScriptEngine *engine) { PropertyList *p = new PropertyList(context); QScriptValue obj = engine->newQObject(p, QScriptEngine::ScriptOwnership); return obj; } PropertyListPrivate::PropertyListPrivate() : propertyListObject(), propertyListFormat(0) { } PropertyList::~PropertyList() { delete d; } PropertyList::PropertyList(QScriptContext *context) : d(new PropertyListPrivate) { Q_UNUSED(context); Q_ASSERT(thisObject().engine() == engine()); } bool PropertyList::isEmpty() const { Q_ASSERT(thisObject().engine() == engine()); PropertyList *p = qscriptvalue_cast(thisObject()); return p->d->propertyListObject.isNull(); } void PropertyList::clear() { Q_ASSERT(thisObject().engine() == engine()); PropertyList *p = qscriptvalue_cast(thisObject()); p->d->propertyListObject = QVariant(); p->d->propertyListFormat = 0; } void PropertyList::readFromObject(const QScriptValue &value) { Q_ASSERT(thisObject().engine() == engine()); PropertyList *p = qscriptvalue_cast(thisObject()); p->d->propertyListObject = value.toVariant(); p->d->propertyListFormat = 0; // wasn't deserialized from any external format } void PropertyList::readFromString(const QString &input) { Q_ASSERT(thisObject().engine() == engine()); PropertyList *p = qscriptvalue_cast(thisObject()); p->d->readFromData(p->context(), input.toUtf8()); } void PropertyList::readFromFile(const QString &filePath) { Q_ASSERT(thisObject().engine() == engine()); PropertyList *p = qscriptvalue_cast(thisObject()); QFile file(filePath); if (file.open(QIODevice::ReadOnly)) { QByteArray data = file.readAll(); if (!data.isEmpty()) { p->d->readFromData(p->context(), data); } else { p->context()->throwError(file.errorString()); } } else { p->context()->throwError(file.errorString()); } } void PropertyList::writeToFile(const QString &filePath, const QString &plistFormat) { Q_ASSERT(thisObject().engine() == engine()); PropertyList *p = qscriptvalue_cast(thisObject()); QByteArray data = p->d->writeToData(p->context(), plistFormat); if (Q_LIKELY(!data.isEmpty())) { QFile file(filePath); if (file.open(QIODevice::WriteOnly)) { if (Q_UNLIKELY(file.write(data) != data.size())) { p->context()->throwError(file.errorString()); } } else { p->context()->throwError(file.errorString()); } } } QScriptValue PropertyList::format() const { Q_ASSERT(thisObject().engine() == engine()); PropertyList *p = qscriptvalue_cast(thisObject()); switch (p->d->propertyListFormat) { case QPropertyListOpenStepFormat: return QLatin1String("openstep"); case QPropertyListXMLFormat_v1_0: return QLatin1String("xml1"); case QPropertyListBinaryFormat_v1_0: return QLatin1String("binary1"); case QPropertyListJSONFormat: return QLatin1String("json"); default: return p->engine()->undefinedValue(); } } QScriptValue PropertyList::toObject() const { Q_ASSERT(thisObject().engine() == engine()); PropertyList *p = qscriptvalue_cast(thisObject()); return p->engine()->toScriptValue(p->d->propertyListObject); } QString PropertyList::toString(const QString &plistFormat) const { Q_ASSERT(thisObject().engine() == engine()); PropertyList *p = qscriptvalue_cast(thisObject()); if (plistFormat == QLatin1String("binary1")) { p->context()->throwError(QLatin1String("Property list object cannot be converted to a " "string in the binary1 format; this format can only " "be written directly to a file")); return QString(); } if (!isEmpty()) return QString::fromUtf8(p->d->writeToData(p->context(), plistFormat)); return QString(); } QString PropertyList::toXMLString() const { return toString(QLatin1String("xml1")); } QString PropertyList::toJSON(const QString &style) const { QString format = QLatin1String("json"); if (!style.isEmpty()) format += QLatin1String("-") + style; return toString(format); } } // namespace Internal } // namespace qbs #include "propertylistutils.h" namespace qbs { namespace Internal { void PropertyListPrivate::readFromData(QScriptContext *context, QByteArray data) { @autoreleasepool { NSPropertyListFormat format; int internalFormat = 0; NSError *error = nil; NSString *errorString = nil; id plist = nil; if ([NSPropertyListSerialization respondsToSelector:@selector(propertyListWithData:options:format:error:)]) { error = nil; errorString = nil; plist = [NSPropertyListSerialization propertyListWithData:QByteArray_toNSData(data) options:0 format:&format error:&error]; if (Q_UNLIKELY(!plist)) { errorString = [error localizedDescription]; } } else { error = nil; errorString = nil; plist = [NSPropertyListSerialization propertyListFromData:QByteArray_toNSData(data) mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&errorString]; } if (plist) internalFormat = format; #if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_7 if (!plist && NSClassFromString(@"NSJSONSerialization")) { error = nil; errorString = nil; plist = [NSJSONSerialization JSONObjectWithData:QByteArray_toNSData(data) options:0 error:&error]; if (Q_UNLIKELY(!plist)) { errorString = [error localizedDescription]; } else { internalFormat = QPropertyListJSONFormat; } } #endif if (Q_UNLIKELY(!plist)) { context->throwError(QString_fromNSString(errorString)); } else { QVariant obj = QPropertyListUtils::fromPropertyList(plist); if (!obj.isNull()) { propertyListObject = obj; propertyListFormat = internalFormat; } else { context->throwError(QLatin1String("error converting property list")); } } } } QByteArray PropertyListPrivate::writeToData(QScriptContext *context, const QString &format) { @autoreleasepool { NSError *error = nil; NSString *errorString = nil; NSData *data = nil; id obj = QPropertyListUtils::toPropertyList(propertyListObject); if (!obj) { context->throwError(QLatin1String("error converting property list")); return 0; } if (format == QLatin1String("json") || format == QLatin1String("json-pretty") || format == QLatin1String("json-compact")) { #if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_7 if (NSClassFromString(@"NSJSONSerialization")) { if ([NSJSONSerialization isValidJSONObject:obj]) { error = nil; errorString = nil; const NSJSONWritingOptions options = format == QLatin1String("json-pretty") ? NSJSONWritingPrettyPrinted : 0; data = [NSJSONSerialization dataWithJSONObject:obj options:options error:&error]; if (Q_UNLIKELY(!data)) { errorString = [error localizedDescription]; } } else { errorString = @"Property list object cannot be converted to JSON data"; } } #endif else { errorString = @"JSON serialization of property lists is not " @"supported on this version of OS X"; } } else if (format == QLatin1String("xml1") || format == QLatin1String("binary1")) { const NSPropertyListFormat plistFormat = format == QLatin1String("xml1") ? NSPropertyListXMLFormat_v1_0 : NSPropertyListBinaryFormat_v1_0; error = nil; errorString = nil; if ([NSPropertyListSerialization respondsToSelector:@selector(dataWithPropertyList:format:options:error:)]) { data = [NSPropertyListSerialization dataWithPropertyList:obj format:plistFormat options:0 error:&error]; if (Q_UNLIKELY(!data)) { errorString = [error localizedDescription]; } } else { data = [NSPropertyListSerialization dataFromPropertyList:obj format:plistFormat errorDescription:&errorString]; } } else { errorString = [NSString stringWithFormat:@"Property lists cannot be written in the '%s' " @"format", format.toUtf8().constData()]; } if (Q_UNLIKELY(!data)) { context->throwError(QString_fromNSString(errorString)); } return QByteArray_fromNSData(data); } } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/jsextensions/propertylistutils.h000066400000000000000000000067711266132464200246360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2014 Petroules Corporation. ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QPROPERTYLISTUTILS_H #define QPROPERTYLISTUTILS_H #include #import #if !defined(__OBJC__) || !defined(__cplusplus) #error "This file must be included from Objective-C++" #endif static inline QString QString_fromNSString(const NSString *string) { #if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) return QString::fromNSString(string); #else if (!string) return QString(); QString qstring; qstring.resize([string length]); [string getCharacters:reinterpret_cast(qstring.data()) range:NSMakeRange(0, [string length])]; return qstring; #endif } static inline NSString *QString_toNSString(const QString &qstring) { #if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0) return qstring.toNSString(); #else return [NSString stringWithCharacters:reinterpret_cast(qstring.unicode()) length:qstring.length()]; #endif } static inline QByteArray QByteArray_fromNSData(const NSData *data) { #if QT_VERSION >= QT_VERSION_CHECK(5, 3, 0) return QByteArray::fromNSData(data); #else if (!data) return QByteArray(); return QByteArray(reinterpret_cast([data bytes]), [data length]); #endif } static inline NSData *QByteArray_toNSData(const QByteArray &qbytearray) { #if QT_VERSION >= QT_VERSION_CHECK(5, 3, 0) return qbytearray.toNSData(); #else return [NSData dataWithBytes:qbytearray.constData() length:qbytearray.size()]; #endif } class QPropertyListUtils { Q_DISABLE_COPY(QPropertyListUtils) public: static QVariant fromPropertyList(id plist); static id toPropertyList(const QVariant &map); private: QPropertyListUtils(); }; template QMap qHashToMap(const QHash &hash) { QMap map; QHashIterator i(hash); while (i.hasNext()) { i.next(); map.insert(i.key(), i.value()); } return map; } #endif // QPROPERTYLISTUTILS_H qbs-src-1.4.5/src/lib/corelib/jsextensions/propertylistutils.mm000066400000000000000000000167211266132464200250140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Petroules Corporation. ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #import #include "propertylistutils.h" #include #include #include #include static inline QDateTime QDateTime_fromNSDate(const NSDate *date) { #if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0) return QDateTime::fromNSDate(date); #else if (!date) return QDateTime(); return QDateTime::fromMSecsSinceEpoch(static_cast([date timeIntervalSince1970] * 1000)); #endif } static inline NSDate *QDateTime_toNSDate(const QDateTime &qdatetime) { #if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0) return qdatetime.toNSDate(); #else return [NSDate dateWithTimeIntervalSince1970:static_cast(qdatetime.toMSecsSinceEpoch()) / 1000]; #endif } static QVariant fromObject(id obj); static QVariantMap fromDictionary(NSDictionary *dict); static QVariantList fromArray(NSArray *array); static QVariant fromObject(id obj) { QVariant value; if (!obj) { return value; } else if ([obj isKindOfClass:[NSDictionary class]]) { value = fromDictionary(obj); } else if ([obj isKindOfClass:[NSArray class]]) { value = fromArray(obj); } else if ([obj isKindOfClass:[NSString class]]) { value = QString_fromNSString(obj); } else if ([obj isKindOfClass:[NSData class]]) { value = QByteArray_fromNSData(obj); } else if ([obj isKindOfClass:[NSDate class]]) { value = QDateTime_fromNSDate(obj); } else if ([obj isKindOfClass:[NSNumber class]]) { if (strcmp([(NSNumber *)obj objCType], @encode(BOOL)) == 0) { value = static_cast([obj boolValue]); } else if (strcmp([(NSNumber *)obj objCType], @encode(signed char)) == 0) { value = [obj charValue]; } else if (strcmp([(NSNumber *)obj objCType], @encode(unsigned char)) == 0) { value = [obj unsignedCharValue]; } else if (strcmp([(NSNumber *)obj objCType], @encode(signed short)) == 0) { value = [obj shortValue]; } else if (strcmp([(NSNumber *)obj objCType], @encode(unsigned short)) == 0) { value = [obj unsignedShortValue]; } else if (strcmp([(NSNumber *)obj objCType], @encode(signed int)) == 0) { value = [obj intValue]; } else if (strcmp([(NSNumber *)obj objCType], @encode(unsigned int)) == 0) { value = [obj unsignedIntValue]; } else if (strcmp([(NSNumber *)obj objCType], @encode(signed long long)) == 0) { value = [obj longLongValue]; } else if (strcmp([(NSNumber *)obj objCType], @encode(unsigned long long)) == 0) { value = [obj unsignedLongLongValue]; } else if (strcmp([(NSNumber *)obj objCType], @encode(float)) == 0) { value = [obj floatValue]; } else if (strcmp([(NSNumber *)obj objCType], @encode(double)) == 0) { value = [obj doubleValue]; } else { // NSDecimal or unknown value = [obj doubleValue]; } } else if ([obj isKindOfClass:[NSNull class]]) { // A null variant, close enough... } else { // unknown } return value; } static QVariantMap fromDictionary(NSDictionary *dict) { QVariantMap map; for (NSString *key in dict) map[QString_fromNSString(key)] = fromObject([dict objectForKey:key]); return map; } static QVariantList fromArray(NSArray *array) { QVariantList list; for (id obj in array) list.append(fromObject(obj)); return list; } QVariant QPropertyListUtils::fromPropertyList(id plist) { return fromObject(plist); } static id toObject(const QVariant &variant); static NSDictionary *toDictionary(const QVariantMap &map); static NSArray *toArray(const QVariantList &list); static id toObject(const QVariant &variant) { if (variant.type() == QVariant::Hash) { return toDictionary(qHashToMap(variant.toHash())); } else if (variant.type() == QVariant::Map) { return toDictionary(variant.toMap()); } else if (variant.type() == QVariant::List) { return toArray(variant.toList()); } else if (variant.type() == QVariant::String) { return QString_toNSString(variant.toString()); } else if (variant.type() == QVariant::ByteArray) { return QByteArray_toNSData(variant.toByteArray()); } else if (variant.type() == QVariant::Date || variant.type() == QVariant::DateTime) { return QDateTime_toNSDate(variant.toDateTime()); } else if (variant.type() == QVariant::Bool) { return variant.toBool() ? [NSNumber numberWithBool:YES] : [NSNumber numberWithBool:NO]; } else if (variant.type() == QVariant::Char || variant.type() == QVariant::Int) { return [NSNumber numberWithInt:variant.toInt()]; } else if (variant.type() == QVariant::UInt) { return [NSNumber numberWithUnsignedInt:variant.toUInt()]; } else if (variant.type() == QVariant::LongLong) { return [NSNumber numberWithLongLong:variant.toLongLong()]; } else if (variant.type() == QVariant::ULongLong) { return [NSNumber numberWithUnsignedLongLong:variant.toULongLong()]; } else if (variant.type() == QVariant::Double) { return [NSNumber numberWithDouble:variant.toDouble()]; } else { return [NSNull null]; } } static NSDictionary *toDictionary(const QVariantMap &map) { NSMutableDictionary *dict = [NSMutableDictionary dictionary]; QMapIterator i(map); while (i.hasNext()) { i.next(); [dict setObject:toObject(i.value()) forKey:QString_toNSString(i.key())]; } return [NSDictionary dictionaryWithDictionary:dict]; } static NSArray *toArray(const QVariantList &list) { NSMutableArray *array = [NSMutableArray array]; foreach (const QVariant &variant, list) [array addObject:toObject(variant)]; return [NSArray arrayWithArray:array]; } id QPropertyListUtils::toPropertyList(const QVariant &variant) { return toObject(variant); } qbs-src-1.4.5/src/lib/corelib/jsextensions/temporarydir.cpp000066400000000000000000000050051266132464200240360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "temporarydir.h" #include #include #include namespace qbs { namespace Internal { void initializeJsExtensionTemporaryDir(QScriptValue extensionObject) { QScriptEngine *engine = extensionObject.engine(); QScriptValue obj = engine->newQMetaObject(&TemporaryDir::staticMetaObject, engine->newFunction(&TemporaryDir::ctor)); extensionObject.setProperty(QLatin1String("TemporaryDir"), obj); } QScriptValue TemporaryDir::ctor(QScriptContext *context, QScriptEngine *engine) { TemporaryDir *t = new TemporaryDir(context); QScriptValue obj = engine->newQObject(t, QScriptEngine::ScriptOwnership); return obj; } TemporaryDir::TemporaryDir(QScriptContext *context) { Q_UNUSED(context); } bool TemporaryDir::isValid() const { return dir.isValid(); } QString TemporaryDir::path() const { return dir.path(); } bool TemporaryDir::remove() { return dir.remove(); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/jsextensions/temporarydir.h000066400000000000000000000042161266132464200235060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_TEMPORARYDIR_H #define QBS_TEMPORARYDIR_H #include #include #include #include namespace qbs { namespace Internal { void initializeJsExtensionTemporaryDir(QScriptValue extensionObject); class TemporaryDir : public QObject, public QScriptable { Q_OBJECT public: static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine); TemporaryDir(QScriptContext *context); Q_INVOKABLE bool isValid() const; Q_INVOKABLE QString path() const; Q_INVOKABLE bool remove(); private: QTemporaryDir dir; }; } // namespace Internal } // namespace qbs #endif // QBS_TEMPORARYDIR_H qbs-src-1.4.5/src/lib/corelib/jsextensions/textfile.cpp000066400000000000000000000122271266132464200231450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "textfile.h" #include #include #include #include #include #include namespace qbs { namespace Internal { void initializeJsExtensionTextFile(QScriptValue extensionObject) { QScriptEngine *engine = extensionObject.engine(); QScriptValue obj = engine->newQMetaObject(&TextFile::staticMetaObject, engine->newFunction(&TextFile::ctor)); extensionObject.setProperty(QLatin1String("TextFile"), obj); } QScriptValue TextFile::ctor(QScriptContext *context, QScriptEngine *engine) { TextFile *t; switch (context->argumentCount()) { case 0: return context->throwError(Tr::tr("TextFile constructor needs path of file to be opened.")); case 1: t = new TextFile(context, context->argument(0).toString()); break; case 2: t = new TextFile(context, context->argument(0).toString(), static_cast(context->argument(1).toInt32()) ); break; case 3: t = new TextFile(context, context->argument(0).toString(), static_cast(context->argument(1).toInt32()), context->argument(2).toString() ); break; default: return context->throwError(Tr::tr("TextFile constructor takes at most three parameters.")); } return engine->newQObject(t, QScriptEngine::ScriptOwnership); } TextFile::~TextFile() { delete m_stream; delete m_file; } TextFile::TextFile(QScriptContext *context, const QString &filePath, OpenMode mode, const QString &codec) { Q_UNUSED(codec) Q_ASSERT(thisObject().engine() == engine()); m_file = new QFile(filePath); m_stream = new QTextStream(m_file); QIODevice::OpenMode m; switch (mode) { case ReadWrite: m = QIODevice::ReadWrite; break; case ReadOnly: m = QIODevice::ReadOnly; break; case WriteOnly: m = QIODevice::WriteOnly; break; } if (Q_UNLIKELY(!m_file->open(m))) { context->throwError(Tr::tr("Unable to open file '%1': %2") .arg(filePath, m_file->errorString())); delete m_file; m_file = 0; } } void TextFile::close() { if (checkForClosed()) return; m_file->close(); delete m_file; m_file = 0; delete m_stream; m_stream = 0; } void TextFile::setCodec(const QString &codec) { if (checkForClosed()) return; m_stream->setCodec(qPrintable(codec)); } QString TextFile::readLine() { if (checkForClosed()) return QString(); return m_stream->readLine(); } QString TextFile::readAll() { if (checkForClosed()) return QString(); return m_stream->readAll(); } bool TextFile::atEof() const { if (checkForClosed()) return true; return m_stream->atEnd(); } void TextFile::truncate() { if (checkForClosed()) return; m_file->resize(0); m_stream->reset(); } void TextFile::write(const QString &str) { if (checkForClosed()) return; (*m_stream) << str; } void TextFile::writeLine(const QString &str) { if (checkForClosed()) return; (*m_stream) << str; if (HostOsInfo::isWindowsHost()) (*m_stream) << '\r'; (*m_stream) << '\n'; } bool TextFile::checkForClosed() const { if (m_file) return false; context()->throwError(Tr::tr("Access to TextFile object that was already closed.")); return true; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/jsextensions/textfile.h000066400000000000000000000052651266132464200226160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_TEXTFILE_H #define QBS_TEXTFILE_H #include #include #include QT_BEGIN_NAMESPACE class QFile; class QTextStream; QT_END_NAMESPACE namespace qbs { namespace Internal { void initializeJsExtensionTextFile(QScriptValue extensionObject); class TextFile : public QObject, public QScriptable { Q_OBJECT Q_ENUMS(OpenMode) public: enum OpenMode { ReadOnly, WriteOnly, ReadWrite }; static QScriptValue ctor(QScriptContext *context, QScriptEngine *engine); ~TextFile(); Q_INVOKABLE void close(); Q_INVOKABLE void setCodec(const QString &codec); Q_INVOKABLE QString readLine(); Q_INVOKABLE QString readAll(); Q_INVOKABLE bool atEof() const; Q_INVOKABLE void truncate(); Q_INVOKABLE void write(const QString &str); Q_INVOKABLE void writeLine(const QString &str); private: TextFile(QScriptContext *context, const QString &filePath, OpenMode mode = ReadOnly, const QString &codec = QLatin1String("UTF8")); bool checkForClosed() const; QFile *m_file; QTextStream *m_stream; }; } // namespace Internal } // namespace qbs Q_DECLARE_METATYPE(qbs::Internal::TextFile *) #endif // QBS_TEXTFILE_H qbs-src-1.4.5/src/lib/corelib/language/000077500000000000000000000000001266132464200176405ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/artifactproperties.cpp000066400000000000000000000045041266132464200242610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "artifactproperties.h" #include #include namespace qbs { namespace Internal { ArtifactPropertiesPtr ArtifactProperties::create() { return ArtifactPropertiesPtr(new ArtifactProperties); } ArtifactProperties::ArtifactProperties() { } void ArtifactProperties::load(PersistentPool &pool) { pool.stream() >> m_fileTagsFilter; m_propertyMap = pool.idLoadS(); } void ArtifactProperties::store(PersistentPool &pool) const { pool.stream() << m_fileTagsFilter; pool.store(m_propertyMap); } bool operator==(const ArtifactProperties &ap1, const ArtifactProperties &ap2) { return ap1.fileTagsFilter() == ap2.fileTagsFilter() && ap1.propertyMap()->value() == ap2.propertyMap()->value(); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/artifactproperties.h000066400000000000000000000050201266132464200237200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_ARTIFACTPROPERTIES_H #define QBS_ARTIFACTPROPERTIES_H #include "filetags.h" #include "forward_decls.h" #include namespace qbs { namespace Internal { class ArtifactProperties : public PersistentObject { public: static ArtifactPropertiesPtr create(); void setFileTagsFilter(const FileTags &filter) { m_fileTagsFilter = filter; } FileTags fileTagsFilter() const { return m_fileTagsFilter; } PropertyMapPtr propertyMap() const { return m_propertyMap; } void setPropertyMapInternal(const PropertyMapPtr &pmap) { m_propertyMap = pmap; } private: ArtifactProperties(); void load(PersistentPool &); void store(PersistentPool &) const; FileTags m_fileTagsFilter; PropertyMapPtr m_propertyMap; }; bool operator==(const ArtifactProperties &ap1, const ArtifactProperties &ap2); inline bool operator!=(const ArtifactProperties &ap1, const ArtifactProperties &ap2) { return !(ap1 == ap2); } } // namespace Internal } // namespace qbs #endif // QBS_ARTIFACTPROPERTIES_H qbs-src-1.4.5/src/lib/corelib/language/asttools.cpp000066400000000000000000000047331266132464200222230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "asttools.h" #include namespace qbs { namespace Internal { QStringList toStringList(QbsQmlJS::AST::UiQualifiedId *qid) { QStringList result; for (; qid; qid = qid->next) result.append(qid->name.toString()); return result; } CodeLocation toCodeLocation(const QString &filePath, const QbsQmlJS::AST::SourceLocation &location) { return CodeLocation(filePath, location.startLine, location.startColumn); } QString textOf(const QString &source, QbsQmlJS::AST::Node *node) { if (!node) return QString(); return source.mid(node->firstSourceLocation().begin(), node->lastSourceLocation().end() - node->firstSourceLocation().begin()); } QStringRef textRefOf(const QString &source, QbsQmlJS::AST::Node *node) { const quint32 firstBegin = node->firstSourceLocation().begin(); return source.midRef(firstBegin, node->lastSourceLocation().end() - firstBegin); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/asttools.h000066400000000000000000000040271266132464200216640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_ASTTOOLS_H #define QBS_ASTTOOLS_H #include #include #include namespace qbs { namespace Internal { QStringList toStringList(QbsQmlJS::AST::UiQualifiedId *qid); CodeLocation toCodeLocation(const QString &filePath, const QbsQmlJS::AST::SourceLocation &location); QString textOf(const QString &source, QbsQmlJS::AST::Node *node); QStringRef textRefOf(const QString &source, QbsQmlJS::AST::Node *node); } // namespace Internal } // namespace qbs #endif // QBS_ASTTOOLS_H qbs-src-1.4.5/src/lib/corelib/language/builtindeclarations.cpp000066400000000000000000000425701266132464200244130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "builtindeclarations.h" #include "deprecationinfo.h" #include #include namespace qbs { namespace Internal { class AClassWithPublicConstructor : public BuiltinDeclarations { }; Q_GLOBAL_STATIC(AClassWithPublicConstructor, theInstance) const char QBS_LANGUAGE_VERSION[] = "1.0"; BuiltinDeclarations::BuiltinDeclarations() : m_languageVersion(Version::fromString(QLatin1String(QBS_LANGUAGE_VERSION))) { addArtifactItem(); addDependsItem(); addExportItem(); addFileTaggerItem(); addGroupItem(); addModuleItem(); addProbeItem(); addProductItem(); addProjectItem(); addPropertiesItem(); addPropertyOptionsItem(); addRuleItem(); addSubprojectItem(); addTransformerItem(); addScannerItem(); } const BuiltinDeclarations &BuiltinDeclarations::instance() { return *theInstance; } Version BuiltinDeclarations::languageVersion() const { return m_languageVersion; } bool BuiltinDeclarations::containsType(const QString &typeName) const { return m_builtins.contains(typeName); } QStringList BuiltinDeclarations::allTypeNames() const { return m_builtins.keys(); } ItemDeclaration BuiltinDeclarations::declarationsForType(const QString &typeName) const { return m_builtins.value(typeName); } void BuiltinDeclarations::insert(const ItemDeclaration &decl) { m_builtins.insert(decl.typeName(), decl); } static PropertyDeclaration conditionProperty() { PropertyDeclaration decl(QLatin1String("condition"), PropertyDeclaration::Boolean); decl.setInitialValueSource(QLatin1String("true")); return decl; } static PropertyDeclaration nameProperty() { return PropertyDeclaration(QLatin1String("name"), PropertyDeclaration::String); } static PropertyDeclaration buildDirProperty() { return PropertyDeclaration(QLatin1String("buildDirectory"), PropertyDeclaration::Path); } static PropertyDeclaration prepareScriptProperty() { PropertyDeclaration decl(QLatin1String("prepare"), PropertyDeclaration::Verbatim); decl.setFunctionArgumentNames( QStringList() << QLatin1String("project") << QLatin1String("product") << QLatin1String("inputs") << QLatin1String("outputs") << QLatin1String("input") << QLatin1String("output")); return decl; } void BuiltinDeclarations::addArtifactItem() { ItemDeclaration item(QLatin1String("Artifact")); PropertyDeclaration conditionDecl = conditionProperty(); conditionDecl.setDeprecationInfo(DeprecationInfo(Version(1, 4), Tr::tr("If you need " "dynamic artifacts, use the Rule.outputArtifacts script instead of Artifact items."))); item << conditionDecl; PropertyDeclaration fileNameDecl(QLatin1String("fileName"), PropertyDeclaration::Verbatim); fileNameDecl.setDeprecationInfo(DeprecationInfo(Version(1, 4), Tr::tr("Please use 'filePath' instead."))); item << fileNameDecl; item << PropertyDeclaration(QLatin1String("filePath"), PropertyDeclaration::Verbatim); item << PropertyDeclaration(QLatin1String("fileTags"), PropertyDeclaration::Variant); PropertyDeclaration decl(QLatin1String("alwaysUpdated"), PropertyDeclaration::Boolean); decl.setInitialValueSource(QLatin1String("true")); item << decl; insert(item); } void BuiltinDeclarations::addDependsItem() { ItemDeclaration item(QLatin1String("Depends")); item << conditionProperty(); item << nameProperty(); item << PropertyDeclaration(QLatin1String("submodules"), PropertyDeclaration::Variant); PropertyDeclaration requiredDecl(QLatin1String("required"), PropertyDeclaration::Boolean); requiredDecl.setInitialValueSource(QLatin1String("true")); item << requiredDecl; PropertyDeclaration profileDecl(QLatin1String("profiles"), PropertyDeclaration::StringList); profileDecl.setInitialValueSource(QLatin1String("[product.profile]")); item << profileDecl; item << PropertyDeclaration(QLatin1String("productTypes"), PropertyDeclaration::StringList); PropertyDeclaration limitDecl(QLatin1String("limitToSubProject"), PropertyDeclaration::Boolean); limitDecl.setInitialValueSource(QLatin1String("false")); item << limitDecl; insert(item); } void BuiltinDeclarations::addExportItem() { addModuleLikeItem(QStringLiteral("Export")); } void BuiltinDeclarations::addFileTaggerItem() { ItemDeclaration item(QLatin1String("FileTagger")); item << PropertyDeclaration(QLatin1String("patterns"), PropertyDeclaration::StringList); item << PropertyDeclaration(QLatin1String("fileTags"), PropertyDeclaration::Variant); insert(item); } void BuiltinDeclarations::addGroupItem() { ItemDeclaration item(QLatin1String("Group")); item << conditionProperty(); item << PropertyDeclaration(QLatin1String("name"), PropertyDeclaration::String, PropertyDeclaration::PropertyNotAvailableInConfig); item << PropertyDeclaration(QLatin1String("files"), PropertyDeclaration::Variant, PropertyDeclaration::PropertyNotAvailableInConfig); item << PropertyDeclaration(QLatin1String("fileTagsFilter"), PropertyDeclaration::Variant, PropertyDeclaration::PropertyNotAvailableInConfig); item << PropertyDeclaration(QLatin1String("excludeFiles"), PropertyDeclaration::Variant, PropertyDeclaration::PropertyNotAvailableInConfig); item << PropertyDeclaration(QLatin1String("fileTags"), PropertyDeclaration::Variant, PropertyDeclaration::PropertyNotAvailableInConfig); item << PropertyDeclaration(QLatin1String("prefix"), PropertyDeclaration::Variant, PropertyDeclaration::PropertyNotAvailableInConfig); PropertyDeclaration declaration; declaration.setName(QLatin1String("overrideTags")); declaration.setType(PropertyDeclaration::Boolean); declaration.setFlags(PropertyDeclaration::PropertyNotAvailableInConfig); declaration.setInitialValueSource(QLatin1String("true")); item << declaration; insert(item); } void BuiltinDeclarations::addModuleItem() { addModuleLikeItem(QStringLiteral("Module")); } void BuiltinDeclarations::addModuleLikeItem(const QString &typeName) { ItemDeclaration item(typeName); item.setAllowedChildTypes(ItemDeclaration::TypeNames() << QLatin1String("Group") << QLatin1String("Depends") << QLatin1String("FileTagger") << QLatin1String("Rule") << QLatin1String("Probe") << QLatin1String("PropertyOptions") << QLatin1String("Transformer") << QLatin1String("Scanner")); item << nameProperty(); item << conditionProperty(); item << PropertyDeclaration(QLatin1String("setupBuildEnvironment"), PropertyDeclaration::Verbatim); item << PropertyDeclaration(QLatin1String("setupRunEnvironment"), PropertyDeclaration::Verbatim); item << PropertyDeclaration(QLatin1String("validate"), PropertyDeclaration::Variant, PropertyDeclaration::PropertyNotAvailableInConfig); item << PropertyDeclaration(QLatin1String("additionalProductTypes"), PropertyDeclaration::Variant); PropertyDeclaration presentDecl(QLatin1String("present"), PropertyDeclaration::Boolean); presentDecl.setInitialValueSource(QLatin1String("true")); item << presentDecl; insert(item); } void BuiltinDeclarations::addProbeItem() { ItemDeclaration item(QLatin1String("Probe")); item << conditionProperty(); PropertyDeclaration foundProperty(QLatin1String("found"), PropertyDeclaration::Boolean); foundProperty.setInitialValueSource(QLatin1String("false")); item << foundProperty; item << PropertyDeclaration(QLatin1String("configure"), PropertyDeclaration::Verbatim); insert(item); } void BuiltinDeclarations::addProductItem() { ItemDeclaration item(QLatin1String("Product")); item.setAllowedChildTypes(ItemDeclaration::TypeNames() << QLatin1String("Depends") << QLatin1String("Transformer") << QLatin1String("Group") << QLatin1String("FileTagger") << QLatin1String("Export") << QLatin1String("Probe") << QLatin1String("PropertyOptions") << QLatin1String("Rule")); item << conditionProperty(); PropertyDeclaration decl(QLatin1String("type"), PropertyDeclaration::StringList); decl.setInitialValueSource(QLatin1String("[]")); item << decl; item << nameProperty(); decl = PropertyDeclaration(QLatin1String("builtByDefault"), PropertyDeclaration::Boolean); decl.setInitialValueSource(QLatin1String("true")); item << decl; decl = PropertyDeclaration(QLatin1String("profiles"), PropertyDeclaration::StringList); decl.setInitialValueSource(QLatin1String("[project.profile]")); item << decl; item << PropertyDeclaration(QLatin1String("profile"), PropertyDeclaration::String); // Internal decl = PropertyDeclaration(QLatin1String("targetName"), PropertyDeclaration::String); decl.setInitialValueSource(QLatin1String("new String(name)" ".replace(/[/\\\\?%*:|\"<>]/g, '_').valueOf()")); item << buildDirProperty(); item << decl; decl = PropertyDeclaration(QLatin1String("destinationDirectory"), PropertyDeclaration::String); decl.setInitialValueSource(QStringLiteral("buildDirectory")); item << decl; item << PropertyDeclaration(QLatin1String("consoleApplication"), PropertyDeclaration::Boolean); item << PropertyDeclaration(QLatin1String("files"), PropertyDeclaration::Variant, PropertyDeclaration::PropertyNotAvailableInConfig); item << PropertyDeclaration(QLatin1String("excludeFiles"), PropertyDeclaration::Variant, PropertyDeclaration::PropertyNotAvailableInConfig); item << PropertyDeclaration(QLatin1String("qbsSearchPaths"), PropertyDeclaration::StringList); item << PropertyDeclaration(QLatin1String("version"), PropertyDeclaration::String); insert(item); } void BuiltinDeclarations::addProjectItem() { ItemDeclaration item(QLatin1String("Project")); item.setAllowedChildTypes(ItemDeclaration::TypeNames() << QLatin1String("Project") << QLatin1String("PropertyOptions") << QLatin1String("SubProject") << QLatin1String("Product") << QLatin1String("FileTagger") << QLatin1String("Rule")); item << nameProperty(); item << conditionProperty(); item << buildDirProperty(); item << PropertyDeclaration(QLatin1String("minimumQbsVersion"), PropertyDeclaration::String); item << PropertyDeclaration(QLatin1String("sourceDirectory"), PropertyDeclaration::Path); item << PropertyDeclaration(QLatin1String("profile"), PropertyDeclaration::String); item << PropertyDeclaration(QLatin1String("references"), PropertyDeclaration::Variant, PropertyDeclaration::PropertyNotAvailableInConfig); item << PropertyDeclaration(QLatin1String("qbsSearchPaths"), PropertyDeclaration::StringList, PropertyDeclaration::PropertyNotAvailableInConfig); insert(item); } void BuiltinDeclarations::addPropertiesItem() { insert(ItemDeclaration(QLatin1String("Properties"))); } void BuiltinDeclarations::addPropertyOptionsItem() { ItemDeclaration item(QLatin1String("PropertyOptions")); item << nameProperty(); item << PropertyDeclaration(QLatin1String("allowedValues"), PropertyDeclaration::Variant); item << PropertyDeclaration(QLatin1String("description"), PropertyDeclaration::String); insert(item); } void BuiltinDeclarations::addRuleItem() { ItemDeclaration item(QLatin1String("Rule")); item.setAllowedChildTypes(ItemDeclaration::TypeNames() << QLatin1String("Artifact")); item << conditionProperty(); PropertyDeclaration decl(QLatin1String("multiplex"), PropertyDeclaration::Boolean); decl.setInitialValueSource(QLatin1String("false")); item << decl; item << PropertyDeclaration(QLatin1String("name"), PropertyDeclaration::String); item << PropertyDeclaration(QLatin1String("inputs"), PropertyDeclaration::StringList); item << PropertyDeclaration(QLatin1String("outputFileTags"), PropertyDeclaration::StringList); decl = PropertyDeclaration(QLatin1String("outputArtifacts"), PropertyDeclaration::Verbatim); decl.setFunctionArgumentNames( QStringList() << QLatin1String("project") << QLatin1String("product") << QLatin1String("inputs") << QLatin1String("input")); item << decl; decl = PropertyDeclaration(QLatin1String("usings"), PropertyDeclaration::StringList); decl.setDeprecationInfo(DeprecationInfo(Version(1, 5), Tr::tr("Use 'inputsFromDependencies' instead"))); item << decl; item << PropertyDeclaration(QLatin1String("inputsFromDependencies"), PropertyDeclaration::StringList); item << PropertyDeclaration(QLatin1String("auxiliaryInputs"), PropertyDeclaration::StringList); item << PropertyDeclaration(QLatin1String("excludedAuxiliaryInputs"), PropertyDeclaration::StringList); item << PropertyDeclaration(QLatin1String("explicitlyDependsOn"), PropertyDeclaration::StringList); item << prepareScriptProperty(); insert(item); } void BuiltinDeclarations::addSubprojectItem() { ItemDeclaration item(QLatin1String("SubProject")); item.setAllowedChildTypes(ItemDeclaration::TypeNames() << QLatin1String("Project") // needed, because we're adding this internally << QLatin1String("Properties") << QLatin1String("PropertyOptions")); item << PropertyDeclaration(QLatin1String("filePath"), PropertyDeclaration::Path); PropertyDeclaration inheritProperty; inheritProperty.setName(QLatin1String("inheritProperties")); inheritProperty.setType(PropertyDeclaration::Boolean); inheritProperty.setInitialValueSource(QLatin1String("true")); item << inheritProperty; insert(item); } void BuiltinDeclarations::addTransformerItem() { ItemDeclaration item(QLatin1String("Transformer")); item.setAllowedChildTypes(ItemDeclaration::TypeNames() << QLatin1String("Artifact")); item << conditionProperty(); item << PropertyDeclaration(QLatin1String("inputs"), PropertyDeclaration::Variant); item << prepareScriptProperty(); item << PropertyDeclaration(QLatin1String("explicitlyDependsOn"), PropertyDeclaration::StringList); insert(item); } void BuiltinDeclarations::addScannerItem() { ItemDeclaration item(QLatin1String("Scanner")); item << conditionProperty(); item << PropertyDeclaration(QLatin1String("inputs"), PropertyDeclaration::StringList); PropertyDeclaration recursive(QLatin1String("recursive"), PropertyDeclaration::Boolean); recursive.setInitialValueSource(QLatin1String("false")); item << recursive; PropertyDeclaration searchPaths(QLatin1String("searchPaths"), PropertyDeclaration::Verbatim); searchPaths.setFunctionArgumentNames( QStringList() << QLatin1String("project") << QLatin1String("product") << QLatin1String("input")); item << searchPaths; PropertyDeclaration scan(QLatin1String("scan"), PropertyDeclaration::Verbatim); scan.setFunctionArgumentNames( QStringList() << QLatin1String("project") << QLatin1String("product") << QLatin1String("input")); item << scan; insert(item); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/builtindeclarations.h000066400000000000000000000052761266132464200240620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_BUILTINDECLARATIONS_H #define QBS_BUILTINDECLARATIONS_H #include "itemdeclaration.h" #include #include #include namespace qbs { namespace Internal { class BuiltinDeclarations { public: static const BuiltinDeclarations &instance(); Version languageVersion() const; bool containsType(const QString &typeName) const; QStringList allTypeNames() const; ItemDeclaration declarationsForType(const QString &typeName) const; protected: BuiltinDeclarations(); private: void insert(const ItemDeclaration &decl); void addArtifactItem(); void addDependsItem(); void addExportItem(); void addFileTaggerItem(); void addGroupItem(); void addModuleItem(); void addModuleLikeItem(const QString &typeName); void addProbeItem(); void addProductItem(); void addProjectItem(); void addPropertiesItem(); void addPropertyOptionsItem(); void addRuleItem(); void addSubprojectItem(); void addTransformerItem(); void addScannerItem(); const Version m_languageVersion; QMap m_builtins; }; } // namespace Internal } // namespace qbs #endif // QBS_BUILTINDECLARATIONS_H qbs-src-1.4.5/src/lib/corelib/language/builtinvalue.cpp000066400000000000000000000036511266132464200230540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "builtinvalue.h" namespace qbs { namespace Internal { BuiltinValue::BuiltinValue(Builtin builtin) : Value(Value::BuiltinValueType, false) , m_builtin(builtin) { } BuiltinValuePtr BuiltinValue::create(Builtin builtin) { return BuiltinValuePtr(new BuiltinValue(builtin)); } ValuePtr BuiltinValue::clone() const { return BuiltinValuePtr(new BuiltinValue(*this)); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/builtinvalue.h000066400000000000000000000043551266132464200225230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_BUILTINVALUE_H #define QBS_BUILTINVALUE_H #include "value.h" namespace qbs { namespace Internal { class BuiltinValue : public Value { public: enum Builtin { GetNativeSettingFunction, GetEnvFunction, CurrentEnvFunction, CanonicalArchitectureFunction, Rfc1034IdentifierFunction }; static BuiltinValuePtr create(Builtin builtin); void apply(ValueHandler *handler) { handler->handle(this); } ValuePtr clone() const; Builtin builtin() const { return m_builtin; } void setBuiltin(const Builtin &builtin) { m_builtin = builtin; } private: BuiltinValue(Builtin builtin); Builtin m_builtin; }; } // namespace Internal } // namespace qbs #endif // QBS_BUILTINVALUE_H qbs-src-1.4.5/src/lib/corelib/language/deprecationinfo.h000066400000000000000000000044121266132464200231630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_DEPRECATIONINFO_H #define QBS_DEPRECATIONINFO_H #include #include namespace qbs { namespace Internal { class DeprecationInfo { public: explicit DeprecationInfo(const Version &removalVersion, const QString &additionalUserInfo = QString()) : m_removalVersion(removalVersion) , m_additionalUserInfo(additionalUserInfo) {} DeprecationInfo() {} bool isValid() const { return m_removalVersion.isValid(); } Version removalVersion() const { return m_removalVersion; } QString additionalUserInfo() const { return m_additionalUserInfo; } private: Version m_removalVersion; QString m_additionalUserInfo; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.4.5/src/lib/corelib/language/evaluationdata.h000066400000000000000000000036451266132464200230220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_EVALUATIONDATA_H #define QBS_EVALUATIONDATA_H #include #include #include #include namespace qbs { namespace Internal { class Evaluator; class Item; class EvaluationData { public: Evaluator *evaluator; const Item *item; mutable QHash valueCache; }; } // namespace Internal } // namespace qbs #endif // QBS_EVALUATIONDATA_H qbs-src-1.4.5/src/lib/corelib/language/evaluator.cpp000066400000000000000000000167311266132464200223560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "evaluator.h" #include "evaluationdata.h" #include "evaluatorscriptclass.h" #include "filecontext.h" #include "filetags.h" #include "item.h" #include "scriptengine.h" #include #include #include #include #include #include namespace qbs { namespace Internal { Evaluator::Evaluator(ScriptEngine *scriptEngine, const Logger &logger) : m_scriptEngine(scriptEngine) , m_scriptClass(new EvaluatorScriptClass(scriptEngine, logger)) { } Evaluator::~Evaluator() { QHash::iterator it = m_scriptValueMap.begin(); for (; it != m_scriptValueMap.end(); ++it) { EvaluationData *data = attachedPointer(*it); if (data) { if (data->item) data->item->setPropertyObserver(0); delete data; } } delete m_scriptClass; } QScriptValue Evaluator::property(const Item *item, const QString &name) { return scriptValue(item).property(name); } QScriptValue Evaluator::value(const Item *item, const QString &name, bool *propertyWasSet) { QScriptValue v; evaluateProperty(&v, item, name, propertyWasSet); return v; } bool Evaluator::boolValue(const Item *item, const QString &name, bool defaultValue, bool *propertyWasSet) { QScriptValue v; if (!evaluateProperty(&v, item, name, propertyWasSet)) return defaultValue; return v.toBool(); } FileTags Evaluator::fileTagsValue(const Item *item, const QString &name, bool *propertySet) { return FileTags::fromStringList(stringListValue(item, name, propertySet)); } QString Evaluator::stringValue(const Item *item, const QString &name, const QString &defaultValue, bool *propertyWasSet) { QScriptValue v; if (!evaluateProperty(&v, item, name, propertyWasSet)) return defaultValue; return v.toString(); } static QStringList toStringList(const QScriptValue &scriptValue, const Item *item, const QString &propertyName) { if (scriptValue.isString()) { return QStringList(scriptValue.toString()); } else if (scriptValue.isArray()) { QStringList lst; int i = 0; forever { QScriptValue elem = scriptValue.property(i++); if (!elem.isValid()) break; if (elem.isUndefined()) { throw ErrorInfo(Tr::tr("Array element at index %1 is undefined. String expected.") .arg(i - 1), item->property(propertyName)->location()); } if (elem.isArray() || elem.isObject()) { // Let's assume all other JS types are convertible to string. throw ErrorInfo(Tr::tr("Expected array element of type String at index %1.") .arg(i - 1), item->property(propertyName)->location()); } lst.append(elem.toString()); } return lst; } return QStringList(); } QStringList Evaluator::stringListValue(const Item *item, const QString &name, bool *propertyWasSet) { QScriptValue v = property(item, name); if (propertyWasSet) *propertyWasSet = v.isValid() && !v.isUndefined(); handleEvaluationError(item, name, v); return toStringList(v, item, name); } QScriptValue Evaluator::scriptValue(const Item *item) { QScriptValue &scriptValue = m_scriptValueMap[item]; if (scriptValue.isObject()) { // already initialized return scriptValue; } EvaluationData *edata = new EvaluationData; edata->evaluator = this; edata->item = item; edata->item->setPropertyObserver(this); scriptValue = m_scriptEngine->newObject(m_scriptClass); attachPointerTo(scriptValue, edata); return scriptValue; } void Evaluator::onItemPropertyChanged(Item *item) { EvaluationData *data = attachedPointer(m_scriptValueMap.value(item)); if (data) data->valueCache.clear(); } void Evaluator::onItemDestroyed(Item *item) { delete attachedPointer(m_scriptValueMap.value(item)); m_scriptValueMap.remove(item); } void Evaluator::handleEvaluationError(const Item *item, const QString &name, const QScriptValue &scriptValue) { if (Q_LIKELY(!m_scriptEngine->hasErrorOrException(scriptValue))) return; const ValueConstPtr value = item->property(name); CodeLocation location = value ? value->location() : CodeLocation(); if (m_scriptEngine->hasUncaughtException()) { throw ErrorInfo(m_scriptEngine->uncaughtException().toString(), CodeLocation(location.filePath(), m_scriptEngine->uncaughtExceptionLineNumber())); } throw ErrorInfo(scriptValue.toString(), location); } bool Evaluator::evaluateProperty(QScriptValue *result, const Item *item, const QString &name, bool *propertyWasSet) { *result = property(item, name); handleEvaluationError(item, name, *result); if (!result->isValid() || result->isUndefined()) { if (propertyWasSet) *propertyWasSet = false; return false; } if (propertyWasSet) *propertyWasSet = true; return true; } QScriptValue Evaluator::fileScope(const FileContextConstPtr &file) { QScriptValue &result = m_fileScopeMap[file]; if (result.isObject()) { // already initialized return result; } if (file->idScope()) result = scriptValue(file->idScope()); else result = m_scriptEngine->newObject(); result.setProperty(QLatin1String("filePath"), file->filePath()); result.setProperty(QLatin1String("path"), file->dirPath()); m_scriptEngine->import(file, result, result); JsExtensions::setupExtensions(file->jsExtensions(), result); return result; } void Evaluator::setCachingEnabled(bool enabled) { m_scriptClass->setValueCacheEnabled(enabled); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/evaluator.h000066400000000000000000000065241266132464200220220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_EVALUATOR_H #define QBS_EVALUATOR_H #include "forward_decls.h" #include "itemobserver.h" #include #include namespace qbs { namespace Internal { class EvaluatorScriptClass; class FileTags; class Logger; class ScriptEngine; class Evaluator : private ItemObserver { friend class SVConverter; public: Evaluator(ScriptEngine *scriptEngine, const Logger &logger); virtual ~Evaluator(); ScriptEngine *engine() const { return m_scriptEngine; } QScriptValue property(const Item *item, const QString &name); QScriptValue value(const Item *item, const QString &name, bool *propertySet = 0); bool boolValue(const Item *item, const QString &name, bool defaultValue = false, bool *propertyWasSet = 0); FileTags fileTagsValue(const Item *item, const QString &name, bool *propertySet = 0); QString stringValue(const Item *item, const QString &name, const QString &defaultValue = QString(), bool *propertyWasSet = 0); QStringList stringListValue(const Item *item, const QString &name, bool *propertyWasSet = 0); QScriptValue scriptValue(const Item *item); QScriptValue fileScope(const FileContextConstPtr &file); void setCachingEnabled(bool enabled); void handleEvaluationError(const Item *item, const QString &name, const QScriptValue &scriptValue); private: void onItemPropertyChanged(Item *item); void onItemDestroyed(Item *item); bool evaluateProperty(QScriptValue *result, const Item *item, const QString &name, bool *propertyWasSet); ScriptEngine *m_scriptEngine; EvaluatorScriptClass *m_scriptClass; mutable QHash m_scriptValueMap; mutable QHash m_fileScopeMap; }; } // namespace Internal } // namespace qbs #endif // QBS_EVALUATOR_H qbs-src-1.4.5/src/lib/corelib/language/evaluatorscriptclass.cpp000066400000000000000000000566311266132464200246340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "evaluatorscriptclass.h" #include "evaluationdata.h" #include "evaluator.h" #include "filecontext.h" #include "item.h" #include "scriptengine.h" #include "propertydeclaration.h" #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class SVConverter : ValueHandler { EvaluatorScriptClass * const scriptClass; ScriptEngine * const engine; QScriptContext * const scriptContext; const QScriptValue * const object; const ValuePtr &valuePtr; const Item * const itemOfProperty; const QScriptString * const propertyName; const EvaluationData * const data; QScriptValue * const result; QStack * const sourceValueStack; char pushedScopesCount; public: SVConverter(EvaluatorScriptClass *esc, const QScriptValue *obj, const ValuePtr &v, const Item *_itemOfProperty, const QScriptString *propertyName, const EvaluationData *data, QScriptValue *result, QStack *sourceValueStack) : scriptClass(esc) , engine(static_cast(esc->engine())) , scriptContext(esc->engine()->currentContext()) , object(obj) , valuePtr(v) , itemOfProperty(_itemOfProperty) , propertyName(propertyName) , data(data) , result(result) , sourceValueStack(sourceValueStack) , pushedScopesCount(0) { } void start() { valuePtr->apply(this); } private: void setupConvenienceProperty(const QString &conveniencePropertyName, QScriptValue *extraScope, const QScriptValue &scriptValue) { if (!extraScope->isObject()) *extraScope = scriptClass->engine()->newObject(); if (!scriptValue.isValid() || scriptValue.isUndefined()) { // If there's no such value, use an empty array to have the convenience property // still available. extraScope->setProperty(conveniencePropertyName, engine->newArray()); } else { extraScope->setProperty(conveniencePropertyName, scriptValue); } } void pushScope(const QScriptValue &scope) { if (scope.isObject()) { scriptContext->pushScope(scope); ++pushedScopesCount; } } void pushItemScopes(const Item *item) { const Item *scope = item->scope(); if (scope) { pushItemScopes(scope); pushScope(data->evaluator->scriptValue(scope)); } } void popScopes() { for (; pushedScopesCount; --pushedScopesCount) scriptContext->popScope(); } void handle(JSSourceValue *value) { const Item *conditionScopeItem = 0; QScriptValue conditionScope; QScriptValue conditionFileScope; Item *outerItem = data->item->outerItem(); for (int i = 0; i < value->alternatives().count(); ++i) { const JSSourceValue::Alternative *alternative = 0; alternative = &value->alternatives().at(i); if (!conditionScopeItem) { // We have to differentiate between module instances and normal items here. // // The module instance case: // Product { // property bool something: true // Properties { // condition: something // cpp.defines: ["ABC"] // } // } // // data->item points to cpp and the condition's scope chain must contain cpp's // scope, which is the item where cpp is instantiated. The scope chain must not // contain data->item itself. // // The normal item case: // Product { // property bool something: true // property string value: "ABC" // Properties { // condition: something // value: "DEF" // } // } // // data->item points to the product and the condition's scope chain must contain // the product item. conditionScopeItem = data->item->isModuleInstance() ? data->item->scope() : data->item; conditionScope = data->evaluator->scriptValue(conditionScopeItem); QBS_ASSERT(conditionScope.isObject(), return); conditionFileScope = data->evaluator->fileScope(conditionScopeItem->file()); } engine->currentContext()->pushScope(conditionFileScope); pushItemScopes(conditionScopeItem); if (alternative->value->definingItem()) pushItemScopes(alternative->value->definingItem()); engine->currentContext()->pushScope(conditionScope); const QScriptValue cr = engine->evaluate(alternative->condition); engine->currentContext()->popScope(); engine->currentContext()->popScope(); popScopes(); if (engine->hasErrorOrException(cr)) { *result = engine->lastErrorValue(cr); return; } if (cr.toBool()) { // condition is true, let's use the value of this alternative if (alternative->value->sourceUsesOuter() && !outerItem) { // Clone value but without alternatives. JSSourceValuePtr outerValue = JSSourceValue::create(); outerValue->setFile(value->file()); outerValue->setHasFunctionForm(value->hasFunctionForm()); outerValue->setSourceCode(value->sourceCode()); outerValue->setBaseValue(value->baseValue()); if (value->sourceUsesBase()) outerValue->setSourceUsesBaseFlag(); outerValue->setLocation(value->line(), value->column()); outerItem = Item::create(data->item->pool()); outerItem->setProperty(propertyName->toString(), outerValue); } value = alternative->value.data(); break; } } QScriptValue extraScope; if (value->sourceUsesBase()) { QScriptValue baseValue; if (value->baseValue()) { SVConverter converter(scriptClass, object, value->baseValue(), itemOfProperty, propertyName, data, &baseValue, sourceValueStack); converter.start(); } setupConvenienceProperty(QLatin1String("base"), &extraScope, baseValue); } if (value->sourceUsesOuter() && outerItem) { const QScriptValue v = data->evaluator->property(outerItem, *propertyName); if (engine->hasErrorOrException(v)) { *result = engine->lastErrorValue(v); return; } setupConvenienceProperty(QLatin1String("outer"), &extraScope, v); } if (value->sourceUsesOriginal()) { const Item *item = itemOfProperty; while (item->isModuleInstance()) item = item->prototype(); QScriptValue originalValue; SVConverter converter(scriptClass, object, item->property(*propertyName), item, propertyName, data, &originalValue, sourceValueStack); converter.start(); setupConvenienceProperty(QLatin1String("original"), &extraScope, originalValue); } pushScope(data->evaluator->fileScope(value->file())); pushItemScopes(data->item); if (value->definingItem()) pushItemScopes(value->definingItem()); if (itemOfProperty && !itemOfProperty->isModuleInstance()) { // Own properties of module instances must not have the instance itself in the scope. pushScope(*object); } if (value->exportScope()) pushScope(data->evaluator->scriptValue(value->exportScope())); pushScope(extraScope); *result = engine->evaluate(value->sourceCodeForEvaluation(), value->file()->filePath(), value->line()); popScopes(); } void handle(ItemValue *value) { Item *item = value->item(); if (!item) qDebug() << "SVConverter got null item" << propertyName->toString(); *result = data->evaluator->scriptValue(item); if (!result->isValid()) qDebug() << "SVConverter returned invalid script value."; } void handle(VariantValue *variantValue) { *result = scriptClass->engine()->toScriptValue(variantValue->value()); } void handle(BuiltinValue *builtinValue) { *result = scriptClass->scriptValueForBuiltin(builtinValue->builtin()); } }; bool debugProperties = false; enum QueryPropertyType { QPTDefault, QPTParentProperty }; EvaluatorScriptClass::EvaluatorScriptClass(ScriptEngine *scriptEngine, const Logger &logger) : QScriptClass(scriptEngine) , m_logger(logger) , m_valueCacheEnabled(false) { m_getNativeSettingBuiltin = scriptEngine->newFunction(js_getNativeSetting, 3); m_getEnvBuiltin = scriptEngine->newFunction(js_getEnv, 1); m_currentEnvBuiltin = scriptEngine->newFunction(js_currentEnv, 0); m_canonicalArchitectureBuiltin = scriptEngine->newFunction(js_canonicalArchitecture, 1); m_rfc1034identifierBuiltin = scriptEngine->newFunction(js_rfc1034identifier, 1); m_getHashBuiltin = scriptEngine->newFunction(js_getHash, 1); } QScriptClass::QueryFlags EvaluatorScriptClass::queryProperty(const QScriptValue &object, const QScriptString &name, QScriptClass::QueryFlags flags, uint *id) { Q_UNUSED(flags); // We assume that it's safe to save the result of the query in a member of the scriptclass. // It must be cleared in the property method before doing any further lookup. QBS_ASSERT(m_queryResult.isNull(), return QueryFlags()); if (debugProperties) qDebug() << "[SC] queryProperty " << object.objectId() << " " << name; EvaluationData *const data = attachedPointer(object); const QString nameString = name.toString(); if (nameString == QLatin1String("parent")) { *id = QPTParentProperty; m_queryResult.data = data; return QScriptClass::HandlesReadAccess; } *id = QPTDefault; if (!data) { if (debugProperties) qDebug() << "[SC] queryProperty: no data attached"; return QScriptClass::QueryFlags(); } return queryItemProperty(data, nameString); } QScriptClass::QueryFlags EvaluatorScriptClass::queryItemProperty(const EvaluationData *data, const QString &name, bool ignoreParent) { for (const Item *item = data->item; item; item = item->prototype()) { m_queryResult.value = item->properties().value(name); if (!m_queryResult.value.isNull()) { m_queryResult.data = data; m_queryResult.itemOfProperty = item; return HandlesReadAccess; } } if (!ignoreParent && data->item && data->item->parent()) { if (debugProperties) qDebug() << "[SC] queryProperty: query parent"; EvaluationData parentdata = *data; parentdata.item = data->item->parent(); const QueryFlags qf = queryItemProperty(&parentdata, name, true); if (qf.testFlag(HandlesReadAccess)) { m_queryResult.data = data; return qf; } } if (debugProperties) qDebug() << "[SC] queryProperty: no such property"; return QScriptClass::QueryFlags(); } QString EvaluatorScriptClass::resultToString(const QScriptValue &scriptValue) { return (scriptValue.isObject() ? QLatin1String("[Object: ") + QString::number(scriptValue.objectId(), 16) + QLatin1Char(']') : scriptValue.toVariant().toString()); } Item *EvaluatorScriptClass::findParentOfType(const Item *item, const QString &typeName) { for (Item *it = item->parent(); it; it = it->parent()) { if (it->typeName() == typeName) return it; } return 0; } void EvaluatorScriptClass::collectValuesFromNextChain(const EvaluationData *data, QScriptValue *result, const QString &propertyName, const ValuePtr &value) { QScriptValueList lst; QSet oldNextChain = m_currentNextChain; for (ValuePtr next = value; next; next = next->next()) m_currentNextChain.insert(next.data()); for (ValuePtr next = value; next; next = next->next()) { QScriptValue v = data->evaluator->property(next->definingItem(), propertyName); ScriptEngine * const se = static_cast(engine()); if (se->hasErrorOrException(v)) { *result = se->lastErrorValue(v); return; } if (v.isUndefined()) continue; lst << v; } m_currentNextChain = oldNextChain; *result = engine()->newArray(); quint32 k = 0; for (int i = 0; i < lst.count(); ++i) { const QScriptValue &v = lst.at(i); QBS_ASSERT(!v.isError(), continue); if (v.isArray()) { const quint32 vlen = v.property(QStringLiteral("length")).toInt32(); for (quint32 j = 0; j < vlen; ++j) result->setProperty(k++, v.property(j)); } else { result->setProperty(k++, v); } } } static QString overriddenSourceDirectory(const Item *item) { const VariantValuePtr v = item->variantProperty(QLatin1String("_qbs_sourceDir")); return v ? v->value().toString() : QString(); } inline void convertToPropertyType(const Item *item, const PropertyDeclaration::Type t, QScriptValue &v) { if (v.isUndefined()) return; switch (t) { case PropertyDeclaration::UnknownType: case PropertyDeclaration::Variant: case PropertyDeclaration::Verbatim: break; case PropertyDeclaration::Boolean: if (!v.isBool()) v = v.toBool(); break; case PropertyDeclaration::Integer: if (!v.isNumber()) v = v.toNumber(); break; case PropertyDeclaration::Path: { if (!v.isString()) v = v.toString(); const QString srcDir = overriddenSourceDirectory(item); if (!srcDir.isEmpty()) v = v.engine()->toScriptValue(FileInfo::resolvePath(srcDir, v.toString())); break; } case PropertyDeclaration::String: if (!v.isString()) v = v.toString(); break; case PropertyDeclaration::PathList: { if (!v.isArray()) { QScriptValue x = v.engine()->newArray(1); x.setProperty(0, v.isString() ? v : v.toString()); v = x; } const QString srcDir = overriddenSourceDirectory(item); if (srcDir.isEmpty()) break; const quint32 c = v.property(QLatin1String("length")).toUInt32(); for (quint32 i = 0; i < c; ++i) { QScriptValue elem = v.property(i); elem = v.engine()->toScriptValue(FileInfo::resolvePath(srcDir, elem.toString())); v.setProperty(i, elem); } break; } case PropertyDeclaration::StringList: if (!v.isArray()) { QScriptValue x = v.engine()->newArray(1); x.setProperty(0, v.isString() ? v : v.toString()); v = x; } break; } } QScriptValue EvaluatorScriptClass::property(const QScriptValue &object, const QScriptString &name, uint id) { const EvaluationData *data = m_queryResult.data; const Item * const itemOfProperty = m_queryResult.itemOfProperty; m_queryResult.data = 0; m_queryResult.itemOfProperty = 0; QBS_ASSERT(data, return QScriptValue()); const QueryPropertyType qpt = static_cast(id); if (qpt == QPTParentProperty) { return data->item->parent() ? data->evaluator->scriptValue(data->item->parent()) : engine()->undefinedValue(); } ValuePtr value; m_queryResult.value.swap(value); QBS_ASSERT(value, return QScriptValue()); QBS_ASSERT(m_queryResult.isNull(), return QScriptValue()); if (debugProperties) qDebug() << "[SC] property " << name; QScriptValue result; if (m_valueCacheEnabled) { result = data->valueCache.value(name); if (result.isValid()) { if (debugProperties) qDebug() << "[SC] cache hit " << name << ": " << resultToString(result); return result; } } if (value->next() && !m_currentNextChain.contains(value.data())) { collectValuesFromNextChain(data, &result, name.toString(), value); } else { SVConverter converter(this, &object, value, itemOfProperty, &name, data, &result, &m_sourceValueStack); converter.start(); const PropertyDeclaration decl = data->item->propertyDeclaration(name.toString()); convertToPropertyType(data->item, decl.type(), result); } if (debugProperties) qDebug() << "[SC] cache miss " << name << ": " << resultToString(result); if (m_valueCacheEnabled) data->valueCache.insert(name, result); return result; } void EvaluatorScriptClass::setValueCacheEnabled(bool enabled) { m_valueCacheEnabled = enabled; } QScriptValue EvaluatorScriptClass::scriptValueForBuiltin(BuiltinValue::Builtin builtin) const { switch (builtin) { case BuiltinValue::GetNativeSettingFunction: return m_getNativeSettingBuiltin; case BuiltinValue::GetEnvFunction: return m_getEnvBuiltin; case BuiltinValue::CurrentEnvFunction: return m_currentEnvBuiltin; case BuiltinValue::CanonicalArchitectureFunction: return m_canonicalArchitectureBuiltin; case BuiltinValue::Rfc1034IdentifierFunction: return m_rfc1034identifierBuiltin; } QBS_ASSERT(!"unhandled builtin", ;); return QScriptValue(); } QScriptValue EvaluatorScriptClass::js_getNativeSetting(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(context->argumentCount() < 1 || context->argumentCount() > 3)) { return context->throwError(QScriptContext::SyntaxError, QLatin1String("getNativeSetting expects between 1 and 3 arguments")); } QString key = context->argumentCount() > 1 ? context->argument(1).toString() : QString(); // We'll let empty string represent the default registry value if (HostOsInfo::isWindowsHost() && key.isEmpty()) key = QLatin1String("."); QVariant defaultValue = context->argumentCount() > 2 ? context->argument(2).toVariant() : QVariant(); QSettings settings(context->argument(0).toString(), QSettings::NativeFormat); QVariant value = settings.value(key, defaultValue); return value.isNull() ? engine->undefinedValue() : engine->toScriptValue(value); } QScriptValue EvaluatorScriptClass::js_getEnv(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, QLatin1String("getEnv expects 1 argument")); } const QString name = context->argument(0).toString(); ScriptEngine * const e = static_cast(engine); const QString value = e->environment().value(name); e->addEnvironmentVariable(name, value); return value.isNull() ? engine->undefinedValue() : value; } QScriptValue EvaluatorScriptClass::js_currentEnv(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(context); const QProcessEnvironment env = static_cast(engine)->environment(); QScriptValue envObject = engine->newObject(); foreach (const QString &key, env.keys()) envObject.setProperty(key, QScriptValue(env.value(key))); return envObject; } QScriptValue EvaluatorScriptClass::js_canonicalArchitecture(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, QLatin1String("canonicalArchitecture expects 1 argument")); } const QString architecture = context->argument(0).toString(); return engine->toScriptValue(canonicalArchitecture(architecture)); } QScriptValue EvaluatorScriptClass::js_rfc1034identifier(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, QLatin1String("rfc1034Identifier expects 1 argument")); } const QString identifier = context->argument(0).toString(); return engine->toScriptValue(HostOsInfo::rfc1034Identifier(identifier)); } QScriptValue EvaluatorScriptClass::js_getHash(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(context->argumentCount() < 1)) { return context->throwError(QScriptContext::SyntaxError, QLatin1String("getHash expects 1 argument")); } const QByteArray input = context->argument(0).toString().toLatin1(); const QByteArray hash = QCryptographicHash::hash(input, QCryptographicHash::Sha1).toHex().left(16); return engine->toScriptValue(QString::fromLatin1(hash)); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/evaluatorscriptclass.h000066400000000000000000000102211266132464200242620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_EVALUATORSCRIPTCLASS_H #define QBS_EVALUATORSCRIPTCLASS_H #include "builtinvalue.h" #include "forward_decls.h" #include #include #include QT_BEGIN_NAMESPACE class QScriptContext; QT_END_NAMESPACE namespace qbs { namespace Internal { class EvaluationData; class ScriptEngine; class EvaluatorScriptClass : public QScriptClass { public: EvaluatorScriptClass(ScriptEngine *scriptEngine, const Logger &logger); QueryFlags queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id); QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id); void setValueCacheEnabled(bool enabled); QScriptValue scriptValueForBuiltin(BuiltinValue::Builtin builtin) const; static QScriptValue js_getNativeSetting(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_getEnv(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_currentEnv(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_canonicalArchitecture(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_rfc1034identifier(QScriptContext *context, QScriptEngine *engine); static QScriptValue js_getHash(QScriptContext *context, QScriptEngine *engine); private: QueryFlags queryItemProperty(const EvaluationData *data, const QString &name, bool ignoreParent = false); static QString resultToString(const QScriptValue &scriptValue); static Item *findParentOfType(const Item *item, const QString &typeName); void collectValuesFromNextChain(const EvaluationData *data, QScriptValue *result, const QString &propertyName, const ValuePtr &value); struct QueryResult { QueryResult() : data(0), itemOfProperty(0) {} bool isNull() const { return !data; } const EvaluationData *data; const Item *itemOfProperty; // The item that owns the property. ValuePtr value; }; QueryResult m_queryResult; Logger m_logger; bool m_valueCacheEnabled; QScriptValue m_getNativeSettingBuiltin; QScriptValue m_getEnvBuiltin; QScriptValue m_currentEnvBuiltin; QScriptValue m_canonicalArchitectureBuiltin; QScriptValue m_rfc1034identifierBuiltin; QScriptValue m_getHashBuiltin; QStack m_sourceValueStack; QSet m_currentNextChain; }; } // namespace Internal } // namespace qbs #endif // QBS_EVALUATORSCRIPTCLASS_H qbs-src-1.4.5/src/lib/corelib/language/filecontext.cpp000066400000000000000000000036701266132464200226760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "filecontext.h" #include "item.h" namespace qbs { namespace Internal { FileContext::FileContext() : m_idScope(0) { } FileContextPtr FileContext::create() { return FileContextPtr(new FileContext); } void FileContext::ensureIdScope(ItemPool *itemPool) { if (!m_idScope) { m_idScope = Item::create(itemPool); m_idScope->setTypeName(QLatin1String("IdScope")); } } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/filecontext.h000066400000000000000000000037331266132464200223430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_FILECONTEXT_H #define QBS_FILECONTEXT_H #include "filecontextbase.h" #include "forward_decls.h" namespace qbs { namespace Internal { class Item; class ItemPool; class FileContext : public FileContextBase { public: static FileContextPtr create(); Item *idScope() const { return m_idScope; } void ensureIdScope(ItemPool *itemPool); private: FileContext(); Item *m_idScope; }; } // namespace Internal } // namespace qbs #endif // QBS_FILECONTEXT_H qbs-src-1.4.5/src/lib/corelib/language/filecontextbase.cpp000066400000000000000000000036671266132464200235370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "filecontextbase.h" #include namespace qbs { namespace Internal { QString FileContextBase::dirPath() const { return FileInfo::path(m_filePath); } FileContextBase::FileContextBase(const FileContextBase &other) : m_filePath(other.m_filePath) , m_jsImports(other.m_jsImports) , m_jsExtensions(other.m_jsExtensions) , m_searchPaths(other.m_searchPaths) { } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/filecontextbase.h000066400000000000000000000052021266132464200231670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_FILECONTEXTBASE_H #define QBS_FILECONTEXTBASE_H #include "jsimports.h" namespace qbs { namespace Internal { class FileContextBase { public: void setFilePath(const QString &filePath) { m_filePath = filePath; } QString filePath() const { return m_filePath; } void setContent(const QString &content) { m_content = content; } const QString &content() const { return m_content; } void addJsImport(const JsImport &jsImport) { m_jsImports << jsImport; } JsImports jsImports() const { return m_jsImports; } void addJsExtension(const QString &extension) { m_jsExtensions << extension; } QStringList jsExtensions() const { return m_jsExtensions; } void setSearchPaths(const QStringList &paths) { m_searchPaths = paths; } QStringList searchPaths() const { return m_searchPaths; } QString dirPath() const; protected: FileContextBase() {} FileContextBase(const FileContextBase &other); QString m_filePath; QString m_content; JsImports m_jsImports; QStringList m_jsExtensions; QStringList m_searchPaths; }; } // namespace Internal } // namespace qbs #endif // QBS_FILECONTEXTBASE_H qbs-src-1.4.5/src/lib/corelib/language/filetags.cpp000066400000000000000000000060351266132464200221460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "filetags.h" #include namespace qbs { namespace Internal { void FileTag::clear() { Id::operator=(Id()); } QStringList FileTags::toStringList() const { QStringList strlst; foreach (const FileTag &tag, *this) strlst += tag.toString(); return strlst; } FileTags FileTags::fromStringList(const QStringList &strings) { FileTags result; foreach (const QString &str, strings) result += FileTag(str.toLocal8Bit()); return result; } /*! * \return \c{true} if this file tags set has file tags in common with \c{other}. */ bool FileTags::matches(const FileTags &other) const { for (FileTags::const_iterator it = other.begin(); it != other.end(); ++it) if (contains(*it)) return true; return false; } LogWriter operator <<(LogWriter w, const FileTags &tags) { bool firstLoop = true; w.write('('); foreach (const FileTag &tag, tags) { if (firstLoop) firstLoop = false; else w.write(QLatin1String(", ")); w.write(tag.toString()); } w.write(')'); return w; } QDataStream &operator >>(QDataStream &s, FileTags &tags) { int i; s >> i; tags.clear(); tags.reserve(i); QVariant v; while (--i >= 0) { s >> v; tags += FileTag::fromSetting(v); } return s; } QDataStream &operator <<(QDataStream &s, const FileTags &tags) { s << tags.count(); foreach (const FileTag &ft, tags) s << ft.toSetting(); return s; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/filetags.h000066400000000000000000000045751266132464200216220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_FILETAGS_H #define QBS_FILETAGS_H #include #include #include #include namespace qbs { namespace Internal { class FileTag : public Id { public: FileTag() : Id() {} FileTag(const Id &other) : Id(other) {} FileTag(const char *str) : Id(str) {} explicit FileTag(const QByteArray &ba) : Id(ba) {} void clear(); }; class FileTags : public QSet { public: QStringList toStringList() const; static FileTags fromStringList(const QStringList &strings); bool matches(const FileTags &other) const; }; LogWriter operator <<(LogWriter w, const FileTags &tags); QDataStream &operator >>(QDataStream &s, FileTags & tags); QDataStream &operator <<(QDataStream &s, const FileTags &tags); } // namespace Internal } // namespace qbs #endif // QBS_FILETAGS_H qbs-src-1.4.5/src/lib/corelib/language/forward_decls.h000066400000000000000000000115311266132464200226300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_LANG_FORWARD_DECLS_H #define QBS_LANG_FORWARD_DECLS_H #include namespace qbs { namespace Internal { class Value; typedef QSharedPointer ValuePtr; typedef QSharedPointer ValueConstPtr; class ItemValue; typedef QSharedPointer ItemValuePtr; typedef QSharedPointer ItemValueConstPtr; class JSSourceValue; typedef QSharedPointer JSSourceValuePtr; typedef QSharedPointer JSSourceValueConstPtr; class VariantValue; typedef QSharedPointer VariantValuePtr; typedef QSharedPointer VariantValueConstPtr; class BuiltinValue; typedef QSharedPointer BuiltinValuePtr; typedef QSharedPointer BuiltinValueConstPtr; class FileContext; typedef QSharedPointer FileContextPtr; typedef QSharedPointer FileContextConstPtr; class FileContextBase; typedef QSharedPointer FileContextBasePtr; typedef QSharedPointer FileContextBaseConstPtr; class PropertyMapInternal; typedef QSharedPointer PropertyMapPtr; typedef QSharedPointer PropertyMapConstPtr; class FileTagger; typedef QSharedPointer FileTaggerPtr; typedef QSharedPointer FileTaggerConstPtr; class ResolvedProduct; typedef QSharedPointer ResolvedProductPtr; typedef QSharedPointer ResolvedProductConstPtr; class ResolvedProject; typedef QSharedPointer ResolvedProjectPtr; typedef QSharedPointer ResolvedProjectConstPtr; class TopLevelProject; typedef QSharedPointer TopLevelProjectPtr; typedef QSharedPointer TopLevelProjectConstPtr; class ResolvedFileContext; typedef QSharedPointer ResolvedFileContextPtr; typedef QSharedPointer ResolvedFileContextConstPtr; class Rule; typedef QSharedPointer RulePtr; typedef QSharedPointer RuleConstPtr; class ResolvedScanner; typedef QSharedPointer ResolvedScannerPtr; typedef QSharedPointer ResolvedScannerConstPtr; class SourceArtifactInternal; typedef QSharedPointer SourceArtifactPtr; typedef QSharedPointer SourceArtifactConstPtr; class ScriptFunction; typedef QSharedPointer ScriptFunctionPtr; typedef QSharedPointer ScriptFunctionConstPtr; class RuleArtifact; typedef QSharedPointer RuleArtifactPtr; typedef QSharedPointer RuleArtifactConstPtr; class ResolvedModule; typedef QSharedPointer ResolvedModulePtr; typedef QSharedPointer ResolvedModuleConstPtr; class ResolvedGroup; typedef QSharedPointer GroupPtr; typedef QSharedPointer GroupConstPtr; class ResolvedTransformer; typedef QSharedPointer ResolvedTransformerPtr; typedef QSharedPointer ResolvedTransformerConstPtr; class ArtifactProperties; typedef QSharedPointer ArtifactPropertiesPtr; typedef QSharedPointer ArtifactPropertiesConstPtr; } // namespace Internal } // namespace qbs #endif // QBS_LANG_FORWARD_DECLS_H qbs-src-1.4.5/src/lib/corelib/language/functiondeclaration.h000066400000000000000000000044011266132464200240430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_FUNCTIONDECLARATION_H #define QBS_FUNCTIONDECLARATION_H #include #include namespace qbs { namespace Internal { class FunctionDeclaration { public: FunctionDeclaration() {} void setName(const QString &name) { m_name = name; } const QString &name() const { return m_name; } void setSourceCode(const QString &code) { m_sourceCode = code; } const QString &sourceCode() const { return m_sourceCode; } void setLocation(const CodeLocation &location) { m_location = location; } const CodeLocation &location() const { return m_location; } private: QString m_name; QString m_sourceCode; CodeLocation m_location; }; } // namespace Internal } // namespace qbs #endif // QBS_FUNCTIONDECLARATION_H qbs-src-1.4.5/src/lib/corelib/language/identifiersearch.cpp000066400000000000000000000045011266132464200236540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "identifiersearch.h" #include namespace qbs { namespace Internal { IdentifierSearch::IdentifierSearch() { } void IdentifierSearch::start(QbsQmlJS::AST::Node *node) { foreach (bool *found, m_requests) *found = false; m_numberOfFoundIds = 0; node->accept(this); } void IdentifierSearch::add(const QString &name, bool *found) { m_requests.insert(name, found); } bool IdentifierSearch::preVisit(QbsQmlJS::AST::Node *) { return m_numberOfFoundIds < m_requests.count(); } bool IdentifierSearch::visit(QbsQmlJS::AST::IdentifierExpression *e) { bool *found = m_requests.value(e->name.toString()); if (found && !*found) { *found = true; m_numberOfFoundIds++; } return m_numberOfFoundIds < m_requests.count(); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/identifiersearch.h000066400000000000000000000042211266132464200233200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_IDENTIFIERSEARCHVISITOR_H #define QBS_IDENTIFIERSEARCHVISITOR_H #include #include #include #include namespace qbs { namespace Internal { class IdentifierSearch : private QbsQmlJS::AST::Visitor { public: IdentifierSearch(); void start(QbsQmlJS::AST::Node *node); void add(const QString &name, bool *found); private: bool preVisit(QbsQmlJS::AST::Node *); bool visit(QbsQmlJS::AST::IdentifierExpression *e); QMap m_requests; int m_numberOfFoundIds; }; } // namespace Internal } // namespace qbs #endif // QBS_IDENTIFIERSEARCHVISITOR_H qbs-src-1.4.5/src/lib/corelib/language/item.cpp000066400000000000000000000245461266132464200213150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "item.h" #include "builtindeclarations.h" #include "deprecationinfo.h" #include "filecontext.h" #include "itemobserver.h" #include "itempool.h" #include "value.h" #include #include #include #include #include namespace qbs { namespace Internal { Item::Item(ItemPool *pool) : m_pool(pool) , m_propertyObserver(0) , m_moduleInstance(false) , m_prototype(0) , m_scope(0) , m_outerItem(0) , m_parent(0) { } Item::~Item() { if (m_propertyObserver) m_propertyObserver->onItemDestroyed(this); } Item *Item::create(ItemPool *pool) { return pool->allocateItem(); } Item *Item::clone() const { Item *dup = create(pool()); dup->m_id = m_id; dup->m_typeName = m_typeName; dup->m_location = m_location; dup->m_moduleInstance = m_moduleInstance; dup->m_prototype = m_prototype; dup->m_scope = m_scope; dup->m_outerItem = m_outerItem; dup->m_parent = m_parent; dup->m_file = m_file; dup->m_propertyDeclarations = m_propertyDeclarations; dup->m_functions = m_functions; dup->m_modules = m_modules; dup->m_children.reserve(m_children.count()); foreach (const Item *child, m_children) { Item *clonedChild = child->clone(); clonedChild->m_parent = dup; dup->m_children.append(clonedChild); } for (PropertyMap::const_iterator it = m_properties.constBegin(); it != m_properties.constEnd(); ++it) { dup->m_properties.insert(it.key(), it.value()->clone()); } return dup; } bool Item::hasProperty(const QString &name) const { for (const Item *item = this; item; item = item->m_prototype) if (item->m_properties.contains(name)) return true; return false; } bool Item::hasOwnProperty(const QString &name) const { return m_properties.contains(name); } ValuePtr Item::property(const QString &name) const { ValuePtr value; for (const Item *item = this; item; item = item->m_prototype) if ((value = item->m_properties.value(name))) break; return value; } ItemValuePtr Item::itemProperty(const QString &name, bool create) { ItemValuePtr result; ValuePtr v = property(name); if (v && v->type() == Value::ItemValueType) { result = v.staticCast(); } else if (create) { result = ItemValue::create(Item::create(m_pool)); setProperty(name, result); } return result; } JSSourceValuePtr Item::sourceProperty(const QString &name) const { ValuePtr v = property(name); if (!v || v->type() != Value::JSSourceValueType) return JSSourceValuePtr(); return v.staticCast(); } VariantValuePtr Item::variantProperty(const QString &name) const { ValuePtr v = property(name); if (!v || v->type() != Value::VariantValueType) return VariantValuePtr(); return v.staticCast(); } PropertyDeclaration Item::propertyDeclaration(const QString &name) const { const PropertyDeclaration decl = m_propertyDeclarations.value(name); return (!decl.isValid() && m_prototype) ? m_prototype->propertyDeclaration(name) : decl; } void Item::addModule(const Item::Module &module) { const auto it = std::lower_bound(m_modules.begin(), m_modules.end(), module); m_modules.insert(it, module); } void Item::setPropertyObserver(ItemObserver *observer) const { QBS_ASSERT(!observer || !m_propertyObserver, return); // warn if accidentally overwritten m_propertyObserver = observer; } void Item::setProperty(const QString &name, const ValuePtr &value) { m_properties.insert(name, value); if (m_propertyObserver) m_propertyObserver->onItemPropertyChanged(this); } void Item::dump() const { dump(0); } bool Item::isPresentModule() const { // Initial value is "true" as JS source, overwritten one is always QVariant(false). const ValueConstPtr v = property(QLatin1String("present")); return v && v->type() == Value::JSSourceValueType; } void Item::setupForBuiltinType(Logger &logger) { const BuiltinDeclarations &builtins = BuiltinDeclarations::instance(); foreach (const PropertyDeclaration &pd, builtins.declarationsForType(typeName()).properties()) { m_propertyDeclarations.insert(pd.name(), pd); ValuePtr &value = m_properties[pd.name()]; if (!value) { JSSourceValuePtr sourceValue = JSSourceValue::create(); sourceValue->setFile(file()); static const QString undefinedKeyword = QLatin1String("undefined"); sourceValue->setSourceCode(pd.initialValueSource().isEmpty() ? QStringRef(&undefinedKeyword) : QStringRef(&pd.initialValueSource())); value = sourceValue; } else if (pd.isDeprecated()) { const DeprecationInfo &di = pd.deprecationInfo(); if (di.removalVersion() <= Version::qbsVersion()) { QString message = Tr::tr("The property '%1' is no longer valid for %2 items. " "It was removed in qbs %3.") .arg(pd.name(), typeName(), di.removalVersion().toString()); ErrorInfo error(message, value->location()); if (!di.additionalUserInfo().isEmpty()) error.append(di.additionalUserInfo()); throw error; } QString warning = Tr::tr("The property '%1' is deprecated and will be removed in " "qbs %2.").arg(pd.name(), di.removalVersion().toString()); ErrorInfo error(warning, value->location()); if (!di.additionalUserInfo().isEmpty()) error.append(di.additionalUserInfo()); logger.printWarning(error); } } } void Item::copyProperty(const QString &propertyName, Item *target) const { target->setProperty(propertyName, property(propertyName)); } static const char *valueType(const Value *v) { switch (v->type()) { case Value::JSSourceValueType: return "JS source"; case Value::ItemValueType: return "Item"; case Value::VariantValueType: return "Variant"; case Value::BuiltinValueType: return "Built-in"; } return ""; // For dumb compilers. } void Item::dump(int indentation) const { const QByteArray indent(indentation, ' '); qDebug("%stype: %s, pointer value: %p", indent.constData(), qPrintable(m_typeName), this); if (!m_properties.isEmpty()) qDebug("%sproperties:", indent.constData()); for (auto it = m_properties.constBegin(); it != m_properties.constEnd(); ++it) { const QByteArray nextIndent(indentation + 4, ' '); qDebug("%skey: %s, value type: %s", nextIndent.constData(), qPrintable(it.key()), valueType(it.value().data())); switch (it.value()->type()) { case Value::JSSourceValueType: qDebug("%svalue: %s", nextIndent.constData(), qPrintable(it.value().staticCast()->sourceCodeForEvaluation())); break; case Value::ItemValueType: qDebug("%svalue:", nextIndent.constData()); it.value().staticCast()->item()->dump(indentation + 8); break; case Value::VariantValueType: qDebug("%svalue: %s", nextIndent.constData(), qPrintable(it.value().staticCast()->value().toString())); break; case Value::BuiltinValueType: break; } } if (!m_children.isEmpty()) qDebug("%schildren:", indent.constData()); foreach (const Item * const child, m_children) child->dump(indentation + 4); if (prototype()) { qDebug("%sprototype:", indent.constData()); prototype()->dump(indentation + 4); } } void Item::removeProperty(const QString &name) { m_properties.remove(name); } Item *Item::child(const QString &type, bool checkForMultiple) const { Item *child = 0; foreach (Item * const currentChild, children()) { if (currentChild->typeName() == type) { if (!checkForMultiple) return currentChild; if (child) { ErrorInfo error(Tr::tr("Multiple instances of item '%1' found where at most one " "is allowed.").arg(type)); error.append(Tr::tr("First item"), child->location()); error.append(Tr::tr("Second item"), currentChild->location()); throw error; } child = currentChild; } } return child; } void Item::addChild(Item *parent, Item *child) { parent->m_children.append(child); child->setParent(parent); } void Item::setPropertyDeclaration(const QString &name, const PropertyDeclaration &declaration) { m_propertyDeclarations.insert(name, declaration); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/item.h000066400000000000000000000135161266132464200207550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_ITEM_H #define QBS_ITEM_H #include "forward_decls.h" #include "functiondeclaration.h" #include "propertydeclaration.h" #include "qualifiedid.h" #include #include #include #include #include namespace qbs { namespace Internal { class ItemObserver; class ItemPool; class Logger; class Item : public QbsQmlJS::Managed { friend class ItemPool; friend class ItemReaderASTVisitor; Q_DISABLE_COPY(Item) Item(ItemPool *pool); public: ~Item(); struct Module { Module() : item(0), isProduct(false), required(true) {} QualifiedId name; Item *item; bool isProduct; bool required; }; typedef QList Modules; typedef QMap PropertyDeclarationMap; typedef QMap PropertyMap; static Item *create(ItemPool *pool); Item *clone() const; ItemPool *pool() const { return m_pool; } const QString &id() const { return m_id; } const QString &typeName() const { return m_typeName; } const CodeLocation &location() const { return m_location; } Item *prototype() const { return m_prototype; } Item *scope() const { return m_scope; } bool isModuleInstance() const { return m_moduleInstance; } Item *outerItem() const { return m_outerItem; } Item *parent() const { return m_parent; } const FileContextPtr file() const { return m_file; } QList children() const { return m_children; } Item *child(const QString &type, bool checkForMultiple = true) const; const PropertyMap &properties() const { return m_properties; } const PropertyDeclarationMap &propertyDeclarations() const { return m_propertyDeclarations; } PropertyDeclaration propertyDeclaration(const QString &name) const; const Modules &modules() const { return m_modules; } void addModule(const Module &module); void removeModules() { m_modules.clear(); } void setModules(const Modules &modules) { m_modules = modules; } bool hasProperty(const QString &name) const; bool hasOwnProperty(const QString &name) const; ValuePtr property(const QString &name) const; ItemValuePtr itemProperty(const QString &name, bool create = false); JSSourceValuePtr sourceProperty(const QString &name) const; VariantValuePtr variantProperty(const QString &name) const; void setPropertyObserver(ItemObserver *observer) const; void setProperty(const QString &name, const ValuePtr &value); void setProperties(const PropertyMap &props) { m_properties = props; } void removeProperty(const QString &name); void setPropertyDeclaration(const QString &name, const PropertyDeclaration &declaration); void setTypeName(const QString &name) { m_typeName = name; } void setLocation(const CodeLocation &location) { m_location = location; } void setPrototype(Item *prototype) { m_prototype = prototype; } void setFile(const FileContextPtr &file) { m_file = file; } void setScope(Item *item) { m_scope = item; } void setModuleInstanceFlag(bool b) { m_moduleInstance = b; } void setOuterItem(Item *item) { m_outerItem = item; } void setChildren(const QList &children) { m_children = children; } void setParent(Item *item) { m_parent = item; } static void addChild(Item *parent, Item *child); void dump() const; bool isPresentModule() const; void setupForBuiltinType(Logger &logger); void copyProperty(const QString &propertyName, Item *target) const; void setDelayedError(const ErrorInfo &e) { m_delayedError = e; } ErrorInfo delayedError() const { return m_delayedError; } private: void dump(int indentation) const; ItemPool *m_pool; mutable ItemObserver *m_propertyObserver; QString m_id; QString m_typeName; CodeLocation m_location; bool m_moduleInstance; Item *m_prototype; Item *m_scope; Item *m_outerItem; Item *m_parent; QList m_children; FileContextPtr m_file; PropertyMap m_properties; PropertyDeclarationMap m_propertyDeclarations; QList m_functions; Modules m_modules; ErrorInfo m_delayedError; }; inline bool operator<(const Item::Module &m1, const Item::Module &m2) { return m1.name < m2.name; } } // namespace Internal } // namespace qbs #endif // QBS_ITEM_H qbs-src-1.4.5/src/lib/corelib/language/itemdeclaration.cpp000066400000000000000000000042251266132464200235130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "itemdeclaration.h" namespace qbs { namespace Internal { ItemDeclaration::ItemDeclaration(const QString &typeName) : m_typeName(typeName) { } ItemDeclaration::ItemDeclaration(const qbs::Internal::ItemDeclaration &other) : m_typeName(other.m_typeName) , m_properties(other.m_properties) , m_allowedChildTypes(other.m_allowedChildTypes) { } ItemDeclaration &ItemDeclaration::operator<<(const PropertyDeclaration &decl) { m_properties.append(decl); return *this; } bool ItemDeclaration::isChildTypeAllowed(const QString &typeName) const { return m_allowedChildTypes.contains(typeName); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/itemdeclaration.h000066400000000000000000000050551266132464200231620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_ITEMDECLARATION_H #define QBS_ITEMDECLARATION_H #include "propertydeclaration.h" #include #include namespace qbs { namespace Internal { class ItemDeclaration { public: ItemDeclaration(const QString &typeName = QString()); ItemDeclaration(const ItemDeclaration &other); const QString &typeName() const { return m_typeName; } typedef QList Properties; void setProperties(const Properties &props) { m_properties = props; } const Properties &properties() const { return m_properties; } ItemDeclaration &operator<<(const PropertyDeclaration &decl); typedef QSet TypeNames; void setAllowedChildTypes(const TypeNames &typeNames) { m_allowedChildTypes = typeNames; } const TypeNames &allowedChildTypes() const { return m_allowedChildTypes; } bool isChildTypeAllowed(const QString &typeName) const; private: QString m_typeName; Properties m_properties; TypeNames m_allowedChildTypes; }; } // namespace Internal } // namespace qbs #endif // QBS_ITEMDECLARATION_H qbs-src-1.4.5/src/lib/corelib/language/itemobserver.h000066400000000000000000000034641266132464200225260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_ITEMOBSERVER_H #define QBS_ITEMOBSERVER_H namespace qbs { namespace Internal { class Item; class ItemObserver { public: virtual void onItemPropertyChanged(Item *item) = 0; virtual void onItemDestroyed(Item *item) = 0; }; } // namespace Internal } // namespace qbs #endif // QBS_ITEMOBSERVER_H qbs-src-1.4.5/src/lib/corelib/language/itempool.cpp000066400000000000000000000036311266132464200221770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "itempool.h" #include "item.h" namespace qbs { namespace Internal { ItemPool::ItemPool() { } ItemPool::~ItemPool() { for (ItemVector::const_iterator it = m_items.constBegin(); it != m_items.constEnd(); ++it) (*it)->~Item(); } Item *ItemPool::allocateItem() { Item *item = new (&m_pool) Item(this); m_items.push_back(item); return item; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/itempool.h000066400000000000000000000036651266132464200216530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_ITEMPOOL_H #define QBS_ITEMPOOL_H #include #include namespace qbs { namespace Internal { class Item; class ItemPool { Q_DISABLE_COPY(ItemPool) public: ItemPool(); ~ItemPool(); Item *allocateItem(); private: QbsQmlJS::MemoryPool m_pool; typedef QList ItemVector; ItemVector m_items; }; } // namespace Internal } // namespace qbs #endif // QBS_ITEMPOOL_H qbs-src-1.4.5/src/lib/corelib/language/itemreader.cpp000066400000000000000000000051501266132464200224660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "itemreader.h" #include "itemreadervisitorstate.h" namespace qbs { namespace Internal { ItemReader::ItemReader(const Logger &logger) : m_visitorState(new ItemReaderVisitorState(logger)) { } ItemReader::~ItemReader() { delete m_visitorState; } void ItemReader::setSearchPaths(const QStringList &searchPaths) { m_searchPaths = searchPaths; } void ItemReader::pushExtraSearchPaths(const QStringList &extraSearchPaths) { m_extraSearchPaths.push(extraSearchPaths); } void ItemReader::popExtraSearchPaths() { m_extraSearchPaths.pop(); } QStack ItemReader::extraSearchPathsStack() const { return m_extraSearchPaths; } QStringList ItemReader::searchPaths() const { QStringList paths; for (int i = m_extraSearchPaths.count(); --i >= 0;) paths += m_extraSearchPaths.at(i); paths += m_searchPaths; return paths; } Item *ItemReader::readFile(const QString &filePath) { return m_visitorState->readFile(filePath, searchPaths(), m_pool); } QSet ItemReader::filesRead() const { return m_visitorState->filesRead(); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/itemreader.h000066400000000000000000000056131266132464200221370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_ITEMREADER_H #define QBS_ITEMREADER_H #include "forward_decls.h" #include #include #include #include namespace qbs { namespace Internal { class Item; class ItemPool; class ItemReaderVisitorState; /* * Reads a qbs file and creates a tree of Item objects. * * In this stage the following steps are performed: * - The QML/JS parser creates the AST. * - The AST is converted to a tree of Item objects. * * This class is also responsible for the QMLish inheritance semantics. */ class ItemReader { public: ItemReader(const Logger &logger); ~ItemReader(); void setPool(ItemPool *pool) { m_pool = pool; } void setSearchPaths(const QStringList &searchPaths); void pushExtraSearchPaths(const QStringList &extraSearchPaths); void popExtraSearchPaths(); QStack extraSearchPathsStack() const; void setExtraSearchPathsStack(const QStack &s) { m_extraSearchPaths = s; } void clearExtraSearchPathsStack() { m_extraSearchPaths.clear(); } QStringList searchPaths() const; Item *readFile(const QString &filePath); QSet filesRead() const; private: ItemPool *m_pool = nullptr; QStringList m_searchPaths; QStack m_extraSearchPaths; ItemReaderVisitorState * const m_visitorState; }; } // namespace Internal } // namespace qbs #endif // QBS_ITEMREADER_H qbs-src-1.4.5/src/lib/corelib/language/itemreaderastvisitor.cpp000066400000000000000000000637731266132464200246350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "itemreaderastvisitor.h" #include "asttools.h" #include "builtindeclarations.h" #include "filecontext.h" #include "identifiersearch.h" #include "item.h" #include "itemreadervisitorstate.h" #include "value.h" #include #include #include #include #include #include #include #include #include using namespace QbsQmlJS; namespace qbs { namespace Internal { ItemReaderASTVisitor::ItemReaderASTVisitor(ItemReaderVisitorState &visitorState, ItemPool *itemPool, Logger logger, const QStringList &searchPaths) : m_visitorState(visitorState) , m_file(FileContext::create()) , m_itemPool(itemPool) , m_logger(logger) , m_searchPaths(searchPaths) { } ItemReaderASTVisitor::~ItemReaderASTVisitor() { } void ItemReaderASTVisitor::setFilePath(const QString &filePath) { m_file->setFilePath(filePath); } void ItemReaderASTVisitor::setSourceCode(const QString &sourceCode) { m_file->setContent(sourceCode); } bool ItemReaderASTVisitor::visit(AST::UiProgram *ast) { Q_UNUSED(ast); m_sourceValue.clear(); m_file->setSearchPaths(m_searchPaths); if (Q_UNLIKELY(!ast->members->member)) throw ErrorInfo(Tr::tr("No root item found in %1.").arg(m_file->filePath())); return true; } bool ItemReaderASTVisitor::addPrototype(const QString &fileName, const QString &filePath, const QString &as, bool needsCheck) { if (needsCheck && fileName.size() <= 4) return false; const QString componentName = fileName.left(fileName.size() - 4); // ### validate componentName if (needsCheck && !componentName.at(0).isUpper()) return false; QStringList prototypeName; if (!as.isEmpty()) prototypeName.append(as); prototypeName.append(componentName); m_typeNameToFile.insert(prototypeName, filePath); return true; } void ItemReaderASTVisitor::collectPrototypes(const QString &path, const QString &as) { QStringList fileNames; // Yes, file *names*. if (m_visitorState.findDirectoryEntries(path, &fileNames)) { foreach (const QString &fileName, fileNames) addPrototype(fileName, path + QLatin1Char('/') + fileName, as, false); return; } QDirIterator dirIter(path, QStringList(QLatin1String("*.qbs"))); while (dirIter.hasNext()) { const QString filePath = dirIter.next(); const QString fileName = dirIter.fileName(); if (addPrototype(fileName, filePath, as, true)) fileNames << fileName; } m_visitorState.cacheDirectoryEntries(path, fileNames); } void ItemReaderASTVisitor::collectPrototypesAndJsCollections(const QString &path, const QString &as, const CodeLocation &location, JsImportsHash &jsImports) { collectPrototypes(path, as); QDirIterator dirIter(path, QStringList(QLatin1String("*.js"))); while (dirIter.hasNext()) { dirIter.next(); JsImport &jsImport = jsImports[as]; if (jsImport.scopeName.isNull()) { jsImport.scopeName = as; jsImport.location = location; } jsImport.filePaths.append(dirIter.filePath()); } } bool ItemReaderASTVisitor::visit(AST::UiImportList *uiImportList) { foreach (const QString &searchPath, m_searchPaths) collectPrototypes(searchPath + QLatin1String("/imports"), QString()); const QString path = FileInfo::path(m_file->filePath()); // files in the same directory are available as prototypes collectPrototypes(path, QString()); QSet importAsNames; JsImportsHash jsImports; for (const AST::UiImportList *it = uiImportList; it; it = it->next) { const AST::UiImport *const import = it->import; QStringList importUri; bool isBase = false; if (import->importUri) { importUri = toStringList(import->importUri); isBase = (importUri.size() == 1 && importUri.first() == QLatin1String("qbs")) || (importUri.size() == 2 && importUri.first() == QLatin1String("qbs") && importUri.last() == QLatin1String("base")); if (isBase) checkImportVersion(import->versionToken); else if (import->versionToken.length) m_logger.printWarning(ErrorInfo(Tr::tr("Superfluous version specification."), toCodeLocation(import->versionToken))); } QString as; if (isBase) { if (Q_UNLIKELY(!import->importId.isNull())) { throw ErrorInfo(Tr::tr("Import of qbs.base must have no 'as '"), toCodeLocation(import->importIdToken)); } } else { if (importUri.count() == 2 && importUri.first() == QLatin1String("qbs")) { const QString extensionName = importUri.last(); if (JsExtensions::hasExtension(extensionName)) { if (Q_UNLIKELY(!import->importId.isNull())) { throw ErrorInfo(Tr::tr("Import of built-in extension '%1' " "must not have 'as' specifier.").arg(extensionName)); } if (Q_UNLIKELY(m_file->jsExtensions().contains(extensionName))) { m_logger.printWarning(Tr::tr("Built-in extension '%1' already " "imported.").arg(extensionName)); } else { m_file->addJsExtension(extensionName); } continue; } } if (import->importId.isNull()) { if (!import->fileName.isNull()) { throw ErrorInfo(Tr::tr("File imports require 'as '"), toCodeLocation(import->importToken)); } if (importUri.isEmpty()) { throw ErrorInfo(Tr::tr("Invalid import URI."), toCodeLocation(import->importToken)); } as = importUri.last(); } else { as = import->importId.toString(); } if (Q_UNLIKELY(importAsNames.contains(as))) { throw ErrorInfo(Tr::tr("Cannot import into the same name more than once."), toCodeLocation(import->importIdToken)); } if (Q_UNLIKELY(JsExtensions::hasExtension(as))) { throw ErrorInfo(Tr::tr("Cannot reuse the name of built-in extension '%1'.") .arg(as)); } importAsNames.insert(as); } if (!import->fileName.isNull()) { QString filePath = FileInfo::resolvePath(path, import->fileName.toString()); QFileInfo fi(filePath); if (Q_UNLIKELY(!fi.exists())) throw ErrorInfo(Tr::tr("Cannot find imported file %0.").arg(filePath), CodeLocation(m_file->filePath(), import->fileNameToken.startLine, import->fileNameToken.startColumn)); filePath = fi.canonicalFilePath(); if (fi.isDir()) { collectPrototypesAndJsCollections(filePath, as, toCodeLocation(import->fileNameToken), jsImports); } else { if (filePath.endsWith(QLatin1String(".js"), Qt::CaseInsensitive)) { JsImport &jsImport = jsImports[as]; jsImport.scopeName = as; jsImport.filePaths.append(filePath); jsImport.location = toCodeLocation(import->firstSourceLocation()); } else if (filePath.endsWith(QLatin1String(".qbs"), Qt::CaseInsensitive)) { m_typeNameToFile.insert(QStringList(as), filePath); } else { throw ErrorInfo(Tr::tr("Can only import .qbs and .js files"), CodeLocation(m_file->filePath(), import->fileNameToken.startLine, import->fileNameToken.startColumn)); } } } else if (!importUri.isEmpty()) { const QString importPath = isBase ? QLatin1String("qbs/base") : importUri.join(QDir::separator()); bool found = m_typeNameToFile.contains(importUri); if (!found) { foreach (const QString &searchPath, m_searchPaths) { const QFileInfo fi(FileInfo::resolvePath( FileInfo::resolvePath(searchPath, QLatin1String("imports")), importPath)); if (fi.isDir()) { // ### versioning, qbsdir file, etc. const QString &resultPath = fi.absoluteFilePath(); collectPrototypesAndJsCollections(resultPath, as, toCodeLocation(import->importIdToken), jsImports); found = true; break; } } } if (Q_UNLIKELY(!found)) { throw ErrorInfo(Tr::tr("import %1 not found") .arg(importUri.join(QLatin1Char('.'))), toCodeLocation(import->fileNameToken)); } } } for (QHash::const_iterator it = jsImports.constBegin(); it != jsImports.constEnd(); ++it) { m_file->addJsImport(it.value()); } return false; } bool ItemReaderASTVisitor::visit(AST::UiObjectDefinition *ast) { const QString typeName = ast->qualifiedTypeNameId->name.toString(); Item *item = Item::create(m_itemPool); item->m_file = m_file; item->m_parent = m_item; item->m_typeName = typeName; item->m_location = ::qbs::Internal::toCodeLocation(m_file->filePath(), ast->qualifiedTypeNameId->identifierToken); if (m_item) { // Add this item to the children of the parent item. m_item->m_children += item; } else { // This is the root item. m_item = item; m_rootItem = item; } if (ast->initializer) { qSwap(m_item, item); ast->initializer->accept(this); qSwap(m_item, item); } item->setupForBuiltinType(m_logger); if (item->typeName() != QLatin1String("Properties") && item->typeName() != QLatin1String("SubProject")) { setupAlternatives(item); } // resolve inheritance const QStringList fullTypeName = toStringList(ast->qualifiedTypeNameId); const QString baseTypeFileName = m_typeNameToFile.value(fullTypeName); if (!baseTypeFileName.isEmpty()) { const Item * const rootItem = m_visitorState.readFile(baseTypeFileName, m_searchPaths, m_itemPool); inheritItem(item, rootItem); if (rootItem->m_file->idScope()) { // Make ids from the derived file visible in the base file. // ### Do we want to turn off this feature? It's QMLish but kind of strange. item->m_file->ensureIdScope(m_itemPool); rootItem->m_file->idScope()->setPrototype(item->m_file->idScope()); } } return false; } void ItemReaderASTVisitor::checkDuplicateBinding(Item *item, const QStringList &bindingName, const AST::SourceLocation &sourceLocation) { if (Q_UNLIKELY(item->properties().contains(bindingName.last()))) { QString msg = Tr::tr("Duplicate binding for '%1'"); throw ErrorInfo(msg.arg(bindingName.join(QLatin1Char('.'))), qbs::Internal::toCodeLocation(m_file->filePath(), sourceLocation)); } } bool ItemReaderASTVisitor::visit(AST::UiPublicMember *ast) { PropertyDeclaration p; if (Q_UNLIKELY(ast->name.isEmpty())) throw ErrorInfo(Tr::tr("public member without name")); if (Q_UNLIKELY(ast->memberType.isEmpty())) throw ErrorInfo(Tr::tr("public member without type")); if (Q_UNLIKELY(ast->type == AST::UiPublicMember::Signal)) throw ErrorInfo(Tr::tr("public member with signal type not supported")); p.setName(ast->name.toString()); p.setType(PropertyDeclaration::propertyTypeFromString(ast->memberType.toString())); if (p.type() == PropertyDeclaration::UnknownType) throw ErrorInfo(Tr::tr("Unknown type '%1' in property declaration.") .arg(ast->memberType.toString()), toCodeLocation(ast->typeToken)); if (ast->typeModifier.compare(QLatin1String("list"))) p.setFlags(p.flags() | PropertyDeclaration::ListProperty); else if (Q_UNLIKELY(!ast->typeModifier.isEmpty())) throw ErrorInfo(Tr::tr("public member with type modifier '%1' not supported").arg( ast->typeModifier.toString())); m_item->m_propertyDeclarations.insert(p.name(), p); JSSourceValuePtr value = JSSourceValue::create(); value->setFile(m_file); if (ast->statement) { m_sourceValue.swap(value); visitStatement(ast->statement); m_sourceValue.swap(value); const QStringList bindingName(p.name()); checkDuplicateBinding(m_item, bindingName, ast->colonToken); } m_item->m_properties.insert(p.name(), value); return false; } bool ItemReaderASTVisitor::visit(AST::UiScriptBinding *ast) { QBS_CHECK(ast->qualifiedId); QBS_CHECK(!ast->qualifiedId->name.isEmpty()); const QStringList bindingName = toStringList(ast->qualifiedId); if (bindingName.length() == 1 && bindingName.first() == QLatin1String("id")) { AST::ExpressionStatement *expStmt = AST::cast(ast->statement); if (Q_UNLIKELY(!expStmt)) throw ErrorInfo(Tr::tr("id: must be followed by identifier")); AST::IdentifierExpression *idExp = AST::cast(expStmt->expression); if (Q_UNLIKELY(!idExp || idExp->name.isEmpty())) throw ErrorInfo(Tr::tr("id: must be followed by identifier")); m_item->m_id = idExp->name.toString(); m_file->ensureIdScope(m_itemPool); m_file->idScope()->m_properties[m_item->m_id] = ItemValue::create(m_item); return false; } JSSourceValuePtr value = JSSourceValue::create(); value->setFile(m_file); m_sourceValue.swap(value); visitStatement(ast->statement); m_sourceValue.swap(value); Item *targetItem = targetItemForBinding(m_item, bindingName, value); checkDuplicateBinding(targetItem, bindingName, ast->qualifiedId->identifierToken); targetItem->m_properties.insert(bindingName.last(), value); return false; } bool ItemReaderASTVisitor::visit(AST::FunctionDeclaration *ast) { FunctionDeclaration f; if (Q_UNLIKELY(ast->name.isNull())) throw ErrorInfo(Tr::tr("function decl without name")); f.setName(ast->name.toString()); // remove the name QString funcNoName = textOf(m_file->content(), ast); funcNoName.replace(QRegExp(QLatin1String("^(\\s*function\\s*)\\w*")), QLatin1String("(\\1")); funcNoName.append(QLatin1Char(')')); f.setSourceCode(funcNoName); f.setLocation(toCodeLocation(ast->firstSourceLocation())); m_item->m_functions += f; return false; } Version ItemReaderASTVisitor::readImportVersion(const QString &str, const CodeLocation &location) { const Version v = Version::fromString(str); if (Q_UNLIKELY(!v.isValid())) throw ErrorInfo(Tr::tr("Cannot parse version number in import statement."), location); if (Q_UNLIKELY(v.patchLevel() != 0)) { throw ErrorInfo(Tr::tr("Version number in import statement cannot have more than " "two components."), location); } return v; } bool ItemReaderASTVisitor::visitStatement(AST::Statement *statement) { QBS_CHECK(statement); QBS_CHECK(m_sourceValue); if (AST::cast(statement)) m_sourceValue->m_flags |= JSSourceValue::HasFunctionForm; m_sourceValue->setFile(m_file); m_sourceValue->setSourceCode(textRefOf(m_file->content(), statement)); m_sourceValue->setLocation(statement->firstSourceLocation().startLine, statement->firstSourceLocation().startColumn); bool usesBase, usesOuter, usesOriginal; IdentifierSearch idsearch; idsearch.add(QLatin1String("base"), &usesBase); idsearch.add(QLatin1String("outer"), &usesOuter); idsearch.add(QLatin1String("original"), &usesOriginal); idsearch.start(statement); if (usesBase) m_sourceValue->m_flags |= JSSourceValue::SourceUsesBase; if (usesOuter) m_sourceValue->m_flags |= JSSourceValue::SourceUsesOuter; if (usesOriginal) m_sourceValue->m_flags |= JSSourceValue::SourceUsesOriginal; return false; } CodeLocation ItemReaderASTVisitor::toCodeLocation(const AST::SourceLocation &location) const { return CodeLocation(m_file->filePath(), location.startLine, location.startColumn); } Item *ItemReaderASTVisitor::targetItemForBinding(Item *item, const QStringList &bindingName, const JSSourceValueConstPtr &value) { Item *targetItem = item; const int c = bindingName.count() - 1; for (int i = 0; i < c; ++i) { ValuePtr v = targetItem->m_properties.value(bindingName.at(i)); if (!v) { Item *newItem = Item::create(m_itemPool); v = ItemValue::create(newItem); targetItem->m_properties.insert(bindingName.at(i), v); } if (Q_UNLIKELY(v->type() != Value::ItemValueType)) { QString msg = Tr::tr("Binding to non-item property."); throw ErrorInfo(msg, value->location()); } ItemValuePtr jsv = v.staticCast(); targetItem = jsv->item(); } return targetItem; } void ItemReaderASTVisitor::checkImportVersion(const AST::SourceLocation &versionToken) const { if (!versionToken.length) return; const QString importVersionString = m_file->content().mid(versionToken.offset, versionToken.length); const Version importVersion = readImportVersion(importVersionString, toCodeLocation(versionToken)); if (Q_UNLIKELY(importVersion != BuiltinDeclarations::instance().languageVersion())) throw ErrorInfo(Tr::tr("Incompatible qbs language version %1. This is version %2.").arg( importVersionString, BuiltinDeclarations::instance().languageVersion().toString()), toCodeLocation(versionToken)); } void ItemReaderASTVisitor::inheritItem(Item *dst, const Item *src) { if (!src->typeName().isEmpty()) dst->setTypeName(src->typeName()); int insertPos = 0; for (int i = 0; i < src->m_children.count(); ++i) { Item *child = src->m_children.at(i); dst->m_children.insert(insertPos++, child); child->m_parent = dst; } for (QMap::const_iterator it = src->m_properties.constBegin(); it != src->m_properties.constEnd(); ++it) { ValuePtr &v = dst->m_properties[it.key()]; if (v) { if (v->type() == it.value()->type()) { if (v->type() == Value::JSSourceValueType) { JSSourceValuePtr sv = v.staticCast(); while (sv->baseValue()) sv = sv->baseValue(); const JSSourceValuePtr baseValue = it.value().staticCast(); sv->setBaseValue(baseValue); for (QList::iterator it = sv->m_alternatives.begin(); it != sv->m_alternatives.end(); ++it) { JSSourceValue::Alternative &alternative = *it; alternative.value->setBaseValue(baseValue); } } else if (v->type() == Value::ItemValueType) { QBS_CHECK(v.staticCast()->item()); QBS_CHECK(it.value().staticCast()->item()); inheritItem(v.staticCast()->item(), it.value().staticCast()->item()); } else { QBS_CHECK(!"unexpected value type"); } } } else { v = it.value(); } } for (Item::PropertyDeclarationMap::const_iterator it = src->m_propertyDeclarations.constBegin(); it != src->m_propertyDeclarations.constEnd(); ++it) { dst->m_propertyDeclarations[it.key()] = it.value(); } } void ItemReaderASTVisitor::setupAlternatives(Item *item) { QList::iterator it = item->m_children.begin(); while (it != item->m_children.end()) { Item *child = *it; if (child->typeName() == QLatin1String("Properties")) { handlePropertiesBlock(item, child); it = item->m_children.erase(it); } else { ++it; } } } class PropertiesBlockConverter { public: PropertiesBlockConverter(const QString &condition, Item *propertiesBlockContainer, const Item *propertiesBlock) : m_propertiesBlockContainer(propertiesBlockContainer) , m_propertiesBlock(propertiesBlock) { m_alternative.condition = condition; } void operator()() { apply(m_propertiesBlockContainer, m_propertiesBlock); } private: JSSourceValue::Alternative m_alternative; Item *m_propertiesBlockContainer; const Item *m_propertiesBlock; void apply(Item *a, const Item *b) { for (QMap::const_iterator it = b->properties().constBegin(); it != b->properties().constEnd(); ++it) { if (b == m_propertiesBlock && it.key() == QLatin1String("condition")) continue; if (it.value()->type() == Value::ItemValueType) { ItemValuePtr aval = a->itemProperty(it.key()); if (!aval) { aval = ItemValue::create(Item::create(a->pool()), true); a->setProperty(it.key(), aval); } apply(aval->item(), it.value().staticCast()->item()); } else if (it.value()->type() == Value::JSSourceValueType) { ValuePtr aval = a->property(it.key()); if (Q_UNLIKELY(aval && aval->type() != Value::JSSourceValueType)) throw ErrorInfo(Tr::tr("Incompatible value type in unconditional value at %1.").arg( aval->location().toString())); apply(it.key(), a, aval.staticCast(), it.value().staticCast()); } else { QBS_CHECK(!"Unexpected value type in conditional value."); } } } void apply(const QString &propertyName, Item *item, JSSourceValuePtr value, const JSSourceValuePtr &conditionalValue) { QBS_ASSERT(!value || value->file() == conditionalValue->file(), return); if (!value) { value = JSSourceValue::create(true); value->setFile(conditionalValue->file()); item->setProperty(propertyName, value); static const QString baseKeyword = QLatin1String("base"); value->setSourceCode(QStringRef(&baseKeyword)); value->setSourceUsesBaseFlag(); } m_alternative.value = conditionalValue; value->addAlternative(m_alternative); } }; void ItemReaderASTVisitor::handlePropertiesBlock(Item *item, const Item *block) { ValuePtr value = block->property(QLatin1String("condition")); if (Q_UNLIKELY(!value)) throw ErrorInfo(Tr::tr("Properties.condition must be provided."), block->location()); if (Q_UNLIKELY(value->type() != Value::JSSourceValueType)) throw ErrorInfo(Tr::tr("Properties.condition must be a value binding."), block->location()); JSSourceValuePtr srcval = value.staticCast(); const QString condition = srcval->sourceCodeForEvaluation(); PropertiesBlockConverter convertBlock(condition, item, block); convertBlock(); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/itemreaderastvisitor.h000066400000000000000000000103731266132464200242660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_ITEMREADERASTVISITOR_H #define QBS_ITEMREADERASTVISITOR_H #include "forward_decls.h" #include #include #include #include #include namespace qbs { namespace Internal { class Item; class ItemPool; class ItemReaderVisitorState; class JsImport; class Version; class ItemReaderASTVisitor : public QbsQmlJS::AST::Visitor { public: ItemReaderASTVisitor(ItemReaderVisitorState &visitorState, ItemPool *itemPool, Logger logger, const QStringList &searchPaths); ~ItemReaderASTVisitor(); void setFilePath(const QString &filePath); void setSourceCode(const QString &sourceCode); bool visit(QbsQmlJS::AST::UiProgram *ast); bool visit(QbsQmlJS::AST::UiImportList *uiImportList); bool visit(QbsQmlJS::AST::UiObjectDefinition *ast); bool visit(QbsQmlJS::AST::UiPublicMember *ast); bool visit(QbsQmlJS::AST::UiScriptBinding *ast); bool visit(QbsQmlJS::AST::FunctionDeclaration *ast); Item *rootItem() const { return m_rootItem; } private: static Version readImportVersion(const QString &str, const CodeLocation &location = CodeLocation()); bool visitStatement(QbsQmlJS::AST::Statement *statement); CodeLocation toCodeLocation(const QbsQmlJS::AST::SourceLocation &location) const; void checkDuplicateBinding(Item *item, const QStringList &bindingName, const QbsQmlJS::AST::SourceLocation &sourceLocation); Item *targetItemForBinding(Item *item, const QStringList &binding, const JSSourceValueConstPtr &value); void checkImportVersion(const QbsQmlJS::AST::SourceLocation &versionToken) const; static void inheritItem(Item *dst, const Item *src); void setupAlternatives(Item *item); static void replaceConditionScopes(const JSSourceValuePtr &value, Item *newScope); void handlePropertiesBlock(Item *item, const Item *block); void collectPrototypes(const QString &path, const QString &as); using JsImportsHash = QHash; void collectPrototypesAndJsCollections(const QString &path, const QString &as, const CodeLocation &location, JsImportsHash &jsImports); bool addPrototype(const QString &fileName, const QString &filePath, const QString &as, bool needsCheck); ItemReaderVisitorState &m_visitorState; const FileContextPtr m_file; ItemPool * const m_itemPool; Logger m_logger; const QStringList m_searchPaths; QHash m_typeNameToFile; Item *m_item = nullptr; Item *m_rootItem = nullptr; JSSourceValuePtr m_sourceValue; }; } // namespace Internal } // namespace qbs #endif // QBS_ITEMREADERASTVISITOR_H qbs-src-1.4.5/src/lib/corelib/language/itemreadervisitorstate.cpp000066400000000000000000000123501266132464200251470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "itemreadervisitorstate.h" #include "asttools.h" #include "itemreaderastvisitor.h" #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class ASTCacheValueData : public QSharedData { Q_DISABLE_COPY(ASTCacheValueData) public: ASTCacheValueData() : ast(0) , processing(false) { } QString code; QbsQmlJS::Engine engine; QbsQmlJS::AST::UiProgram *ast; bool processing; }; class ASTCacheValue { public: ASTCacheValue() : d(new ASTCacheValueData) { } ASTCacheValue(const ASTCacheValue &other) : d(other.d) { } void setProcessingFlag(bool b) { d->processing = b; } bool isProcessing() const { return d->processing; } void setCode(const QString &code) { d->code = code; } QString code() const { return d->code; } QbsQmlJS::Engine *engine() const { return &d->engine; } void setAst(QbsQmlJS::AST::UiProgram *ast) { d->ast = ast; } QbsQmlJS::AST::UiProgram *ast() const { return d->ast; } bool isValid() const { return d->ast; } private: QExplicitlySharedDataPointer d; }; class ItemReaderVisitorState::ASTCache : public QHash {}; ItemReaderVisitorState::ItemReaderVisitorState(Logger logger) : m_logger(logger) , m_astCache(new ASTCache) { } ItemReaderVisitorState::~ItemReaderVisitorState() { delete m_astCache; } Item *ItemReaderVisitorState::readFile(const QString &filePath, const QStringList &searchPaths, ItemPool *itemPool) { ASTCacheValue &cacheValue = (*m_astCache)[filePath]; if (cacheValue.isValid()) { if (Q_UNLIKELY(cacheValue.isProcessing())) throw ErrorInfo(Tr::tr("Loop detected when importing '%1'.").arg(filePath)); } else { QFile file(filePath); if (Q_UNLIKELY(!file.open(QFile::ReadOnly))) throw ErrorInfo(Tr::tr("Cannot open '%1'.").arg(filePath)); m_filesRead.insert(filePath); const QString code = QTextStream(&file).readAll(); QbsQmlJS::Lexer lexer(cacheValue.engine()); lexer.setCode(code, 1); QbsQmlJS::Parser parser(cacheValue.engine()); file.close(); if (!parser.parse()) { QList parserMessages = parser.diagnosticMessages(); if (Q_UNLIKELY(!parserMessages.isEmpty())) { ErrorInfo err; foreach (const QbsQmlJS::DiagnosticMessage &msg, parserMessages) err.append(msg.message, toCodeLocation(filePath, msg.loc)); throw err; } } cacheValue.setCode(code); cacheValue.setAst(parser.ast()); } ItemReaderASTVisitor astVisitor(*this, itemPool, m_logger, searchPaths); astVisitor.setFilePath(QFileInfo(filePath).absoluteFilePath()); astVisitor.setSourceCode(cacheValue.code()); cacheValue.setProcessingFlag(true); cacheValue.ast()->accept(&astVisitor); cacheValue.setProcessingFlag(false); return astVisitor.rootItem(); } void ItemReaderVisitorState::cacheDirectoryEntries(const QString &dirPath, const QStringList &entries) { m_directoryEntries.insert(dirPath, entries); } bool ItemReaderVisitorState::findDirectoryEntries(const QString &dirPath, QStringList *entries) const { const auto it = m_directoryEntries.constFind(dirPath); if (it == m_directoryEntries.constEnd()) return false; *entries = it.value(); return true; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/itemreadervisitorstate.h000066400000000000000000000046021266132464200246150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_ITEMREADERVISITORSTATE_H #define QBS_ITEMREADERVISITORSTATE_H #include #include #include #include namespace qbs { namespace Internal { class Item; class ItemPool; class ItemReaderVisitorState { public: ItemReaderVisitorState(Logger logger); ~ItemReaderVisitorState(); QSet filesRead() const { return m_filesRead; } Item *readFile(const QString &filePath, const QStringList &searchPaths, ItemPool *itemPool); void cacheDirectoryEntries(const QString &dirPath, const QStringList &entries); bool findDirectoryEntries(const QString &dirPath, QStringList *entries) const; private: Logger m_logger; QSet m_filesRead; QHash m_directoryEntries; class ASTCache; ASTCache * const m_astCache; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.4.5/src/lib/corelib/language/jsimports.h000066400000000000000000000044241266132464200220470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_JSIMPORTS_H #define QBS_JSIMPORTS_H #include #include #include namespace qbs { namespace Internal { /** * Represents JavaScript import of the form * import 'fileOrDirectory' as scopeName * * There can be several filenames per scope * if we import a whole directory. */ class JsImport { public: QString scopeName; QStringList filePaths; CodeLocation location; }; inline uint qHash(const JsImport &jsi) { return qHash(jsi.scopeName); } typedef QList JsImports; inline bool operator==(const JsImport &jsi1, const JsImport &jsi2) { return jsi1.scopeName == jsi2.scopeName && jsi1.filePaths.toSet() == jsi2.filePaths.toSet(); } } // namespace Internal } // namespace qbs #endif // QBS_JSIMPORTS_H qbs-src-1.4.5/src/lib/corelib/language/language.cpp000066400000000000000000001226151266132464200221360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "language.h" #include "artifactproperties.h" #include "propertymapinternal.h" #include "resolvedfilecontext.h" #include "scriptengine.h" #include #include #include #include #include // TODO: Move to language? #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { template bool equals(const T *v1, const T *v2) { if (v1 == v2) return true; if (!v1 != !v2) return false; return *v1 == *v2; } FileTagger::FileTagger(const QStringList &patterns, const FileTags &fileTags) : m_fileTags(fileTags) { setPatterns(patterns); } void FileTagger::setPatterns(const QStringList &patterns) { m_patterns.clear(); foreach (const QString &pattern, patterns) { QBS_CHECK(!pattern.isEmpty()); m_patterns << QRegExp(pattern, Qt::CaseSensitive, QRegExp::Wildcard); } } /*! * \class FileTagger * \brief The \c FileTagger class maps 1:1 to the respective item in a qbs source file. */ void FileTagger::load(PersistentPool &pool) { setPatterns(pool.idLoadStringList()); pool.stream() >> m_fileTags; } void FileTagger::store(PersistentPool &pool) const { QStringList patterns; foreach (const QRegExp ®Exp, m_patterns) patterns << regExp.pattern(); pool.storeStringList(patterns); pool.stream() << m_fileTags; } /*! * \class SourceArtifact * \brief The \c SourceArtifact class represents a source file. * Everything except the file path is inherited from the surrounding \c ResolvedGroup. * (TODO: Not quite true. Artifacts in transformers will be generated by the transformer, but are * still represented as source artifacts. We may or may not want to change this; if we do, * SourceArtifact could simply have a back pointer to the group in addition to the file path.) * \sa ResolvedGroup */ void SourceArtifactInternal::load(PersistentPool &pool) { absoluteFilePath = pool.idLoadString(); pool.stream() >> fileTags; pool.stream() >> overrideFileTags; properties = pool.idLoadS(); } void SourceArtifactInternal::store(PersistentPool &pool) const { pool.storeString(absoluteFilePath); pool.stream() << fileTags; pool.stream() << overrideFileTags; pool.store(properties); } void SourceWildCards::load(PersistentPool &pool) { prefix = pool.idLoadString(); patterns = pool.idLoadStringList(); excludePatterns = pool.idLoadStringList(); pool.loadContainerS(files); } void SourceWildCards::store(PersistentPool &pool) const { pool.storeString(prefix); pool.storeStringList(patterns); pool.storeStringList(excludePatterns); pool.storeContainer(files); } /*! * \class ResolvedGroup * \brief The \c ResolvedGroup class corresponds to the Group item in a qbs source file. */ /*! * \variable ResolvedGroup::files * \brief The files listed in the group item's "files" binding. * Note that these do not include expanded wildcards. */ /*! * \variable ResolvedGroup::wildcards * \brief Represents the wildcard elements in this group's "files" binding. * If no wildcards are specified there, this variable is null. * \sa SourceWildCards */ /*! * \brief Returns all files specified in the group item as source artifacts. * This includes the expanded list of wildcards. */ QList ResolvedGroup::allFiles() const { QList lst = files; if (wildcards) lst.append(wildcards->files); return lst; } void ResolvedGroup::load(PersistentPool &pool) { name = pool.idLoadString(); pool.stream() >> enabled; location.load(pool); prefix = pool.idLoadString(); pool.loadContainerS(files); wildcards = pool.idLoadS(); properties = pool.idLoadS(); pool.stream() >> fileTags >> overrideTags; } void ResolvedGroup::store(PersistentPool &pool) const { pool.storeString(name); pool.stream() << enabled; location.store(pool); pool.storeString(prefix); pool.storeContainer(files); pool.store(wildcards); pool.store(properties); pool.stream() << fileTags << overrideTags; } /*! * \class RuleArtifact * \brief The \c RuleArtifact class represents an Artifact item encountered in the context * of a Rule item. * When applying the rule, one \c Artifact object will be constructed from each \c RuleArtifact * object. During that process, the \c RuleArtifact's bindings are evaluated and the results * are inserted into the corresponding \c Artifact's properties. * \sa Rule */ void RuleArtifact::load(PersistentPool &pool) { pool.stream() >> filePath >> fileTags >> alwaysUpdated; location.load(pool); int i; pool.stream() >> i; bindings.clear(); bindings.reserve(i); Binding binding; for (; --i >= 0;) { binding.name = pool.idLoadStringList(); binding.code = pool.idLoadString(); binding.location.load(pool); bindings += binding; } } void RuleArtifact::store(PersistentPool &pool) const { pool.stream() << filePath << fileTags << alwaysUpdated; location.store(pool); pool.stream() << bindings.count(); for (int i = bindings.count(); --i >= 0;) { const Binding &binding = bindings.at(i); pool.storeStringList(binding.name); pool.storeString(binding.code); binding.location.store(pool); } } /*! * \class ScriptFunction * \brief The \c ScriptFunction class represents the JavaScript code found in the "prepare" binding * of a \c Rule or \c Transformer item in a qbs file. * \sa Rule * \sa ResolvedTransformer */ ScriptFunction::ScriptFunction() { } ScriptFunction::~ScriptFunction() { } /*! * \variable ScriptFunction::script * \brief The actual Javascript code, taken verbatim from the qbs source file. */ /*! * \variable ScriptFunction::location * \brief The exact location of the script in the qbs source file. * This is mostly needed for diagnostics. */ bool ScriptFunction::isValid() const { return location.line() != -1; } void ScriptFunction::load(PersistentPool &pool) { sourceCode = pool.idLoadString(); argumentNames = pool.idLoadStringList(); location.load(pool); fileContext = pool.idLoadS(); } void ScriptFunction::store(PersistentPool &pool) const { pool.storeString(sourceCode); pool.storeStringList(argumentNames); location.store(pool); pool.store(fileContext); } bool operator==(const ScriptFunction &a, const ScriptFunction &b) { return a.sourceCode == b.sourceCode && a.location == b.location && a.argumentNames == b.argumentNames && equals(a.fileContext.data(), b.fileContext.data()); } void ResolvedModule::load(PersistentPool &pool) { name = pool.idLoadString(); moduleDependencies = pool.idLoadStringList(); setupBuildEnvironmentScript = pool.idLoadS(); setupRunEnvironmentScript = pool.idLoadS(); } void ResolvedModule::store(PersistentPool &pool) const { pool.storeString(name); pool.storeStringList(moduleDependencies); pool.store(setupBuildEnvironmentScript); pool.store(setupRunEnvironmentScript); } bool operator==(const ResolvedModule &m1, const ResolvedModule &m2) { return m1.name == m2.name && m1.moduleDependencies.toSet() == m2.moduleDependencies.toSet() && equals(m1.setupBuildEnvironmentScript.data(), m2.setupBuildEnvironmentScript.data()) && equals(m1.setupRunEnvironmentScript.data(), m2.setupRunEnvironmentScript.data()); } QString Rule::toString() const { QStringList outputTagsSorted = collectedOutputFileTags().toStringList(); outputTagsSorted.sort(); QStringList inputTagsSorted = inputs.toStringList(); inputTagsSorted.sort(); return QLatin1Char('[') + outputTagsSorted.join(QLatin1Char(',')) + QLatin1String("][") + inputTagsSorted.join(QLatin1Char(',')) + QLatin1Char(']'); } bool Rule::acceptsAsInput(Artifact *artifact) const { return artifact->fileTags().matches(inputs); } FileTags Rule::staticOutputFileTags() const { FileTags result; foreach (const RuleArtifactConstPtr &artifact, artifacts) result.unite(artifact->fileTags); return result; } FileTags Rule::collectedOutputFileTags() const { return outputFileTags.isEmpty() ? staticOutputFileTags() : outputFileTags; } bool Rule::isDynamic() const { return outputArtifactsScript->isValid(); } void Rule::load(PersistentPool &pool) { name = pool.idLoadString(); prepareScript = pool.idLoadS(); outputArtifactsScript = pool.idLoadS(); module = pool.idLoadS(); pool.stream() >> inputs >> outputFileTags >> auxiliaryInputs >> excludedAuxiliaryInputs >> inputsFromDependencies >> explicitlyDependsOn >> multiplex; pool.loadContainerS(artifacts); } void Rule::store(PersistentPool &pool) const { pool.storeString(name); pool.store(prepareScript); pool.store(outputArtifactsScript); pool.store(module); pool.stream() << inputs << outputFileTags << auxiliaryInputs << excludedAuxiliaryInputs << inputsFromDependencies << explicitlyDependsOn << multiplex; pool.storeContainer(artifacts); } ResolvedProduct::ResolvedProduct() : enabled(true) { } ResolvedProduct::~ResolvedProduct() { } void ResolvedProduct::accept(BuildGraphVisitor *visitor) const { if (!buildData) return; foreach (BuildGraphNode * const node, buildData->roots) node->accept(visitor); } /*! * \brief Returns all files of all groups as source artifacts. * This includes the expanded list of wildcards. */ QList ResolvedProduct::allFiles() const { QList lst; foreach (const GroupConstPtr &group, groups) lst += group->allFiles(); return lst; } /*! * \brief Returns all files of all enabled groups as source artifacts. * \sa ResolvedProduct::allFiles() */ QList ResolvedProduct::allEnabledFiles() const { QList lst; foreach (const GroupConstPtr &group, groups) { if (group->enabled) lst += group->allFiles(); } return lst; } FileTags ResolvedProduct::fileTagsForFileName(const QString &fileName) const { FileTags result; foreach (FileTaggerConstPtr tagger, fileTaggers) { foreach (const QRegExp &pattern, tagger->patterns()) { if (FileInfo::globMatches(pattern, fileName)) { result.unite(tagger->fileTags()); break; } } } return result; } void ResolvedProduct::load(PersistentPool &pool) { pool.stream() >> enabled >> fileTags; name = pool.idLoadString(); profile = pool.idLoadString(); targetName = pool.idLoadString(); sourceDirectory = pool.idLoadString(); destinationDirectory = pool.idLoadString(); location.load(pool); productProperties = pool.loadVariantMap(); moduleProperties = pool.idLoadS(); pool.loadContainerS(rules); pool.loadContainerS(dependencies); pool.loadContainerS(fileTaggers); pool.loadContainerS(modules); pool.loadContainerS(transformers); pool.loadContainerS(scanners); pool.loadContainerS(groups); pool.loadContainerS(artifactProperties); buildData.reset(pool.idLoad()); } void ResolvedProduct::store(PersistentPool &pool) const { pool.stream() << enabled << fileTags; pool.storeString(name); pool.storeString(profile); pool.storeString(targetName); pool.storeString(sourceDirectory); pool.storeString(destinationDirectory); location.store(pool); pool.store(productProperties); pool.store(moduleProperties); pool.storeContainer(rules); pool.storeContainer(dependencies); pool.storeContainer(fileTaggers); pool.storeContainer(modules); pool.storeContainer(transformers); pool.storeContainer(scanners); pool.storeContainer(groups); pool.storeContainer(artifactProperties); pool.store(buildData.data()); } QList topSortModules(const QHash > &moduleChildren, const QList &modules, QSet &seenModuleNames) { QList result; foreach (const ResolvedModule *m, modules) { if (m->name.isNull()) continue; result.append(topSortModules(moduleChildren, moduleChildren.value(m), seenModuleNames)); if (!seenModuleNames.contains(m->name)) { seenModuleNames.insert(m->name); result.append(m); } } return result; } static QScriptValue js_getEnv(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(context->argumentCount() < 1)) return context->throwError(QScriptContext::SyntaxError, QLatin1String("getEnv expects 1 argument")); QVariant v = engine->property("_qbs_procenv"); QProcessEnvironment *procenv = reinterpret_cast(v.value()); return engine->toScriptValue(procenv->value(context->argument(0).toString())); } static QScriptValue js_putEnv(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(context->argumentCount() < 2)) return context->throwError(QScriptContext::SyntaxError, QLatin1String("putEnv expects 2 arguments")); QVariant v = engine->property("_qbs_procenv"); QProcessEnvironment *procenv = reinterpret_cast(v.value()); procenv->insert(context->argument(0).toString(), context->argument(1).toString()); return engine->undefinedValue(); } static QScriptValue js_unsetEnv(QScriptContext *context, QScriptEngine *engine) { if (Q_UNLIKELY(context->argumentCount() < 1)) return context->throwError(QScriptContext::SyntaxError, QLatin1String("unsetEnv expects 1 argument")); QVariant v = engine->property("_qbs_procenv"); QProcessEnvironment *procenv = reinterpret_cast(v.value()); procenv->remove(context->argument(0).toString()); return engine->undefinedValue(); } static QScriptValue js_currentEnv(QScriptContext *context, QScriptEngine *engine) { Q_UNUSED(context); QVariant v = engine->property("_qbs_procenv"); const QProcessEnvironment * const procenv = reinterpret_cast(v.value()); QScriptValue envObject = engine->newObject(); foreach (const QString &key, procenv->keys()) envObject.setProperty(key, QScriptValue(procenv->value(key))); return envObject; } enum EnvType { BuildEnv, RunEnv }; static bool findModuleMapRecursively_impl(const QVariantMap &cfg, const QString &moduleName, QVariantMap *result) { for (QVariantMap::const_iterator it = cfg.constBegin(); it != cfg.constEnd(); ++it) { if (it.key() == moduleName) { *result = it.value().toMap(); return true; } if (findModuleMapRecursively_impl(it.value().toMap().value(QStringLiteral("modules")).toMap(), moduleName, result)) { return true; } } return false; } static QVariantMap findModuleMapRecursively(const QVariantMap &cfg, const QString &moduleName) { QVariantMap result; findModuleMapRecursively_impl(cfg, moduleName, &result); return result; } static QProcessEnvironment getProcessEnvironment(ScriptEngine *engine, EnvType envType, const QList &modules, const PropertyMapConstPtr &productConfiguration, const QProcessEnvironment &env) { QMap moduleMap; foreach (const ResolvedModuleConstPtr &module, modules) moduleMap.insert(module->name, module.data()); QHash > moduleParents; QHash > moduleChildren; foreach (ResolvedModuleConstPtr module, modules) { foreach (const QString &moduleName, module->moduleDependencies) { const ResolvedModule * const depmod = moduleMap.value(moduleName); QBS_ASSERT(depmod, return env); moduleParents[depmod].append(module.data()); moduleChildren[module.data()].append(depmod); } } QList rootModules; foreach (ResolvedModuleConstPtr module, modules) { if (moduleParents.value(module.data()).isEmpty()) { QBS_ASSERT(module, return env); rootModules.append(module.data()); } } QProcessEnvironment procenv = env; { QVariant v; v.setValue(&procenv); engine->setProperty("_qbs_procenv", v); } engine->clearImportsCache(); QScriptValue scope = engine->newObject(); const QScriptValue getEnvValue = engine->newFunction(js_getEnv, 1); const QScriptValue putEnvValue = engine->newFunction(js_putEnv, 2); const QScriptValue unsetEnvValue = engine->newFunction(js_unsetEnv, 1); const QScriptValue currentEnvValue = engine->newFunction(js_currentEnv, 0); scope.setProperty(QLatin1String("getEnv"), getEnvValue); scope.setProperty(QLatin1String("putEnv"), putEnvValue); scope.setProperty(QLatin1String("unsetEnv"), unsetEnvValue); scope.setProperty(QLatin1String("currentEnv"), currentEnvValue); QSet seenModuleNames; QList topSortedModules = topSortModules(moduleChildren, rootModules, seenModuleNames); foreach (const ResolvedModule *module, topSortedModules) { if ((envType == BuildEnv && module->setupBuildEnvironmentScript->sourceCode.isEmpty()) || (envType == RunEnv && module->setupBuildEnvironmentScript->sourceCode.isEmpty() && module->setupRunEnvironmentScript->sourceCode.isEmpty())) continue; ScriptFunctionConstPtr setupScript; if (envType == BuildEnv) { setupScript = module->setupBuildEnvironmentScript; } else { if (!module->setupRunEnvironmentScript) setupScript = module->setupBuildEnvironmentScript; else setupScript = module->setupRunEnvironmentScript; } // handle imports engine->import(setupScript->fileContext, scope, scope); JsExtensions::setupExtensions(setupScript->fileContext->jsExtensions(), scope); // expose properties of direct module dependencies QScriptValue scriptValue; QVariantMap productModules = productConfiguration->value() .value(QLatin1String("modules")).toMap(); foreach (const ResolvedModule * const depmod, moduleChildren.value(module)) { scriptValue = engine->newObject(); QVariantMap moduleCfg = productModules.value(depmod->name).toMap(); for (QVariantMap::const_iterator it = moduleCfg.constBegin(); it != moduleCfg.constEnd(); ++it) scriptValue.setProperty(it.key(), engine->toScriptValue(it.value())); scope.setProperty(depmod->name, scriptValue); } // expose the module's properties QVariantMap moduleCfg = findModuleMapRecursively(productModules, module->name); for (QVariantMap::const_iterator it = moduleCfg.constBegin(); it != moduleCfg.constEnd(); ++it) scope.setProperty(it.key(), engine->toScriptValue(it.value())); QScriptContext *ctx = engine->currentContext(); ctx->pushScope(scope); scriptValue = engine->evaluate(setupScript->sourceCode + QLatin1String("()")); ctx->popScope(); if (Q_UNLIKELY(engine->hasErrorOrException(scriptValue))) { QString envTypeStr = (envType == BuildEnv ? QLatin1String("build") : QLatin1String("run")); throw ErrorInfo(Tr::tr("Error while setting up %1 environment: %2") .arg(envTypeStr, engine->lastErrorString(scriptValue)), setupScript->location); } } engine->setProperty("_qbs_procenv", QVariant()); return procenv; } void ResolvedProduct::setupBuildEnvironment(ScriptEngine *engine, const QProcessEnvironment &env) const { if (!buildEnvironment.isEmpty()) return; buildEnvironment = getProcessEnvironment(engine, BuildEnv, modules, moduleProperties, env); } void ResolvedProduct::setupRunEnvironment(ScriptEngine *engine, const QProcessEnvironment &env) const { if (!runEnvironment.isEmpty()) return; runEnvironment = getProcessEnvironment(engine, RunEnv, modules, moduleProperties, env); } void ResolvedProduct::registerArtifactWithChangedInputs(Artifact *artifact) { QBS_CHECK(buildData); QBS_CHECK(artifact->product == this); QBS_CHECK(artifact->transformer); if (artifact->transformer->rule->multiplex) { // Reapplication of rules only makes sense for multiplex rules (e.g. linker). buildData->artifactsWithChangedInputsPerRule[artifact->transformer->rule] += artifact; } } void ResolvedProduct::unregisterArtifactWithChangedInputs(Artifact *artifact) { QBS_CHECK(buildData); QBS_CHECK(artifact->product == this); QBS_CHECK(artifact->transformer); buildData->artifactsWithChangedInputsPerRule[artifact->transformer->rule] -= artifact; } void ResolvedProduct::unmarkForReapplication(const RuleConstPtr &rule) { QBS_CHECK(buildData); buildData->artifactsWithChangedInputsPerRule.remove(rule); } bool ResolvedProduct::isMarkedForReapplication(const RuleConstPtr &rule) const { return !buildData->artifactsWithChangedInputsPerRule.value(rule).isEmpty(); } ArtifactSet ResolvedProduct::lookupArtifactsByFileTag(const FileTag &tag) const { QBS_CHECK(buildData); return buildData->artifactsByFileTag.value(tag); } ArtifactSet ResolvedProduct::targetArtifacts() const { QBS_CHECK(buildData); ArtifactSet taSet; foreach (Artifact * const a, buildData->rootArtifacts()) { if (a->fileTags().matches(fileTags)) taSet << a; } return taSet; } TopLevelProject *ResolvedProduct::topLevelProject() const { return project->topLevelProject(); } QString ResolvedProduct::uniqueName(const QString &name, const QString &profile) { QBS_CHECK(!profile.isEmpty()); return name + QLatin1Char('.') + profile; } QString ResolvedProduct::uniqueName() const { return uniqueName(name, profile); } static QStringList findGeneratedFiles(const Artifact *base, const FileTags &tags) { QStringList result; foreach (const Artifact *parent, base->parentArtifacts()) { if (tags.isEmpty() || parent->fileTags().matches(tags)) result << parent->filePath(); } if (result.isEmpty() || tags.isEmpty()) foreach (const Artifact *parent, base->parentArtifacts()) result << findGeneratedFiles(parent, tags); return result; } QStringList ResolvedProduct::generatedFiles(const QString &baseFile, const FileTags &tags) const { ProductBuildData *data = buildData.data(); if (!data) return QStringList(); foreach (const Artifact *art, ArtifactSet::fromNodeSet(data->nodes)) { if (art->filePath() == baseFile) return findGeneratedFiles(art, tags); } return QStringList(); } QString ResolvedProduct::deriveBuildDirectoryName(const QString &name, const QString &profile) { QString dirName = uniqueName(name, profile); const QByteArray hash = QCryptographicHash::hash(dirName.toUtf8(), QCryptographicHash::Sha1); return HostOsInfo::rfc1034Identifier(dirName) .append(QLatin1Char('.')) .append(QString::fromLatin1(hash.toHex().left(8))); } QString ResolvedProduct::buildDirectory() const { const QString result = productProperties.value(QLatin1String("buildDirectory")).toString(); QBS_CHECK(!result.isEmpty()); return result; } bool ResolvedProduct::isInParentProject(const ResolvedProductConstPtr &other) const { for (const ResolvedProject *otherParent = other->project.data(); otherParent; otherParent = otherParent->parentProject.data()) { if (otherParent == project.data()) return true; } return false; } bool ResolvedProduct::builtByDefault() const { return productProperties.value(QLatin1String("builtByDefault"), true).toBool(); } void ResolvedProduct::cacheExecutablePath(const QString &origFilePath, const QString &fullFilePath) { QMutexLocker locker(&m_executablePathCacheLock); m_executablePathCache.insert(origFilePath, fullFilePath); } QString ResolvedProduct::cachedExecutablePath(const QString &origFilePath) const { QMutexLocker locker(&m_executablePathCacheLock); return m_executablePathCache.value(origFilePath); } ResolvedProject::ResolvedProject() : enabled(true), m_topLevelProject(0) { } void ResolvedProject::accept(BuildGraphVisitor *visitor) const { foreach (const ResolvedProductPtr &product, products) product->accept(visitor); foreach (const ResolvedProjectPtr &subProject, subProjects) subProject->accept(visitor); } TopLevelProject *ResolvedProject::topLevelProject() { if (m_topLevelProject) return m_topLevelProject; TopLevelProject *tlp = dynamic_cast(this); if (tlp) { m_topLevelProject = tlp; return m_topLevelProject; } QBS_CHECK(!parentProject.isNull()); m_topLevelProject = parentProject->topLevelProject(); return m_topLevelProject; } QList ResolvedProject::allSubProjects() const { QList projectList = subProjects; foreach (const ResolvedProjectConstPtr &subProject, subProjects) projectList << subProject->allSubProjects(); return projectList; } QList ResolvedProject::allProducts() const { QList productList = products; foreach (const ResolvedProjectConstPtr &subProject, subProjects) productList << subProject->allProducts(); return productList; } void ResolvedProject::load(PersistentPool &pool) { name = pool.idLoadString(); location.load(pool); int count; pool.stream() >> enabled >> count; products.clear(); products.reserve(count); for (; --count >= 0;) { ResolvedProductPtr rProduct = pool.idLoadS(); if (rProduct->buildData) { foreach (BuildGraphNode * const node, rProduct->buildData->nodes) { node->product = rProduct; // restore parent links foreach (BuildGraphNode *child, node->children) child->parents.insert(node); } } products.append(rProduct); } pool.stream() >> count; subProjects.clear(); subProjects.reserve(count); for (; --count >= 0;) { ResolvedProjectPtr p = pool.idLoadS(); subProjects.append(p); } m_projectProperties = pool.loadVariantMap(); } void ResolvedProject::store(PersistentPool &pool) const { pool.storeString(name); location.store(pool); pool.stream() << enabled << products.count(); foreach (const ResolvedProductConstPtr &product, products) pool.store(product); pool.stream() << subProjects.count(); foreach (const ResolvedProjectConstPtr &project, subProjects) pool.store(project); pool.store(m_projectProperties); } TopLevelProject::TopLevelProject() : bgLocker(0), locked(false), lastResolveTime(FileTime::oldestTime()) { } TopLevelProject::~TopLevelProject() { delete bgLocker; } QString TopLevelProject::deriveId(const QString &profile, const QVariantMap &config) { const QVariantMap qbsProperties = config.value(QLatin1String("qbs")).toMap(); const QString buildVariant = qbsProperties.value(QLatin1String("buildVariant")).toString(); QString prefix = profile; if (prefix.isEmpty()) prefix = QLatin1String("no-profile"); return prefix + QLatin1Char('-') + buildVariant; } QString TopLevelProject::deriveBuildDirectory(const QString &buildRoot, const QString &id) { return buildRoot + QLatin1Char('/') + id; } void TopLevelProject::setBuildConfiguration(const QVariantMap &config) { m_buildConfiguration = config; m_id = deriveId(profile(), config); } QString TopLevelProject::profile() const { return projectProperties().value(QLatin1String("profile")).toString(); } QString TopLevelProject::buildGraphFilePath() const { return ProjectBuildData::deriveBuildGraphFilePath(buildDirectory, id()); } void TopLevelProject::store(const Logger &logger) const { // TODO: Use progress observer here. if (!buildData) return; if (!buildData->isDirty) { logger.qbsDebug() << "[BG] build graph is unchanged in project " << id() << "."; return; } const QString fileName = buildGraphFilePath(); logger.qbsDebug() << "[BG] storing: " << fileName; PersistentPool pool(logger); PersistentPool::HeadData headData; headData.projectConfig = buildConfiguration(); pool.setHeadData(headData); pool.setupWriteStream(fileName); store(pool); pool.finalizeWriteStream(); buildData->isDirty = false; } void TopLevelProject::load(PersistentPool &pool) { ResolvedProject::load(pool); m_id = pool.idLoadString(); pool.stream() >> usedEnvironment; pool.stream() >> canonicalFilePathResults; pool.stream() >> fileExistsResults; pool.stream() >> fileLastModifiedResults; QHash envHash; pool.stream() >> envHash; for (QHash::const_iterator i = envHash.begin(); i != envHash.end(); ++i) environment.insert(i.key(), i.value()); pool.stream() >> profileConfigs; pool.stream() >> buildSystemFiles; pool.stream() >> lastResolveTime; buildData.reset(pool.idLoad()); QBS_CHECK(buildData); buildData->isDirty = false; } void TopLevelProject::store(PersistentPool &pool) const { ResolvedProject::store(pool); pool.storeString(m_id); pool.stream() << usedEnvironment << canonicalFilePathResults << fileExistsResults << fileLastModifiedResults; QHash envHash; foreach (const QString &key, environment.keys()) envHash.insert(key, environment.value(key)); pool.stream() << envHash; pool.stream() << profileConfigs; pool.stream() << buildSystemFiles; pool.stream() << lastResolveTime; pool.store(buildData.data()); } /*! * \class SourceWildCards * \brief Objects of the \c SourceWildCards class result from giving wildcards in a * \c ResolvedGroup's "files" binding. * \sa ResolvedGroup */ /*! * \variable SourceWildCards::prefix * \brief Inherited from the \c ResolvedGroup * \sa ResolvedGroup */ /*! * \variable SourceWildCards::patterns * \brief All elements of the \c ResolvedGroup's "files" binding that contain wildcards. * \sa ResolvedGroup */ /*! * \variable SourceWildCards::excludePatterns * \brief Corresponds to the \c ResolvedGroup's "excludeFiles" binding. * \sa ResolvedGroup */ /*! * \variable SourceWildCards::files * \brief The \c SourceArtifacts resulting from the expanded list of matching files. */ QSet SourceWildCards::expandPatterns(const GroupConstPtr &group, const QString &baseDir) const { QSet files = expandPatterns(group, patterns, baseDir); files -= expandPatterns(group, excludePatterns, baseDir); return files; } QSet SourceWildCards::expandPatterns(const GroupConstPtr &group, const QStringList &patterns, const QString &baseDir) const { QSet files; QString expandedPrefix = prefix; if (expandedPrefix.startsWith(QLatin1String("~/"))) expandedPrefix.replace(0, 1, QDir::homePath()); foreach (QString pattern, patterns) { pattern.prepend(expandedPrefix); pattern.replace(QLatin1Char('\\'), QLatin1Char('/')); QStringList parts = pattern.split(QLatin1Char('/'), QString::SkipEmptyParts); if (FileInfo::isAbsolute(pattern)) { QString rootDir; if (HostOsInfo::isWindowsHost() && pattern.at(0) != QLatin1Char('/')) { rootDir = parts.takeFirst(); if (!rootDir.endsWith(QLatin1Char('/'))) rootDir.append(QLatin1Char('/')); } else { rootDir = QLatin1Char('/'); } expandPatterns(files, group, parts, rootDir); } else { expandPatterns(files, group, parts, baseDir); } } return files; } static bool isQbsBuildDir(const QDir &dir) { return dir.exists(dir.dirName() + QLatin1String(".bg")); } void SourceWildCards::expandPatterns(QSet &result, const GroupConstPtr &group, const QStringList &parts, const QString &baseDir) const { // People might build directly in the project source directory. This is okay, since // we keep the build data in a "container" directory. However, we must make sure we don't // match any generated files therein as source files. if (isQbsBuildDir(baseDir)) return; QStringList changed_parts = parts; bool recursive = false; QString part = changed_parts.takeFirst(); while (part == QLatin1String("**")) { recursive = true; if (changed_parts.isEmpty()) { part = QLatin1String("*"); break; } part = changed_parts.takeFirst(); } const bool isDir = !changed_parts.isEmpty(); const QString &filePattern = part; const QDirIterator::IteratorFlags itFlags = recursive ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags; QDir::Filters itFilters = isDir ? QDir::Dirs : QDir::Files; if (isDir && !FileInfo::isPattern(filePattern)) itFilters |= QDir::Hidden; if (filePattern != QLatin1String("..") && filePattern != QLatin1String(".")) itFilters |= QDir::NoDotAndDotDot; QDirIterator it(baseDir, QStringList(filePattern), itFilters, itFlags); while (it.hasNext()) { const QString filePath = it.next(); if (isQbsBuildDir(it.fileInfo().dir())) continue; // See above. QBS_ASSERT(FileInfo(filePath).isDir() == isDir, break); if (isDir) expandPatterns(result, group, changed_parts, filePath); else result += QDir::cleanPath(filePath); } } void ResolvedTransformer::load(PersistentPool &pool) { module = pool.idLoadS(); pool.stream() >> inputs; pool.loadContainerS(outputs); transform = pool.idLoadS(); pool.stream() >> explicitlyDependsOn; } void ResolvedTransformer::store(PersistentPool &pool) const { pool.store(module); pool.stream() << inputs; pool.storeContainer(outputs); pool.store(transform); pool.stream() << explicitlyDependsOn; } template QMap listToMap(const QList &list) { QMap map; foreach (const T &elem, list) map.insert(keyFromElem(elem), elem); return map; } template bool listsAreEqual(const QList &l1, const QList &l2) { if (l1.count() != l2.count()) return false; const QMap map1 = listToMap(l1); const QMap map2 = listToMap(l2); foreach (const QString &key, map1.keys()) { const T value2 = map2.value(key); if (!value2) return false; if (!equals(map1.value(key).data(), value2.data())) return false; } return true; } QString keyFromElem(const SourceArtifactPtr &sa) { return sa->absoluteFilePath; } QString keyFromElem(const ResolvedTransformerPtr &t) { return t->transform->sourceCode; } QString keyFromElem(const RulePtr &r) { return r->toString(); } QString keyFromElem(const ArtifactPropertiesPtr &ap) { QStringList lst = ap->fileTagsFilter().toStringList(); lst.sort(); return lst.join(QLatin1Char(',')); } bool operator==(const SourceArtifactInternal &sa1, const SourceArtifactInternal &sa2) { return sa1.absoluteFilePath == sa2.absoluteFilePath && sa1.fileTags == sa2.fileTags && sa1.overrideFileTags == sa2.overrideFileTags && sa1.properties->value() == sa2.properties->value(); } bool sourceArtifactSetsAreEqual(const QList &l1, const QList &l2) { return listsAreEqual(l1, l2); } bool operator==(const ResolvedTransformer &t1, const ResolvedTransformer &t2) { return equals(t1.module.data(), t2.module.data()) && t1.inputs.toSet() == t2.inputs.toSet() && sourceArtifactSetsAreEqual(t1.outputs, t2.outputs) && equals(t1.transform.data(), t2.transform.data()) && t1.explicitlyDependsOn == t2.explicitlyDependsOn; } bool transformerListsAreEqual(const QList &l1, const QList &l2) { return listsAreEqual(l1, l2); } bool operator==(const Rule &r1, const Rule &r2) { if (r1.artifacts.count() != r2.artifacts.count()) return false; for (int i = 0; i < r1.artifacts.count(); ++i) { if (!equals(r1.artifacts.at(i).data(), r2.artifacts.at(i).data())) return false; } return r1.module->name == r2.module->name && equals(r1.prepareScript.data(), r2.prepareScript.data()) && equals(r1.outputArtifactsScript.data(), r2.outputArtifactsScript.data()) && r1.inputs == r2.inputs && r1.outputFileTags == r2.outputFileTags && r1.auxiliaryInputs == r2.auxiliaryInputs && r1.excludedAuxiliaryInputs == r2.excludedAuxiliaryInputs && r1.inputsFromDependencies == r2.inputsFromDependencies && r1.explicitlyDependsOn == r2.explicitlyDependsOn && r1.multiplex == r2.multiplex; } bool ruleListsAreEqual(const QList &l1, const QList &l2) { return listsAreEqual(l1, l2); } bool operator==(const RuleArtifact &a1, const RuleArtifact &a2) { return a1.filePath == a2.filePath && a1.fileTags == a2.fileTags && a1.alwaysUpdated == a2.alwaysUpdated && a1.bindings.toList().toSet() == a2.bindings.toList().toSet(); } bool operator==(const RuleArtifact::Binding &b1, const RuleArtifact::Binding &b2) { return b1.code == b2.code && b1.name == b2.name; } uint qHash(const RuleArtifact::Binding &b) { return qHash(qMakePair(b.code, b.name.join(QLatin1Char(',')))); } bool artifactPropertyListsAreEqual(const QList &l1, const QList &l2) { return listsAreEqual(l1, l2); } void ResolvedScanner::load(PersistentPool &pool) { module = pool.idLoadS(); pool.stream() >> inputs >> recursive; searchPathsScript = pool.idLoadS(); scanScript = pool.idLoadS(); } void ResolvedScanner::store(PersistentPool &pool) const { pool.store(module); pool.stream() << inputs << recursive; pool.store(searchPathsScript); pool.store(scanScript); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/language.h000066400000000000000000000372541266132464200216070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_LANGUAGE_H #define QBS_LANGUAGE_H #include "filetags.h" #include "forward_decls.h" #include "jsimports.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QScriptEngine; QT_END_NAMESPACE namespace qbs { namespace Internal { class BuildGraphLocker; class BuildGraphLoader; class BuildGraphVisitor; class FileTagger : public PersistentObject { public: static FileTaggerPtr create() { return FileTaggerPtr(new FileTagger); } static FileTaggerPtr create(const QStringList &patterns, const FileTags &fileTags) { return FileTaggerPtr(new FileTagger(patterns, fileTags)); } const QList &patterns() const { return m_patterns; } const FileTags &fileTags() const { return m_fileTags; } private: FileTagger(const QStringList &patterns, const FileTags &fileTags); FileTagger() {} void setPatterns(const QStringList &patterns); void load(PersistentPool &); void store(PersistentPool &) const; QList m_patterns; FileTags m_fileTags; }; class RuleArtifact : public PersistentObject { public: static RuleArtifactPtr create() { return RuleArtifactPtr(new RuleArtifact); } QString filePath; FileTags fileTags; bool alwaysUpdated; CodeLocation location; class Binding { public: QStringList name; QString code; CodeLocation location; }; QVector bindings; private: RuleArtifact() : alwaysUpdated(true) {} void load(PersistentPool &pool); void store(PersistentPool &pool) const; }; uint qHash(const RuleArtifact::Binding &b); bool operator==(const RuleArtifact::Binding &b1, const RuleArtifact::Binding &b2); inline bool operator!=(const RuleArtifact::Binding &b1, const RuleArtifact::Binding &b2) { return !(b1 == b2); } bool operator==(const RuleArtifact &a1, const RuleArtifact &a2); inline bool operator!=(const RuleArtifact &a1, const RuleArtifact &a2) { return !(a1 == a2); } class SourceArtifactInternal : public PersistentObject { public: static SourceArtifactPtr create() { return SourceArtifactPtr(new SourceArtifactInternal); } QString absoluteFilePath; FileTags fileTags; bool overrideFileTags; PropertyMapPtr properties; private: SourceArtifactInternal() : overrideFileTags(true) {} void load(PersistentPool &pool); void store(PersistentPool &pool) const; }; bool operator==(const SourceArtifactInternal &sa1, const SourceArtifactInternal &sa2); inline bool operator!=(const SourceArtifactInternal &sa1, const SourceArtifactInternal &sa2) { return !(sa1 == sa2); } bool sourceArtifactSetsAreEqual(const QList &l1, const QList &l2); class SourceWildCards : public PersistentObject { public: typedef QSharedPointer Ptr; typedef QSharedPointer ConstPtr; static Ptr create() { return Ptr(new SourceWildCards); } QSet expandPatterns(const GroupConstPtr &group, const QString &baseDir) const; // TODO: Use back pointer to Group instead? QString prefix; QStringList patterns; QStringList excludePatterns; QList files; private: SourceWildCards() {} QSet expandPatterns(const GroupConstPtr &group, const QStringList &patterns, const QString &baseDir) const; void expandPatterns(QSet &result, const GroupConstPtr &group, const QStringList &parts, const QString &baseDir) const; void load(PersistentPool &pool); void store(PersistentPool &pool) const; }; class ResolvedGroup : public PersistentObject { public: static GroupPtr create() { return GroupPtr(new ResolvedGroup); } CodeLocation location; QString name; bool enabled; QString prefix; QList files; SourceWildCards::Ptr wildcards; PropertyMapPtr properties; FileTags fileTags; bool overrideTags; QList allFiles() const; private: ResolvedGroup() : enabled(true) {} void load(PersistentPool &pool); void store(PersistentPool &pool) const; }; class ScriptFunction : public PersistentObject { public: static ScriptFunctionPtr create() { return ScriptFunctionPtr(new ScriptFunction); } ~ScriptFunction(); QString sourceCode; QStringList argumentNames; CodeLocation location; ResolvedFileContextConstPtr fileContext; mutable QScriptValue scriptFunction; // cache bool isValid() const; private: ScriptFunction(); void load(PersistentPool &); void store(PersistentPool &) const; }; bool operator==(const ScriptFunction &a, const ScriptFunction &b); inline bool operator!=(const ScriptFunction &a, const ScriptFunction &b) { return !(a == b); } class ResolvedModule : public PersistentObject { public: static ResolvedModulePtr create() { return ResolvedModulePtr(new ResolvedModule); } QString name; QStringList moduleDependencies; ScriptFunctionPtr setupBuildEnvironmentScript; ScriptFunctionPtr setupRunEnvironmentScript; private: ResolvedModule() {} void load(PersistentPool &pool); void store(PersistentPool &pool) const; }; bool operator==(const ResolvedModule &m1, const ResolvedModule &m2); inline bool operator!=(const ResolvedModule &m1, const ResolvedModule &m2) { return !(m1 == m2); } /** * Per default each rule is a "non-multiplex rule". * * A "multiplex rule" creates one transformer that takes all * input artifacts with the matching input file tag and creates * one or more artifacts. (e.g. linker rule) * * A "non-multiplex rule" creates one transformer per matching input file. */ class Rule : public PersistentObject { public: static RulePtr create() { return RulePtr(new Rule); } ResolvedModuleConstPtr module; QString name; ScriptFunctionPtr prepareScript; FileTags outputFileTags; // unused, if artifacts is non-empty ScriptFunctionPtr outputArtifactsScript; // unused, if artifacts is non-empty FileTags inputs; FileTags auxiliaryInputs; FileTags excludedAuxiliaryInputs; FileTags inputsFromDependencies; FileTags explicitlyDependsOn; bool multiplex; QList artifacts; // unused, if outputFileTags/outputArtifactsScript is non-empty // members that we don't need to save int ruleGraphId; QString toString() const; bool acceptsAsInput(Artifact *artifact) const; FileTags staticOutputFileTags() const; FileTags collectedOutputFileTags() const; bool isDynamic() const; private: Rule() : multiplex(false), ruleGraphId(-1) {} void load(PersistentPool &pool); void store(PersistentPool &pool) const; }; bool operator==(const Rule &r1, const Rule &r2); inline bool operator!=(const Rule &r1, const Rule &r2) { return !(r1 == r2); } bool ruleListsAreEqual(const QList &l1, const QList &l2); class ResolvedTransformer : public PersistentObject { public: static ResolvedTransformerPtr create() { return ResolvedTransformerPtr(new ResolvedTransformer); } ResolvedModuleConstPtr module; QStringList inputs; QList outputs; ScriptFunctionPtr transform; FileTags explicitlyDependsOn; private: ResolvedTransformer() {} void load(PersistentPool &pool); void store(PersistentPool &pool) const; }; bool operator==(const ResolvedTransformer &t1, const ResolvedTransformer &t2); inline bool operator!=(const ResolvedTransformer &t1, const ResolvedTransformer &t2) { return !(t1 == t2); } bool transformerListsAreEqual(const QList &l1, const QList &l2); class ResolvedScanner : public PersistentObject { public: static ResolvedScannerPtr create() { return ResolvedScannerPtr(new ResolvedScanner); } ResolvedModuleConstPtr module; FileTags inputs; bool recursive; ScriptFunctionPtr searchPathsScript; ScriptFunctionPtr scanScript; private: ResolvedScanner() : recursive(false) {} void load(PersistentPool &pool); void store(PersistentPool &pool) const; }; class TopLevelProject; class ScriptEngine; class ResolvedProduct : public PersistentObject { public: static ResolvedProductPtr create() { return ResolvedProductPtr(new ResolvedProduct); } ~ResolvedProduct(); bool enabled; FileTags fileTags; QString name; QString targetName; QString profile; QString sourceDirectory; QString destinationDirectory; CodeLocation location; WeakPointer project; QVariantMap productProperties; PropertyMapPtr moduleProperties; QSet rules; QSet dependencies; QList fileTaggers; QList modules; QList transformers; QList scanners; QList groups; QList artifactProperties; QScopedPointer buildData; mutable QProcessEnvironment buildEnvironment; // must not be saved mutable QProcessEnvironment runEnvironment; // must not be saved void accept(BuildGraphVisitor *visitor) const; QList allFiles() const; QList allEnabledFiles() const; FileTags fileTagsForFileName(const QString &fileName) const; void setupBuildEnvironment(ScriptEngine *scriptEngine, const QProcessEnvironment &env) const; void setupRunEnvironment(ScriptEngine *scriptEngine, const QProcessEnvironment &env) const; void registerArtifactWithChangedInputs(Artifact *artifact); void unregisterArtifactWithChangedInputs(Artifact *artifact); void unmarkForReapplication(const RuleConstPtr &rule); bool isMarkedForReapplication(const RuleConstPtr &rule) const; ArtifactSet lookupArtifactsByFileTag(const FileTag &tag) const; ArtifactSet targetArtifacts() const; TopLevelProject *topLevelProject() const; static QString uniqueName(const QString &name, const QString &profile); QString uniqueName() const; QStringList generatedFiles(const QString &baseFile, const FileTags &tags) const; static QString deriveBuildDirectoryName(const QString &name, const QString &profile); QString buildDirectory() const; bool isInParentProject(const ResolvedProductConstPtr &other) const; bool builtByDefault() const; void cacheExecutablePath(const QString &origFilePath, const QString &fullFilePath); QString cachedExecutablePath(const QString &origFilePath) const; private: ResolvedProduct(); void load(PersistentPool &pool); void store(PersistentPool &pool) const; QHash m_executablePathCache; mutable QMutex m_executablePathCacheLock; }; class ResolvedProject : public PersistentObject { public: static ResolvedProjectPtr create() { return ResolvedProjectPtr(new ResolvedProject); } QString name; CodeLocation location; bool enabled; QList products; QList subProjects; WeakPointer parentProject; void accept(BuildGraphVisitor *visitor) const; void setProjectProperties(const QVariantMap &config) { m_projectProperties = config; } const QVariantMap &projectProperties() const { return m_projectProperties; } TopLevelProject *topLevelProject(); QList allSubProjects() const; QList allProducts() const; protected: ResolvedProject(); void load(PersistentPool &pool); void store(PersistentPool &pool) const; private: QVariantMap m_projectProperties; TopLevelProject *m_topLevelProject; }; class TopLevelProject : public ResolvedProject { friend class BuildGraphLoader; public: ~TopLevelProject(); static TopLevelProjectPtr create() { return TopLevelProjectPtr(new TopLevelProject); } static QString deriveId(const QString &profile, const QVariantMap &config); static QString deriveBuildDirectory(const QString &buildRoot, const QString &id); QString buildDirectory; // Not saved QProcessEnvironment environment; // Environment variables requested by the project while resolving. // TODO: This information is currently not used. Remove in 1.5 or use elaborate change tracking // logic where rules declare the environment variables that could influence their // behavior. QHash usedEnvironment; QHash canonicalFilePathResults; // Results of calls to "File.canonicalFilePath()." QHash fileExistsResults; // Results of calls to "File.exists()". QHash fileLastModifiedResults; // Results of calls to "File.lastModified()". QScopedPointer buildData; BuildGraphLocker *bgLocker; // This holds the system-wide build graph file lock. bool locked; // This is the API-level lock for the project instance. QSet buildSystemFiles; FileTime lastResolveTime; void setBuildConfiguration(const QVariantMap &config); const QVariantMap &buildConfiguration() const { return m_buildConfiguration; } QString id() const { return m_id; } QString profile() const; QVariantMap profileConfigs; QString buildGraphFilePath() const; void store(const Logger &logger) const; private: TopLevelProject(); void load(PersistentPool &pool); void store(PersistentPool &pool) const; QString m_id; QVariantMap m_buildConfiguration; }; bool artifactPropertyListsAreEqual(const QList &l1, const QList &l2); } // namespace Internal } // namespace qbs QT_BEGIN_NAMESPACE Q_DECLARE_TYPEINFO(qbs::Internal::JsImport, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(qbs::Internal::RuleArtifact::Binding, Q_MOVABLE_TYPE); QT_END_NAMESPACE #endif // QBS_LANGUAGE_H qbs-src-1.4.5/src/lib/corelib/language/language.pri000066400000000000000000000043171266132464200221440ustar00rootroot00000000000000include(../../../install_prefix.pri) HEADERS += \ $$PWD/artifactproperties.h \ $$PWD/asttools.h \ $$PWD/builtindeclarations.h \ $$PWD/builtinvalue.h \ $$PWD/deprecationinfo.h \ $$PWD/evaluationdata.h \ $$PWD/evaluator.h \ $$PWD/evaluatorscriptclass.h \ $$PWD/filecontext.h \ $$PWD/filecontextbase.h \ $$PWD/filetags.h \ $$PWD/forward_decls.h \ $$PWD/functiondeclaration.h \ $$PWD/identifiersearch.h \ $$PWD/item.h \ $$PWD/itemdeclaration.h \ $$PWD/itemobserver.h \ $$PWD/itempool.h \ $$PWD/itemreader.h \ $$PWD/itemreaderastvisitor.h \ $$PWD/itemreadervisitorstate.h \ $$PWD/jsimports.h \ $$PWD/language.h \ $$PWD/loader.h \ $$PWD/moduleloader.h \ $$PWD/modulemerger.h \ $$PWD/preparescriptobserver.h \ $$PWD/projectresolver.h \ $$PWD/property.h \ $$PWD/propertydeclaration.h \ $$PWD/propertymapinternal.h \ $$PWD/qualifiedid.h \ $$PWD/resolvedfilecontext.h \ $$PWD/scriptengine.h \ $$PWD/scriptpropertyobserver.h \ $$PWD/value.h SOURCES += \ $$PWD/artifactproperties.cpp \ $$PWD/asttools.cpp \ $$PWD/builtindeclarations.cpp \ $$PWD/builtinvalue.cpp \ $$PWD/evaluator.cpp \ $$PWD/evaluatorscriptclass.cpp \ $$PWD/filecontext.cpp \ $$PWD/filecontextbase.cpp \ $$PWD/filetags.cpp \ $$PWD/identifiersearch.cpp \ $$PWD/item.cpp \ $$PWD/itemdeclaration.cpp \ $$PWD/itempool.cpp \ $$PWD/itemreader.cpp \ $$PWD/itemreaderastvisitor.cpp \ $$PWD/itemreadervisitorstate.cpp \ $$PWD/language.cpp \ $$PWD/loader.cpp \ $$PWD/moduleloader.cpp \ $$PWD/modulemerger.cpp \ $$PWD/preparescriptobserver.cpp \ $$PWD/projectresolver.cpp \ $$PWD/propertydeclaration.cpp \ $$PWD/propertymapinternal.cpp \ $$PWD/qualifiedid.cpp \ $$PWD/resolvedfilecontext.cpp \ $$PWD/scriptengine.cpp \ $$PWD/value.cpp qbs_enable_unit_tests { HEADERS += $$PWD/tst_language.h SOURCES += $$PWD/tst_language.cpp OTHER_FILES += $$PWD/testdata/* } !qbs_no_dev_install { language_headers.files = $$PWD/forward_decls.h language_headers.path = $${QBS_INSTALL_PREFIX}/include/qbs/language INSTALLS += language_headers } qbs-src-1.4.5/src/lib/corelib/language/loader.cpp000066400000000000000000000107171266132464200216200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "loader.h" #include "language.h" #include "moduleloader.h" #include "projectresolver.h" #include "scriptengine.h" #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { Loader::Loader(ScriptEngine *engine, const Logger &logger) : m_logger(logger) , m_progressObserver(0) , m_engine(engine) { } void Loader::setProgressObserver(ProgressObserver *observer) { m_progressObserver = observer; } void Loader::setSearchPaths(const QStringList &_searchPaths) { QStringList searchPaths; foreach (const QString &searchPath, _searchPaths) { if (!FileInfo::exists(searchPath)) { m_logger.qbsWarning() << Tr::tr("Search path '%1' does not exist.") .arg(QDir::toNativeSeparators(searchPath)); } else { searchPaths += searchPath; } } m_searchPaths = searchPaths; } TopLevelProjectPtr Loader::loadProject(const SetupProjectParameters ¶meters) { QBS_CHECK(QFileInfo(parameters.projectFilePath()).isAbsolute()); m_engine->setEnvironment(parameters.adjustedEnvironment()); m_engine->clearExceptions(); m_engine->clearImportsCache(); m_engine->clearRequestedProperties(); QTimer cancelationTimer; // At this point, we cannot set a sensible total effort, because we know nothing about // the project yet. That's why we use a placeholder here, so the user at least // sees that an operation is starting. The real total effort will be set later when // we have enough information. if (m_progressObserver) { m_progressObserver->initialize(Tr::tr("Resolving project for configuration %1") .arg(TopLevelProject::deriveId(parameters.topLevelProfile(), parameters.finalBuildConfigurationTree())), 1); cancelationTimer.setSingleShot(false); QObject::connect(&cancelationTimer, &QTimer::timeout, [this]() { QBS_ASSERT(m_progressObserver, return); if (m_progressObserver->canceled()) m_engine->cancel(); }); cancelationTimer.start(1000); } const FileTime resolveTime = FileTime::currentTime(); ModuleLoader moduleLoader(m_engine, m_logger); moduleLoader.setProgressObserver(m_progressObserver); moduleLoader.setSearchPaths(m_searchPaths); ModuleLoaderResult loadResult = moduleLoader.load(parameters); ProjectResolver resolver(&moduleLoader, m_logger); resolver.setProgressObserver(m_progressObserver); const TopLevelProjectPtr project = resolver.resolve(loadResult, parameters); project->lastResolveTime = resolveTime; // E.g. if the top-level project is disabled. if (m_progressObserver) m_progressObserver->setFinished(); return project; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/loader.h000066400000000000000000000043431266132464200212630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_LOADER_H #define QBS_LOADER_H #include "forward_decls.h" #include #include namespace qbs { class Settings; class SetupProjectParameters; namespace Internal { class Logger; class ProgressObserver; class ScriptEngine; class Loader { public: Loader(ScriptEngine *engine, const Logger &logger); void setProgressObserver(ProgressObserver *observer); void setSearchPaths(const QStringList &searchPaths); TopLevelProjectPtr loadProject(const SetupProjectParameters ¶meters); private: Logger m_logger; ProgressObserver *m_progressObserver; ScriptEngine * const m_engine; QStringList m_searchPaths; }; } // namespace Internal } // namespace qbs #endif // QBS_LOADER_H qbs-src-1.4.5/src/lib/corelib/language/moduleloader.cpp000066400000000000000000002073041266132464200230260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "moduleloader.h" #include "builtindeclarations.h" #include "builtinvalue.h" #include "evaluator.h" #include "filecontext.h" #include "item.h" #include "itemreader.h" #include "qualifiedid.h" #include "scriptengine.h" #include "value.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class ModuleLoader::ItemModuleList : public QList {}; const QString moduleSearchSubDir = QLatin1String("modules"); ModuleLoader::ModuleLoader(ScriptEngine *engine, const Logger &logger) : m_engine(engine) , m_pool(0) , m_logger(logger) , m_progressObserver(0) , m_reader(new ItemReader(logger)) , m_evaluator(new Evaluator(engine, logger)) { } ModuleLoader::~ModuleLoader() { delete m_evaluator; delete m_reader; } void ModuleLoader::setProgressObserver(ProgressObserver *progressObserver) { m_progressObserver = progressObserver; } static void addExtraModuleSearchPath(QStringList &list, const QString &searchPath) { list += FileInfo::resolvePath(searchPath, moduleSearchSubDir); } void ModuleLoader::setSearchPaths(const QStringList &searchPaths) { m_reader->setSearchPaths(searchPaths); m_moduleDirListCache.clear(); m_moduleSearchPaths.clear(); foreach (const QString &path, searchPaths) addExtraModuleSearchPath(m_moduleSearchPaths, path); if (m_logger.traceEnabled()) { m_logger.qbsTrace() << "[MODLDR] module search paths:"; foreach (const QString &path, m_moduleSearchPaths) m_logger.qbsTrace() << " " << path; } } ModuleLoaderResult ModuleLoader::load(const SetupProjectParameters ¶meters) { if (m_logger.traceEnabled()) m_logger.qbsTrace() << "[MODLDR] load" << parameters.projectFilePath(); m_parameters = parameters; m_validItemPropertyNamesPerItem.clear(); m_productModuleCache.clear(); m_modulePrototypeItemCache.clear(); m_disabledItems.clear(); m_reader->clearExtraSearchPathsStack(); ModuleLoaderResult result; m_pool = result.itemPool.data(); m_reader->setPool(m_pool); Item *root = m_reader->readFile(parameters.projectFilePath()); if (!root) return ModuleLoaderResult(); if (root->typeName() != QLatin1String("Project")) root = wrapWithProject(root); const QString buildDirectory = TopLevelProject::deriveBuildDirectory(parameters.buildRoot(), TopLevelProject::deriveId(parameters.topLevelProfile(), parameters.finalBuildConfigurationTree())); root->setProperty(QLatin1String("sourceDirectory"), VariantValue::create(QFileInfo(root->file()->filePath()).absolutePath())); root->setProperty(QLatin1String("buildDirectory"), VariantValue::create(buildDirectory)); root->setProperty(QLatin1String("profile"), VariantValue::create(m_parameters.topLevelProfile())); handleTopLevelProject(&result, root, buildDirectory, QSet() << QDir::cleanPath(parameters.projectFilePath())); result.root = root; result.qbsFiles = m_reader->filesRead(); return result; } static void handlePropertyError(const ErrorInfo &error, const SetupProjectParameters ¶ms, Logger logger) { if (params.propertyCheckingMode() == SetupProjectParameters::PropertyCheckingStrict) throw error; logger.printWarning(error); } class PropertyDeclarationCheck : public ValueHandler { const QHash > &m_validItemPropertyNamesPerItem; const QSet &m_disabledItems; Item *m_parentItem; QString m_currentName; SetupProjectParameters m_params; Logger m_logger; public: PropertyDeclarationCheck(const QHash > &validItemPropertyNamesPerItem, const QSet &disabledItems, const SetupProjectParameters ¶ms, const Logger &logger) : m_validItemPropertyNamesPerItem(validItemPropertyNamesPerItem) , m_disabledItems(disabledItems) , m_parentItem(0) , m_params(params) , m_logger(logger) { } void operator()(Item *item) { handleItem(item); } private: void handle(JSSourceValue *value) { if (!m_parentItem->propertyDeclaration(m_currentName).isValid() && !value->createdByPropertiesBlock()) { const ErrorInfo error(Tr::tr("Property '%1' is not declared.") .arg(m_currentName), value->location()); handlePropertyError(error, m_params, m_logger); } } void handle(ItemValue *value) { if (!value->item()->isModuleInstance() && !m_validItemPropertyNamesPerItem.value(m_parentItem).contains(m_currentName) && m_parentItem->file() && !m_parentItem->file()->idScope()->hasProperty(m_currentName) && !value->createdByPropertiesBlock()) { const ErrorInfo error(Tr::tr("Item '%1' is not declared. " "Did you forget to add a Depends item?").arg(m_currentName), value->location().isValid() ? value->location() : m_parentItem->location()); handlePropertyError(error, m_params, m_logger); } else { handleItem(value->item()); } } void handleItem(Item *item) { if (m_disabledItems.contains(item) // The Properties child of a SubProject item is not a regular item. || item->typeName() == QLatin1String("Properties")) { return; } Item *oldParentItem = m_parentItem; for (Item::PropertyMap::const_iterator it = item->properties().constBegin(); it != item->properties().constEnd(); ++it) { if (item->propertyDeclaration(it.key()).isValid()) continue; m_currentName = it.key(); m_parentItem = item; it.value()->apply(this); } m_parentItem = oldParentItem; foreach (Item *child, item->children()) { if (child->typeName() != QLatin1String("Export")) handleItem(child); } // Properties that don't refer to an existing module with a matching Depends item // only exist in the prototype, not in the instance. // Example 1 - setting a property of an unknown module: Export { abc.def: true } // Example 2 - setting a non-existing Export property: Export { blubb: true } if (item->typeName() == QLatin1String("Export") && item->prototype()) handleItem(item->prototype()); } void handle(VariantValue *) { /* only created internally - no need to check */ } void handle(BuiltinValue *) { /* only created internally - no need to check */ } }; void ModuleLoader::handleTopLevelProject(ModuleLoaderResult *loadResult, Item *item, const QString &buildDirectory, const QSet &referencedFilePaths) { TopLevelProjectContext tlp; handleProject(loadResult, &tlp, item, buildDirectory, referencedFilePaths); foreach (ProjectContext *projectContext, tlp.projects) { m_reader->setExtraSearchPathsStack(projectContext->searchPathsStack); for (auto it = projectContext->products.begin(); it != projectContext->products.end(); ++it) handleProduct(it); } m_reader->clearExtraSearchPathsStack(); checkItemTypes(item); PropertyDeclarationCheck check(m_validItemPropertyNamesPerItem, m_disabledItems, m_parameters, m_logger); check(item); } void ModuleLoader::handleProject(ModuleLoaderResult *loadResult, TopLevelProjectContext *topLevelProjectContext, Item *item, const QString &buildDirectory, const QSet &referencedFilePaths) { auto *p = new ProjectContext; auto &projectContext = *p; projectContext.topLevelProject = topLevelProjectContext; projectContext.result = loadResult; projectContext.buildDirectory = buildDirectory; ProductContext dummyProductContext; dummyProductContext.project = &projectContext; dummyProductContext.moduleProperties = m_parameters.finalBuildConfigurationTree(); loadBaseModule(&dummyProductContext, item); overrideItemProperties(item, QLatin1String("project"), m_parameters.overriddenValuesTree()); const QString projectName = m_evaluator->stringValue(item, QLatin1String("name")); if (!projectName.isEmpty()) overrideItemProperties(item, projectName, m_parameters.overriddenValuesTree()); if (!checkItemCondition(item)) { delete p; return; } topLevelProjectContext->projects << &projectContext; m_reader->pushExtraSearchPaths(readExtraSearchPaths(item) << item->file()->dirPath()); projectContext.searchPathsStack = m_reader->extraSearchPathsStack(); projectContext.item = item; ItemValuePtr itemValue = ItemValue::create(item); projectContext.scope = Item::create(m_pool); projectContext.scope->setFile(item->file()); projectContext.scope->setProperty(QLatin1String("project"), itemValue); const QString minVersionStr = m_evaluator->stringValue(item, QLatin1String("minimumQbsVersion"), QLatin1String("1.3.0")); const Version minVersion = Version::fromString(minVersionStr); if (!minVersion.isValid()) { throw ErrorInfo(Tr::tr("The value '%1' of Project.minimumQbsVersion " "is not a valid version string.").arg(minVersionStr), item->location()); } if (!m_qbsVersion.isValid()) m_qbsVersion = Version::fromString(QLatin1String(QBS_VERSION)); if (m_qbsVersion < minVersion) { throw ErrorInfo(Tr::tr("The project requires at least qbs version %1, but " "this is qbs version %2.").arg(minVersion.toString(), m_qbsVersion.toString())); } foreach (Item *child, item->children()) { child->setScope(projectContext.scope); if (child->typeName() == QLatin1String("Product")) { foreach (Item * const additionalProductItem, multiplexProductItem(&dummyProductContext, child)) { Item::addChild(item, additionalProductItem); } } } foreach (Item *child, item->children()) { if (child->typeName() == QLatin1String("Product")) { prepareProduct(&projectContext, child); } else if (child->typeName() == QLatin1String("SubProject")) { handleSubProject(&projectContext, child, referencedFilePaths); } else if (child->typeName() == QLatin1String("Project")) { copyProperties(item, child); handleProject(loadResult, topLevelProjectContext, child, buildDirectory, referencedFilePaths); } } const QString projectFileDirPath = FileInfo::path(item->file()->filePath()); const QStringList refs = m_evaluator->stringListValue(item, QLatin1String("references")); typedef QPair ItemAndRefPath; QList additionalProjectChildren; foreach (const QString &filePath, refs) { QString absReferencePath = FileInfo::resolvePath(projectFileDirPath, filePath); if (FileInfo(absReferencePath).isDir()) { QString qbsFilePath; QDirIterator dit(absReferencePath, QStringList(QLatin1String("*.qbs"))); while (dit.hasNext()) { if (!qbsFilePath.isEmpty()) { throw ErrorInfo(Tr::tr("Referenced directory '%1' contains more than one " "qbs file.").arg(absReferencePath), item->property(QLatin1String("references"))->location()); } qbsFilePath = dit.next(); } if (qbsFilePath.isEmpty()) { throw ErrorInfo(Tr::tr("Referenced directory '%1' does not contain a qbs file.") .arg(absReferencePath), item->property(QLatin1String("references"))->location()); } absReferencePath = qbsFilePath; } if (referencedFilePaths.contains(absReferencePath)) throw ErrorInfo(Tr::tr("Cycle detected while referencing file '%1'.").arg(filePath), item->property(QLatin1String("references"))->location()); Item *subItem = m_reader->readFile(absReferencePath); subItem->setScope(projectContext.scope); subItem->setParent(projectContext.item); additionalProjectChildren << qMakePair(subItem, absReferencePath); if (subItem->typeName() == QLatin1String("Product")) { foreach (Item * const additionalProductItem, multiplexProductItem(&dummyProductContext, subItem)) { additionalProjectChildren << qMakePair(additionalProductItem, absReferencePath); } } } foreach (const ItemAndRefPath &irp, additionalProjectChildren) { Item * const subItem = irp.first; Item::addChild(projectContext.item, subItem); if (subItem->typeName() == QLatin1String("Product")) { prepareProduct(&projectContext, subItem); } else if (subItem->typeName() == QLatin1String("Project")) { copyProperties(item, subItem); handleProject(loadResult, topLevelProjectContext, subItem, buildDirectory, QSet(referencedFilePaths) << irp.second); } else { throw ErrorInfo(Tr::tr("The top-level item of a file in a \"references\" list must be " "a Product or a Project, but it is \"%1\".").arg(subItem->typeName()), subItem->location()); } } m_reader->popExtraSearchPaths(); } QList ModuleLoader::multiplexProductItem(ProductContext *dummyContext, Item *productItem) { // Temporarily attach the qbs module here, in case we need to access one of its properties // to evaluate the profiles property. const QString qbsKey = QLatin1String("qbs"); ValuePtr qbsValue = productItem->property(qbsKey); // Retrieve now to restore later. if (qbsValue) qbsValue = qbsValue->clone(); loadBaseModule(dummyContext, productItem); // Overriding the product item properties must be done here already, because otherwise // the "profiles" property would not be overridable. QString productName = m_evaluator->stringValue(productItem, QLatin1String("name")); if (productName.isEmpty()) { productName = FileInfo::completeBaseName(productItem->file()->filePath()); productItem->setProperty(QLatin1String("name"), VariantValue::create(productName)); } overrideItemProperties(productItem, productName, m_parameters.overriddenValuesTree()); const QString profilesKey = QLatin1String("profiles"); const ValueConstPtr profilesValue = productItem->property(profilesKey); QBS_CHECK(profilesValue); // Default value set in BuiltinDeclarations. const QStringList profileNames = m_evaluator->stringListValue(productItem, profilesKey); if (profileNames.isEmpty()) { throw ErrorInfo(Tr::tr("The 'profiles' property cannot be an empty list."), profilesValue->location()); } foreach (const QString &profileName, profileNames) { if (profileNames.count(profileName) > 1) { throw ErrorInfo(Tr::tr("The profile '%1' appears in the 'profiles' list twice, " "which is not allowed.").arg(profileName), profilesValue->location()); } } // "Unload" the qbs module again. if (qbsValue) productItem->setProperty(qbsKey, qbsValue); else productItem->removeProperty(qbsKey); productItem->removeModules(); m_validItemPropertyNamesPerItem[productItem].clear(); QList additionalProductItems; const QString profileKey = QLatin1String("profile"); productItem->setProperty(profileKey, VariantValue::create(profileNames.first())); Settings settings(m_parameters.settingsDirectory()); for (int i = 0; i < profileNames.count(); ++i) { Profile profile(profileNames.at(i), &settings); if (!profile.exists()) { throw ErrorInfo(Tr::tr("The profile '%1' does not exist.").arg(profile.name()), productItem->location()); // TODO: profilesValue->location() is invalid, why? } if (i == 0) continue; // We use the original item for the first profile. Item * const cloned = productItem->clone(); cloned->setProperty(profileKey, VariantValue::create(profileNames.at(i))); additionalProductItems << cloned; } return additionalProductItems; } void ModuleLoader::prepareProduct(ProjectContext *projectContext, Item *item) { checkCancelation(); if (m_logger.traceEnabled()) m_logger.qbsTrace() << "[MODLDR] prepareProduct " << item->file()->filePath(); initProductProperties(projectContext, item); ProductContext productContext; productContext.name = m_evaluator->stringValue(item, QLatin1String("name")); QBS_CHECK(!productContext.name.isEmpty()); bool profilePropertySet; productContext.profileName = m_evaluator->stringValue(item, QLatin1String("profile"), QString(), &profilePropertySet); QBS_CHECK(profilePropertySet); const QVariantMap::ConstIterator it = projectContext->result->profileConfigs.find(productContext.profileName); if (it == projectContext->result->profileConfigs.constEnd()) { const QVariantMap buildConfig = SetupProjectParameters::expandedBuildConfiguration( m_parameters.settingsDirectory(), productContext.profileName, m_parameters.buildVariant()); productContext.moduleProperties = SetupProjectParameters::finalBuildConfigurationTree( buildConfig, m_parameters.overriddenValues(), m_parameters.buildRoot(), m_parameters.topLevelProfile()); projectContext->result->profileConfigs.insert(productContext.profileName, productContext.moduleProperties); } else { productContext.moduleProperties = it.value().toMap(); } productContext.item = item; productContext.project = projectContext; QVector exportItems; foreach (Item *child, item->children()) { if (child->typeName() == QLatin1String("Export")) exportItems << child; } Item *mergedExportItem = mergeExportItems(&productContext, exportItems); ProductModuleInfo &pmi = projectContext->topLevelProject->productModules[productContext.name]; pmi.exportItem = mergedExportItem; ItemValuePtr itemValue = ItemValue::create(item); productContext.scope = Item::create(m_pool); productContext.scope->setProperty(QLatin1String("product"), itemValue); productContext.scope->setFile(item->file()); productContext.scope->setScope(productContext.project->scope); setScopeForDescendants(item, productContext.scope); projectContext->products << productContext; } void ModuleLoader::handleProduct(ProductContext *productContext) { checkCancelation(); Item *item = productContext->item; if (m_logger.traceEnabled()) m_logger.qbsTrace() << "[MODLDR] handleProduct " << item->file()->filePath(); QStringList extraSearchPaths = readExtraSearchPaths(item); Settings settings(m_parameters.settingsDirectory()); const QStringList prefsSearchPaths = Preferences(&settings, productContext->profileName).searchPaths(); foreach (const QString &p, prefsSearchPaths) { if (!m_moduleSearchPaths.contains(p) && FileInfo(p).exists()) extraSearchPaths << p; } m_reader->pushExtraSearchPaths(extraSearchPaths); DependsContext dependsContext; dependsContext.product = productContext; dependsContext.productDependencies = &productContext->info.usedProducts; resolveDependencies(&dependsContext, item); addTransitiveDependencies(productContext, productContext->item); copyGroupsFromModulesToProduct(*productContext); checkItemCondition(item); foreach (Item *child, item->children()) { if (child->typeName() == QLatin1String("Group")) handleGroup(productContext, child); else if (child->typeName() == QLatin1String("Probe")) resolveProbe(item, child); } productContext->project->result->productInfos.insert(item, productContext->info); m_reader->popExtraSearchPaths(); } void ModuleLoader::initProductProperties(const ProjectContext *project, Item *item) { const QString productName = m_evaluator->stringValue(item, QLatin1String("name")); const QString profile = m_evaluator->stringValue(item, QLatin1String("profile")); QBS_CHECK(!profile.isEmpty()); const QString buildDir = ResolvedProduct::deriveBuildDirectoryName(productName, profile); item->setProperty(QLatin1String("buildDirectory"), VariantValue::create( FileInfo::resolvePath(project->buildDirectory, buildDir))); item->setProperty(QLatin1String("sourceDirectory"), VariantValue::create( QFileInfo(item->file()->filePath()).absolutePath())); } void ModuleLoader::handleSubProject(ModuleLoader::ProjectContext *projectContext, Item *item, const QSet &referencedFilePaths) { if (m_logger.traceEnabled()) m_logger.qbsTrace() << "[MODLDR] handleSubProject " << item->file()->filePath(); Item * const propertiesItem = item->child(QLatin1String("Properties")); bool subProjectEnabled = true; if (propertiesItem) subProjectEnabled = checkItemCondition(propertiesItem); if (!subProjectEnabled) return; const QString projectFileDirPath = FileInfo::path(item->file()->filePath()); const QString relativeFilePath = m_evaluator->stringValue(item, QLatin1String("filePath")); QString subProjectFilePath = FileInfo::resolvePath(projectFileDirPath, relativeFilePath); if (referencedFilePaths.contains(subProjectFilePath)) throw ErrorInfo(Tr::tr("Cycle detected while loading subproject file '%1'.") .arg(relativeFilePath), item->location()); Item *loadedItem = m_reader->readFile(subProjectFilePath); if (loadedItem->typeName() == QLatin1String("Product")) loadedItem = wrapWithProject(loadedItem); const bool inheritProperties = m_evaluator->boolValue(item, QLatin1String("inheritProperties"), true); if (inheritProperties) copyProperties(item->parent(), loadedItem); if (propertiesItem) { const Item::PropertyMap &overriddenProperties = propertiesItem->properties(); for (Item::PropertyMap::ConstIterator it = overriddenProperties.constBegin(); it != overriddenProperties.constEnd(); ++it) { loadedItem->setProperty(it.key(), overriddenProperties.value(it.key())); } } if (loadedItem->typeName() != QLatin1String("Project")) { ErrorInfo error; error.append(Tr::tr("Expected Project item, but encountered '%1'.") .arg(loadedItem->typeName()), loadedItem->location()); const ValuePtr &filePathProperty = item->properties().value(QLatin1String("filePath")); error.append(Tr::tr("The problematic file was referenced from here."), filePathProperty->location()); throw error; } Item::addChild(item, loadedItem); item->setScope(projectContext->scope); handleProject(projectContext->result, projectContext->topLevelProject, loadedItem, projectContext->buildDirectory, QSet(referencedFilePaths) << subProjectFilePath); } void ModuleLoader::handleGroup(ProductContext *productContext, Item *item) { checkCancelation(); propagateModulesFromProduct(productContext, item); checkItemCondition(item); } static void mergeProperty(Item *dst, const QString &name, const ValuePtr &value) { if (value->type() == Value::ItemValueType) { Item *valueItem = value.staticCast()->item(); if (!valueItem) return; Item *subItem = dst->itemProperty(name, true)->item(); for (QMap::const_iterator it = valueItem->properties().constBegin(); it != valueItem->properties().constEnd(); ++it) mergeProperty(subItem, it.key(), it.value()); } else { dst->setProperty(name, value); } } Item *ModuleLoader::mergeExportItems(ModuleLoader::ProductContext *productContext, const QVector &exportItemsInProduct) { Item *merged = Item::create(productContext->item->pool()); merged->setTypeName(QLatin1String("Export")); merged->setFile(productContext->item->file()); merged->setLocation(productContext->item->location()); QSet exportItems; foreach (Item *exportItem, exportItemsInProduct) { checkCancelation(); if (Q_UNLIKELY(productContext->filesWithExportItem.contains(exportItem->file()))) throw ErrorInfo(Tr::tr("Multiple Export items in one product are prohibited."), exportItem->location()); merged->setFile(exportItem->file()); merged->setLocation(exportItem->location()); productContext->filesWithExportItem += exportItem->file(); exportItems.insert(exportItem); foreach (Item *child, exportItem->children()) Item::addChild(merged, child); for (QMap::const_iterator it = exportItem->properties().constBegin(); it != exportItem->properties().constEnd(); ++it) { mergeProperty(merged, it.key(), it.value()); } } QList children = productContext->item->children(); for (int i = 0; i < children.count();) { if (exportItems.contains(children.at(i))) children.removeAt(i); else ++i; } productContext->item->setChildren(children); Item::addChild(productContext->item, merged); merged->setupForBuiltinType(m_logger); return merged; } void ModuleLoader::propagateModulesFromProduct(ProductContext *productContext, Item *item) { for (Item::Modules::const_iterator it = productContext->item->modules().constBegin(); it != productContext->item->modules().constEnd(); ++it) { Item::Module m = *it; Item *targetItem = moduleInstanceItem(item, m.name); targetItem->setPrototype(m.item); targetItem->setModuleInstanceFlag(true); targetItem->setScope(m.item->scope()); targetItem->setModules(m.item->modules()); // "parent" should point to the group/artifact parent targetItem->setParent(item->parent()); // the outer item of a module is the product's instance of it targetItem->setOuterItem(m.item); // ### Is this always the same as the scope item? m.item = targetItem; item->addModule(m); } } void ModuleLoader::resolveDependencies(DependsContext *dependsContext, Item *item) { loadBaseModule(dependsContext->product, item); // Resolve all Depends items. ItemModuleList loadedModules; ProductDependencyResults productDependencies; foreach (Item *child, item->children()) if (child->typeName() == QLatin1String("Depends")) resolveDependsItem(dependsContext, item, child, &loadedModules, &productDependencies); QSet loadedModuleNames; foreach (const Item::Module &module, loadedModules) { const QString fullName = module.name.toString(); if (loadedModuleNames.contains(fullName)) continue; loadedModuleNames.insert(fullName); item->addModule(module); } dependsContext->productDependencies->append(productDependencies); } void ModuleLoader::resolveDependsItem(DependsContext *dependsContext, Item *item, Item *dependsItem, ItemModuleList *moduleResults, ProductDependencyResults *productResults) { checkCancelation(); if (!checkItemCondition(dependsItem)) { if (m_logger.traceEnabled()) m_logger.qbsTrace() << "Depends item disabled, ignoring."; return; } bool productTypesIsSet; const QStringList productTypes = m_evaluator->stringListValue(dependsItem, QLatin1String("productTypes"), &productTypesIsSet); bool nameIsSet; const QString name = m_evaluator->stringValue(dependsItem, QLatin1String("name"), QString(), &nameIsSet); bool submodulesPropertySet; QStringList submodules = m_evaluator->stringListValue(dependsItem, QLatin1String("submodules"), &submodulesPropertySet); if (productTypesIsSet) { if (nameIsSet) { throw ErrorInfo(Tr::tr("The 'productTypes' and 'name' properties are mutually " "exclusive."), dependsItem->location()); } if (submodulesPropertySet) { throw ErrorInfo(Tr::tr("The 'productTypes' and 'subModules' properties are mutually " "exclusive."), dependsItem->location()); } if (productTypes.isEmpty()) { m_logger.qbsTrace() << "Ignoring Depends item with empty productTypes list."; return; } // TODO: We could also filter by the "profiles" property. This would required a refactoring // (Dependency needs a list of profiles and the multiplexing must happen later). ModuleLoaderResult::ProductInfo::Dependency dependency; dependency.productTypes = productTypes; dependency.limitToSubProject = m_evaluator->boolValue(dependsItem, QLatin1String("limitToSubProject")); productResults->append(dependency); return; } if (submodules.isEmpty() && submodulesPropertySet) { m_logger.qbsTrace() << "Ignoring Depends item with empty submodules list."; return; } if (Q_UNLIKELY(submodules.count() > 1 && !dependsItem->id().isEmpty())) { QString msg = Tr::tr("A Depends item with more than one module cannot have an id."); throw ErrorInfo(msg, dependsItem->location()); } QList moduleNames; const QualifiedId nameParts = QualifiedId::fromString(name); if (submodules.isEmpty()) { moduleNames << nameParts; } else { foreach (const QString &submodule, submodules) moduleNames << nameParts + QualifiedId::fromString(submodule); } Item::Module result; foreach (const QualifiedId &moduleName, moduleNames) { const bool isRequired = m_evaluator->boolValue(dependsItem, QLatin1String("required")); Item *moduleItem = loadModule(dependsContext->product, item, dependsItem->location(), dependsItem->id(), moduleName, false, isRequired, &result.isProduct); if (!moduleItem) { // ### 1.5: change error message to the more generic "Dependency '%1' not found.". throw ErrorInfo(Tr::tr("Product dependency '%1' not found.").arg(moduleName.toString()), dependsItem->location()); } if (m_logger.traceEnabled()) m_logger.qbsTrace() << "module loaded: " << moduleName.toString(); result.name = moduleName; result.item = moduleItem; result.required = isRequired; moduleResults->append(result); if (result.isProduct) { if (m_logger.traceEnabled()) m_logger.qbsTrace() << "product dependency loaded: " << moduleName.toString(); const QString profilesKey = QLatin1String("profiles"); const QStringList profiles = m_evaluator->stringListValue(dependsItem, profilesKey); if (profiles.isEmpty()) { ModuleLoaderResult::ProductInfo::Dependency dependency; dependency.name = moduleName.toString(); dependency.profile = QLatin1String("*"); productResults->append(dependency); continue; } foreach (const QString &profile, profiles) { ModuleLoaderResult::ProductInfo::Dependency dependency; dependency.name = moduleName.toString(); dependency.profile = profile; productResults->append(dependency); } } } } Item *ModuleLoader::moduleInstanceItem(Item *item, const QualifiedId &moduleName) { Item *instance = item; for (int i = 0; i < moduleName.count(); ++i) { const QString &moduleNameSegment = moduleName.at(i); m_validItemPropertyNamesPerItem[instance].insert(moduleNameSegment); bool createNewItem = true; const ValuePtr v = instance->properties().value(moduleName.at(i)); if (v && v->type() == Value::ItemValueType) { const ItemValuePtr iv = v.staticCast(); if (iv->item()) { createNewItem = false; instance = iv->item(); } } if (createNewItem) { Item *newItem = Item::create(m_pool); instance->setProperty(moduleNameSegment, ItemValue::create(newItem)); instance = newItem; } } QBS_ASSERT(moduleName.isEmpty() || instance != item, return 0); return instance; } Item *ModuleLoader::loadProductModule(ModuleLoader::ProductContext *productContext, const QString &moduleName) { if (m_logger.traceEnabled()) m_logger.qbsTrace() << "[MODLDR] loadProductModule name: " << moduleName; Item *module = m_productModuleCache.value(moduleName); if (module) { if (m_logger.traceEnabled()) m_logger.qbsTrace() << "[MODLDR] loadProductModule cache hit."; return module; } ProductModuleInfo &pmi = productContext->project->topLevelProject->productModules[moduleName]; module = pmi.exportItem; if (module) { if (m_logger.traceEnabled()) m_logger.qbsTrace() << "[MODLDR] loadProductModule cache miss."; DependsContext dependsContext; dependsContext.product = productContext; dependsContext.productDependencies = &pmi.productDependencies; resolveDependencies(&dependsContext, module); m_productModuleCache.insert(moduleName, module); } return module; } Item *ModuleLoader::loadModule(ProductContext *productContext, Item *item, const CodeLocation &dependsItemLocation, const QString &moduleId, const QualifiedId &moduleName, bool isBaseModule, bool isRequired, bool *isProductDependency) { if (m_logger.traceEnabled()) m_logger.qbsTrace() << "[MODLDR] loadModule name: " << moduleName << ", id: " << moduleId; Item *moduleInstance = moduleId.isEmpty() ? moduleInstanceItem(item, moduleName) : moduleInstanceItem(item, QStringList(moduleId)); if (!moduleInstance->typeName().isNull()) { // already handled return moduleInstance; } *isProductDependency = true; Item *modulePrototype = loadProductModule(productContext, moduleName.toString()); if (!modulePrototype) { *isProductDependency = false; QStringList moduleSearchPaths; foreach (const QString &searchPath, m_reader->searchPaths()) addExtraModuleSearchPath(moduleSearchPaths, searchPath); bool cacheHit; modulePrototype = searchAndLoadModuleFile(productContext, dependsItemLocation, moduleName, moduleSearchPaths, isRequired, &cacheHit); if (isBaseModule && modulePrototype && !cacheHit) setupBaseModulePrototype(modulePrototype); } if (!modulePrototype) return 0; instantiateModule(productContext, nullptr, item, moduleInstance, modulePrototype, moduleName, *isProductDependency); if (moduleInstance->isPresentModule()) { resolveProbes(moduleInstance); try { m_evaluator->boolValue(moduleInstance, QLatin1String("validate")); } catch (const ErrorInfo &error) { if (isRequired) { // Error will be thrown for enabled products only moduleInstance->setDelayedError(error); } else { return createNonPresentModule(moduleName.toString(), QLatin1String("failed validation"), moduleInstance); } } } return moduleInstance; } Item *ModuleLoader::searchAndLoadModuleFile(ProductContext *productContext, const CodeLocation &dependsItemLocation, const QualifiedId &moduleName, const QStringList &extraSearchPaths, bool isRequired, bool *cacheHit) { QStringList searchPaths = extraSearchPaths; searchPaths.append(m_moduleSearchPaths); bool triedToLoadModule = false; const QString fullName = moduleName.toString(); foreach (const QString &path, searchPaths) { const QString dirPath = findExistingModulePath(path, moduleName); if (dirPath.isEmpty()) continue; QStringList moduleFileNames = m_moduleDirListCache.value(dirPath); if (moduleFileNames.isEmpty()) { QDirIterator dirIter(dirPath, QStringList(QLatin1String("*.qbs"))); while (dirIter.hasNext()) moduleFileNames += dirIter.next(); m_moduleDirListCache.insert(dirPath, moduleFileNames); } foreach (const QString &filePath, moduleFileNames) { triedToLoadModule = true; Item *module = loadModuleFile(productContext, fullName, moduleName.count() == 1 && moduleName.first() == QLatin1String("qbs"), filePath, cacheHit, &triedToLoadModule); if (module) return module; if (!triedToLoadModule) m_moduleDirListCache[dirPath].removeOne(filePath); } } if (!isRequired) return createNonPresentModule(fullName, QLatin1String("not found"), nullptr); if (Q_UNLIKELY(triedToLoadModule)) throw ErrorInfo(Tr::tr("Module %1 could not be loaded.").arg(fullName), dependsItemLocation); return 0; } // returns QVariant::Invalid for types that do not need conversion static QVariant::Type variantType(PropertyDeclaration::Type t) { switch (t) { case PropertyDeclaration::UnknownType: break; case PropertyDeclaration::Boolean: return QVariant::Bool; case PropertyDeclaration::Integer: return QVariant::Int; case PropertyDeclaration::Path: return QVariant::String; case PropertyDeclaration::PathList: return QVariant::StringList; case PropertyDeclaration::String: return QVariant::String; case PropertyDeclaration::StringList: return QVariant::StringList; case PropertyDeclaration::Variant: break; case PropertyDeclaration::Verbatim: return QVariant::String; } return QVariant::Invalid; } static QVariant convertToPropertyType(const QVariant &v, PropertyDeclaration::Type t, const QStringList &namePrefix, const QString &key) { if (v.isNull() || !v.isValid()) return v; const QVariant::Type vt = variantType(t); if (vt == QVariant::Invalid) return v; // Handle the foo,bar,bla stringlist syntax. if (t == PropertyDeclaration::StringList && v.type() == QVariant::String) return v.toString().split(QLatin1Char(',')); QVariant c = v; if (!c.convert(vt)) { QStringList name = namePrefix; name << key; throw ErrorInfo(Tr::tr("Value '%1' of property '%2' has incompatible type.") .arg(v.toString(), name.join(QLatin1Char('.')))); } return c; } Item *ModuleLoader::loadModuleFile(ProductContext *productContext, const QString &fullModuleName, bool isBaseModule, const QString &filePath, bool *cacheHit, bool *triedToLoad) { checkCancelation(); if (m_logger.traceEnabled()) m_logger.qbsTrace() << "[MODLDR] trying to load " << fullModuleName << " from " << filePath; const ModuleItemCache::key_type cacheKey(filePath, productContext->profileName); const ItemCacheValue cacheValue = m_modulePrototypeItemCache.value(cacheKey); if (cacheValue.module) { m_logger.qbsTrace() << "[LDR] loadModuleFile cache hit for " << filePath; *cacheHit = true; return cacheValue.enabled ? cacheValue.module : 0; } *cacheHit = false; Item * const module = m_reader->readFile(filePath); if (module->typeName() != QLatin1String("Module")) { if (m_logger.traceEnabled()) { m_logger.qbsTrace() << "[MODLDR] Alleged module " << fullModuleName << " has type '" << module->typeName() << "', so it's not a module after all."; } *triedToLoad = false; return 0; } if (!isBaseModule) { DependsContext dependsContext; dependsContext.product = productContext; dependsContext.productDependencies = &productContext->info.usedProducts; resolveDependencies(&dependsContext, module); } // Module properties that are defined in the profile are used as default values. const QVariantMap profileModuleProperties = productContext->moduleProperties.value(fullModuleName).toMap(); QList unknownProfilePropertyErrors; for (QVariantMap::const_iterator vmit = profileModuleProperties.begin(); vmit != profileModuleProperties.end(); ++vmit) { if (Q_UNLIKELY(!module->hasProperty(vmit.key()))) { const ErrorInfo error(Tr::tr("Unknown property: %1.%2").arg(fullModuleName, vmit.key())); unknownProfilePropertyErrors.append(error); continue; } const PropertyDeclaration decl = module->propertyDeclaration(vmit.key()); VariantValuePtr v = VariantValue::create(convertToPropertyType(vmit.value(), decl.type(), QStringList(fullModuleName), vmit.key())); module->setProperty(vmit.key(), v); } // Check the condition last in case the condition needs to evaluate other properties that were // set by the profile if (!checkItemCondition(module)) { m_logger.qbsTrace() << "[LDR] module condition is false"; m_modulePrototypeItemCache.insert(cacheKey, ItemCacheValue(module, false)); return 0; } foreach (const ErrorInfo &error, unknownProfilePropertyErrors) handlePropertyError(error, m_parameters, m_logger); module->setProperty(QLatin1String("name"), VariantValue::create(fullModuleName)); m_modulePrototypeItemCache.insert(cacheKey, ItemCacheValue(module, true)); return module; } void ModuleLoader::loadBaseModule(ProductContext *productContext, Item *item) { const QualifiedId baseModuleName(QLatin1String("qbs")); Item::Module baseModuleDesc; baseModuleDesc.name = baseModuleName; baseModuleDesc.item = loadModule(productContext, item, CodeLocation(), QString(), baseModuleName, true, true, &baseModuleDesc.isProduct); QBS_CHECK(!baseModuleDesc.isProduct); if (Q_UNLIKELY(!baseModuleDesc.item)) throw ErrorInfo(Tr::tr("Cannot load base qbs module.")); item->addModule(baseModuleDesc); } static QStringList hostOS() { QStringList hostSystem; #if defined(Q_OS_AIX) hostSystem << QLatin1String("aix"); #endif #if defined(Q_OS_ANDROID) hostSystem << QLatin1String("android"); #endif #if defined(Q_OS_BLACKBERRY) hostSystem << QLatin1String("blackberry"); #endif #if defined(Q_OS_BSD4) hostSystem << QLatin1String("bsd") << QLatin1String("bsd4"); #endif #if defined(Q_OS_BSDI) hostSystem << QLatin1String("bsdi"); #endif #if defined(Q_OS_CYGWIN) hostSystem << QLatin1String("cygwin"); #endif #if defined(Q_OS_DARWIN) hostSystem << QLatin1String("darwin"); #endif #if defined(Q_OS_DGUX) hostSystem << QLatin1String("dgux"); #endif #if defined(Q_OS_DYNIX) hostSystem << QLatin1String("dynix"); #endif #if defined(Q_OS_FREEBSD) hostSystem << QLatin1String("freebsd"); #endif #if defined(Q_OS_HPUX) hostSystem << QLatin1String("hpux"); #endif #if defined(Q_OS_HURD) hostSystem << QLatin1String("hurd"); #endif #if defined(Q_OS_INTEGRITY) hostSystem << QLatin1String("integrity"); #endif #if defined(Q_OS_IOS) hostSystem << QLatin1String("ios"); #endif #if defined(Q_OS_IRIX) hostSystem << QLatin1String("irix"); #endif #if defined(Q_OS_LINUX) hostSystem << QLatin1String("linux"); #endif #if defined(Q_OS_LYNX) hostSystem << QLatin1String("lynx"); #endif #if defined(Q_OS_OSX) hostSystem << QLatin1String("osx"); #endif #if defined(Q_OS_MSDOS) hostSystem << QLatin1String("msdos"); #endif #if defined(Q_OS_NACL) hostSystem << QLatin1String("nacl"); #endif #if defined(Q_OS_NETBSD) hostSystem << QLatin1String("netbsd"); #endif #if defined(Q_OS_OPENBSD) hostSystem << QLatin1String("openbsd"); #endif #if defined(Q_OS_OS2) hostSystem << QLatin1String("os2"); #endif #if defined(Q_OS_OS2EMX) hostSystem << QLatin1String("os2emx"); #endif #if defined(Q_OS_OSF) hostSystem << QLatin1String("osf"); #endif #if defined(Q_OS_QNX) hostSystem << QLatin1String("qnx"); #endif #if defined(Q_OS_ONX6) hostSystem << QLatin1String("qnx6"); #endif #if defined(Q_OS_RELIANT) hostSystem << QLatin1String("reliant"); #endif #if defined(Q_OS_SCO) hostSystem << QLatin1String("sco"); #endif #if defined(Q_OS_SOLARIS) hostSystem << QLatin1String("solaris"); #endif #if defined(Q_OS_SYMBIAN) hostSystem << QLatin1String("symbian"); #endif #if defined(Q_OS_ULTRIX) hostSystem << QLatin1String("ultrix"); #endif #if defined(Q_OS_UNIX) hostSystem << QLatin1String("unix"); #endif #if defined(Q_OS_UNIXWARE) hostSystem << QLatin1String("unixware"); #endif #if defined(Q_OS_VXWORKS) hostSystem << QLatin1String("vxworks"); #endif #if defined(Q_OS_WIN32) hostSystem << QLatin1String("windows"); #endif #if defined(Q_OS_WINCE) hostSystem << QLatin1String("windowsce"); #endif #if defined(Q_OS_WINPHONE) hostSystem << QLatin1String("windowsphone"); #endif #if defined(Q_OS_WINRT) hostSystem << QLatin1String("winrt"); #endif return hostSystem; } void ModuleLoader::setupBaseModulePrototype(Item *prototype) { prototype->setProperty(QLatin1String("getNativeSetting"), BuiltinValue::create(BuiltinValue::GetNativeSettingFunction)); prototype->setProperty(QLatin1String("getEnv"), BuiltinValue::create(BuiltinValue::GetEnvFunction)); prototype->setProperty(QLatin1String("currentEnv"), BuiltinValue::create(BuiltinValue::CurrentEnvFunction)); prototype->setProperty(QLatin1String("hostOS"), VariantValue::create(hostOS())); prototype->setProperty(QLatin1String("canonicalArchitecture"), BuiltinValue::create(BuiltinValue::CanonicalArchitectureFunction)); prototype->setProperty(QLatin1String("rfc1034Identifier"), BuiltinValue::create(BuiltinValue::Rfc1034IdentifierFunction)); prototype->setProperty(QLatin1String("libexecPath"), VariantValue::create(m_parameters.libexecPath())); const Version qbsVersion = Version::qbsVersion(); prototype->setProperty(QLatin1String("versionMajor"), VariantValue::create(qbsVersion.majorVersion())); prototype->setProperty(QLatin1String("versionMinor"), VariantValue::create(qbsVersion.minorVersion())); prototype->setProperty(QLatin1String("versionPatch"), VariantValue::create(qbsVersion.patchLevel())); } static void collectItemsWithId_impl(Item *item, QList *result) { if (!item->id().isEmpty()) result->append(item); foreach (Item *child, item->children()) collectItemsWithId_impl(child, result); } static QList collectItemsWithId(Item *item) { QList result; collectItemsWithId_impl(item, &result); return result; } static Item *productOf(Item *item) { do { item = item->parent(); } while (item && item->typeName() != QLatin1String("Product")); return item; } static void copyNonOverriddenProperties(const Item *src, Item *dst) { const Item::PropertyMap &srcProps = src->properties(); for (auto it = srcProps.constBegin(); it != srcProps.constEnd(); ++it) { if (it.value()->type() != Value::JSSourceValueType || dst->hasOwnProperty(it.key())) continue; dst->setProperty(it.key(), it.value()); } } void ModuleLoader::instantiateModule(ProductContext *productContext, Item *exportingProduct, Item *instanceScope, Item *moduleInstance, Item *modulePrototype, const QualifiedId &moduleName, bool isProduct) { const QString fullName = moduleName.toString(); moduleInstance->setPrototype(modulePrototype); moduleInstance->setFile(modulePrototype->file()); moduleInstance->setLocation(modulePrototype->location()); moduleInstance->setTypeName(modulePrototype->typeName()); // create module scope Item *moduleScope = Item::create(m_pool); QBS_CHECK(instanceScope->file()); moduleScope->setFile(instanceScope->file()); moduleScope->setScope(instanceScope); productContext->project->scope->copyProperty(QLatin1String("project"), moduleScope); productContext->scope->copyProperty(QLatin1String("product"), moduleScope); if (isProduct) { exportingProduct = 0; for (Item *exportItem = modulePrototype; exportItem; exportItem = exportItem->prototype()) { exportingProduct = productOf(exportItem); if (exportingProduct) break; } QBS_CHECK(exportingProduct); } if (exportingProduct) { if (!isProduct) { copyNonOverriddenProperties(modulePrototype, moduleInstance); moduleInstance->setPrototype(modulePrototype->prototype()); } Item *exportScope = Item::create(moduleInstance->pool()); exportScope->setFile(instanceScope->file()); exportScope->setScope(instanceScope); exportScope->setProperty(QLatin1String("product"), ItemValue::create(exportingProduct)); exportScope->setProperty(QLatin1String("project"), ItemValue::create(exportingProduct->parent())); for (auto it = moduleInstance->properties().begin(); it != moduleInstance->properties().end(); ++it) { if (it.value()->type() != Value::JSSourceValueType) continue; const JSSourceValuePtr v = it.value().staticCast(); v->setExportScope(exportScope); } PropertyDeclaration pd(QLatin1String("_qbs_sourceDir"), PropertyDeclaration::String, PropertyDeclaration::PropertyNotAvailableInConfig); moduleInstance->setPropertyDeclaration(pd.name(), pd); ValuePtr v = exportingProduct->property(QLatin1String("sourceDirectory"))->clone(); moduleInstance->setProperty(pd.name(), v); } moduleInstance->setScope(moduleScope); moduleInstance->setModuleInstanceFlag(true); QHash prototypeInstanceMap; prototypeInstanceMap[modulePrototype] = moduleInstance; // create instances for every child of the prototype createChildInstances(productContext, moduleInstance, modulePrototype, &prototypeInstanceMap); // create ids from from the prototype in the instance if (modulePrototype->file()->idScope()) { foreach (Item *itemWithId, collectItemsWithId(modulePrototype)) { Item *idProto = itemWithId; Item *idInstance = prototypeInstanceMap.value(idProto); QBS_ASSERT(idInstance, continue); ItemValuePtr idInstanceValue = ItemValue::create(idInstance); moduleScope->setProperty(itemWithId->id(), idInstanceValue); } } // create module instances for the dependencies of this module foreach (Item::Module m, modulePrototype->modules()) { Item *depinst = moduleInstanceItem(moduleInstance, m.name); const bool safetyCheck = true; if (safetyCheck) { Item *obj = moduleInstance; for (int i = 0; i < m.name.count(); ++i) { ItemValuePtr iv = obj->itemProperty(m.name.at(i)); QBS_CHECK(iv); obj = iv->item(); QBS_CHECK(obj); } QBS_CHECK(obj == depinst); } QBS_ASSERT(depinst != m.item, continue); instantiateModule(productContext, isProduct ? exportingProduct : nullptr, moduleInstance, depinst, m.item, m.name, m.isProduct); m.item = depinst; moduleInstance->addModule(m); } // override module properties given on the command line const QVariantMap userModuleProperties = m_parameters.overriddenValuesTree().value(fullName).toMap(); for (QVariantMap::const_iterator vmit = userModuleProperties.begin(); vmit != userModuleProperties.end(); ++vmit) { if (Q_UNLIKELY(!moduleInstance->hasProperty(vmit.key()))) { const ErrorInfo error(Tr::tr("Unknown property: %1.%2") .arg(moduleName.toString(), vmit.key())); handlePropertyError(error, m_parameters, m_logger); continue; } const PropertyDeclaration decl = moduleInstance->propertyDeclaration(vmit.key()); moduleInstance->setProperty(vmit.key(), VariantValue::create(convertToPropertyType(vmit.value(), decl.type(), moduleName, vmit.key()))); } } void ModuleLoader::createChildInstances(ProductContext *productContext, Item *instance, Item *prototype, QHash *prototypeInstanceMap) const { foreach (Item *childPrototype, prototype->children()) { Item *childInstance = Item::create(m_pool); prototypeInstanceMap->insert(childPrototype, childInstance); childInstance->setPrototype(childPrototype); childInstance->setTypeName(childPrototype->typeName()); childInstance->setFile(childPrototype->file()); childInstance->setLocation(childPrototype->location()); childInstance->setScope(productContext->scope); Item::addChild(instance, childInstance); createChildInstances(productContext, childInstance, childPrototype, prototypeInstanceMap); } } void ModuleLoader::resolveProbes(Item *item) { foreach (Item *child, item->children()) if (child->typeName() == QLatin1String("Probe")) resolveProbe(item, child); } void ModuleLoader::resolveProbe(Item *parent, Item *probe) { const JSSourceValueConstPtr configureScript = probe->sourceProperty(QLatin1String("configure")); if (Q_UNLIKELY(!configureScript)) throw ErrorInfo(Tr::tr("Probe.configure must be set."), probe->location()); typedef QPair ProbeProperty; QList probeBindings; for (Item *obj = probe; obj; obj = obj->prototype()) { foreach (const QString &name, obj->properties().keys()) { if (name == QLatin1String("configure")) continue; probeBindings += ProbeProperty(name, m_evaluator->value(probe, name)); } } QScriptValue scope = m_engine->newObject(); m_engine->currentContext()->pushScope(m_evaluator->scriptValue(parent)); m_engine->currentContext()->pushScope(m_evaluator->fileScope(configureScript->file())); m_engine->currentContext()->pushScope(scope); foreach (const ProbeProperty &b, probeBindings) scope.setProperty(b.first, b.second); QScriptValue sv = m_engine->evaluate(configureScript->sourceCodeForEvaluation()); if (Q_UNLIKELY(m_engine->hasErrorOrException(sv))) throw ErrorInfo(m_engine->lastErrorString(sv), configureScript->location()); foreach (const ProbeProperty &b, probeBindings) { const QVariant newValue = scope.property(b.first).toVariant(); if (newValue != b.second.toVariant()) probe->setProperty(b.first, VariantValue::create(newValue)); } m_engine->currentContext()->popScope(); m_engine->currentContext()->popScope(); m_engine->currentContext()->popScope(); } void ModuleLoader::checkCancelation() const { if (m_progressObserver && m_progressObserver->canceled()) { throw ErrorInfo(Tr::tr("Project resolving canceled for configuration %1.") .arg(TopLevelProject::deriveId(m_parameters.topLevelProfile(), m_parameters.finalBuildConfigurationTree()))); } } bool ModuleLoader::checkItemCondition(Item *item) { if (m_evaluator->boolValue(item, QLatin1String("condition"), true)) return true; m_disabledItems += item; return false; } void ModuleLoader::checkItemTypes(Item *item) { if (Q_UNLIKELY(!item->typeName().isEmpty() && !BuiltinDeclarations::instance().containsType(item->typeName()))) { const QString msg = Tr::tr("Unexpected item type '%1'."); throw ErrorInfo(msg.arg(item->typeName()), item->location()); } const ItemDeclaration decl = BuiltinDeclarations::instance().declarationsForType(item->typeName()); foreach (Item *child, item->children()) { if (child->typeName().isEmpty()) continue; checkItemTypes(child); if (!decl.isChildTypeAllowed(child->typeName())) throw ErrorInfo(Tr::tr("Items of type '%1' cannot contain items of type '%2'.") .arg(item->typeName(), child->typeName()), item->location()); } foreach (const Item::Module &m, item->modules()) checkItemTypes(m.item); } QStringList ModuleLoader::readExtraSearchPaths(Item *item, bool *wasSet) { QStringList result; const QString propertyName = QLatin1String("qbsSearchPaths"); const QStringList paths = m_evaluator->stringListValue(item, propertyName, wasSet); const JSSourceValueConstPtr prop = item->sourceProperty(propertyName); // Value can come from within a project file or as an overridden value from the user // (e.g command line). const QString basePath = FileInfo::path(prop ? prop->file()->filePath() : m_parameters.projectFilePath()); foreach (const QString &path, paths) result += FileInfo::resolvePath(basePath, path); return result; } void ModuleLoader::copyProperties(const Item *sourceProject, Item *targetProject) { if (!sourceProject) return; const QList &builtinProjectProperties = BuiltinDeclarations::instance() .declarationsForType(QLatin1String("Project")).properties(); QSet builtinProjectPropertyNames; foreach (const PropertyDeclaration &p, builtinProjectProperties) builtinProjectPropertyNames << p.name(); for (Item::PropertyDeclarationMap::ConstIterator it = sourceProject->propertyDeclarations().constBegin(); it != sourceProject->propertyDeclarations().constEnd(); ++it) { // We must not inherit built-in properties such as "name", // but there are exceptions. if (it.key() == QLatin1String("qbsSearchPaths") || it.key() == QLatin1String("profile") || it.key() == QLatin1String("buildDirectory") || it.key() == QLatin1String("sourceDirectory")) { const JSSourceValueConstPtr &v = targetProject->property(it.key()).dynamicCast(); QBS_ASSERT(v, continue); if (v->sourceCode() == QLatin1String("undefined")) sourceProject->copyProperty(it.key(), targetProject); continue; } if (builtinProjectPropertyNames.contains(it.key())) continue; if (targetProject->properties().contains(it.key())) continue; // Ignore stuff the target project already has. targetProject->setPropertyDeclaration(it.key(), it.value()); sourceProject->copyProperty(it.key(), targetProject); } } Item *ModuleLoader::wrapWithProject(Item *item) { Item *prj = Item::create(item->pool()); prj->setChildren(QList() << item); item->setParent(prj); prj->setTypeName(QLatin1String("Project")); prj->setFile(item->file()); prj->setLocation(item->location()); prj->setupForBuiltinType(m_logger); return prj; } QString ModuleLoader::findExistingModulePath(const QString &searchPath, const QualifiedId &moduleName) { QString dirPath = searchPath; foreach (const QString &moduleNamePart, moduleName) { dirPath = FileInfo::resolvePath(dirPath, moduleNamePart); if (!FileInfo::exists(dirPath) || !FileInfo::isFileCaseCorrect(dirPath)) return QString(); } return dirPath; } void ModuleLoader::setScopeForDescendants(Item *item, Item *scope) { foreach (Item *child, item->children()) { child->setScope(scope); setScopeForDescendants(child, scope); } } void ModuleLoader::overrideItemProperties(Item *item, const QString &buildConfigKey, const QVariantMap &buildConfig) { const QVariant buildConfigValue = buildConfig.value(buildConfigKey); if (buildConfigValue.isNull()) return; const QVariantMap overridden = buildConfigValue.toMap(); for (QVariantMap::const_iterator it = overridden.constBegin(); it != overridden.constEnd(); ++it) { const PropertyDeclaration decl = item->propertyDeclarations().value(it.key()); if (!decl.isValid()) { ErrorInfo error(Tr::tr("Unknown property: %1.%2").arg(buildConfigKey, it.key())); handlePropertyError(error, m_parameters, m_logger); continue; } item->setProperty(it.key(), VariantValue::create(convertToPropertyType(it.value(), decl.type(), QStringList(buildConfigKey), it.key()))); } } static void collectAllModules(Item *item, QVector *modules) { foreach (const Item::Module &m, item->modules()) { auto it = std::find_if(modules->begin(), modules->end(), [m] (const Item::Module &m2) { return m.name == m2.name; }); if (it != modules->end()) { // If a module is required somewhere, it is required in the top-level item. if (m.required) it->required = true; continue; } modules->append(m); collectAllModules(m.item, modules); } } static QVector allModules(Item *item) { QVector lst; collectAllModules(item, &lst); return lst; } void ModuleLoader::addTransitiveDependencies(ProductContext *ctx, Item *item) { if (m_logger.traceEnabled()) m_logger.qbsTrace() << "[MODLDR] addTransitiveDependencies"; QVector transitiveDeps = allModules(item); std::sort(transitiveDeps.begin(), transitiveDeps.end()); foreach (const Item::Module &m, item->modules()) { if (m.isProduct) { ctx->info.usedProducts.append( ctx->project->topLevelProject->productModules.value( m.name.toString()).productDependencies); } auto it = std::lower_bound(transitiveDeps.begin(), transitiveDeps.end(), m); if (it != transitiveDeps.end() && it->name == m.name) transitiveDeps.erase(it); } foreach (const Item::Module &module, transitiveDeps) { if (module.isProduct) { item->addModule(module); ctx->info.usedProducts.append( ctx->project->topLevelProject->productModules.value( module.name.toString()).productDependencies); } else { Item::Module dep; dep.item = loadModule(ctx, item, item->location(), QString(), module.name, false, module.required, &dep.isProduct); if (!dep.item) continue; dep.name = module.name; item->addModule(dep); } } } Item *ModuleLoader::createNonPresentModule(const QString &name, const QString &reason, Item *module) { if (m_logger.traceEnabled()) { m_logger.qbsTrace() << "Non-required module '" << name << "' not loaded (" << reason << ")." << "Creating dummy module for presence check."; } if (!module) { module = Item::create(m_pool); module->setFile(FileContext::create()); module->setTypeName(QLatin1String("Module")); } module->setProperty(QLatin1String("present"), VariantValue::create(false)); return module; } void ModuleLoader::copyGroupsFromModuleToProduct(const ProductContext &productContext, const Item *modulePrototype) { for (int i = 0; i < modulePrototype->children().count(); ++i) { Item * const child = modulePrototype->children().at(i); if (child->typeName() == QLatin1String("Group")) { Item * const clonedGroup = child->clone(); clonedGroup->setScope(productContext.scope); Item::addChild(productContext.item, clonedGroup); } } } void ModuleLoader::copyGroupsFromModulesToProduct(const ProductContext &productContext) { foreach (const Item::Module &module, productContext.item->modules()) { Item *prototype = module.item; bool modulePassedValidation; while ((modulePassedValidation = prototype->isPresentModule() && !prototype->delayedError().hasError()) && prototype->prototype()) { prototype = prototype->prototype(); } if (modulePassedValidation) copyGroupsFromModuleToProduct(productContext, prototype); } } QString ModuleLoaderResult::ProductInfo::Dependency::uniqueName() const { return ResolvedProduct::uniqueName(name, profile); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/moduleloader.h000066400000000000000000000225371266132464200224760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_MODULELOADER_H #define QBS_MODULELOADER_H #include "forward_decls.h" #include "itempool.h" #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QScriptContext; class QScriptEngine; QT_END_NAMESPACE namespace qbs { class CodeLocation; namespace Internal { class Evaluator; class Item; class ItemReader; class ProgressObserver; class QualifiedId; class ScriptEngine; struct ModuleLoaderResult { ModuleLoaderResult() : itemPool(new ItemPool), root(0) {} struct ProductInfo { struct Dependency { QStringList productTypes; QString name; QString profile; // "*" <=> Match all profiles. bool limitToSubProject; QString uniqueName() const; }; QList usedProducts; }; QSharedPointer itemPool; Item *root; QHash productInfos; QSet qbsFiles; QVariantMap profileConfigs; }; /* * Loader stage II. Responsible for * - loading modules and module dependencies, * - project references, * - Probe items. */ class ModuleLoader { public: ModuleLoader(ScriptEngine *engine, const Logger &logger); ~ModuleLoader(); void setProgressObserver(ProgressObserver *progressObserver); void setSearchPaths(const QStringList &searchPaths); Evaluator *evaluator() const { return m_evaluator; } ModuleLoaderResult load(const SetupProjectParameters ¶meters); private: struct ItemCacheValue { explicit ItemCacheValue(Item *module = 0, bool enabled = false) : module(module), enabled(enabled) {} Item *module; bool enabled; }; typedef QMap, ItemCacheValue> ModuleItemCache; class ContextBase { public: ContextBase() : item(0), scope(0) {} Item *item; Item *scope; }; class ProjectContext; class ProductContext : public ContextBase { public: ProjectContext *project; ModuleLoaderResult::ProductInfo info; QString name; QString profileName; QSet filesWithExportItem; QVariantMap moduleProperties; }; class TopLevelProjectContext; class ProjectContext : public ContextBase { public: TopLevelProjectContext *topLevelProject; ModuleLoaderResult *result; QString buildDirectory; QVector products; QStack searchPathsStack; }; struct ProductModuleInfo { ProductModuleInfo() : exportItem() {} Item *exportItem; QList productDependencies; }; class TopLevelProjectContext { Q_DISABLE_COPY(TopLevelProjectContext) public: TopLevelProjectContext() {} ~TopLevelProjectContext() { qDeleteAll(projects); } QVector projects; QHash productModules; }; class DependsContext { public: ProductContext *product; QList *productDependencies; }; typedef QList ProductDependencyResults; void handleTopLevelProject(ModuleLoaderResult *loadResult, Item *item, const QString &buildDirectory, const QSet &referencedFilePaths); void handleProject(ModuleLoaderResult *loadResult, TopLevelProjectContext *topLevelProjectContext, Item *item, const QString &buildDirectory, const QSet &referencedFilePaths); QList multiplexProductItem(ProductContext *dummyContext, Item *productItem); void prepareProduct(ProjectContext *projectContext, Item *item); void handleProduct(ProductContext *productContext); void initProductProperties(const ProjectContext *project, Item *item); void handleSubProject(ProjectContext *projectContext, Item *item, const QSet &referencedFilePaths); void handleGroup(ProductContext *productContext, Item *group); Item *mergeExportItems(ProductContext *productContext, const QVector &exportItemsInProduct); void propagateModulesFromProduct(ProductContext *productContext, Item *item); void resolveDependencies(DependsContext *dependsContext, Item *item); class ItemModuleList; void resolveDependsItem(DependsContext *dependsContext, Item *item, Item *dependsItem, ItemModuleList *moduleResults, ProductDependencyResults *productResults); Item *moduleInstanceItem(Item *item, const QualifiedId &moduleName); Item *loadProductModule(ProductContext *productContext, const QString &moduleName); Item *loadModule(ProductContext *productContext, Item *item, const CodeLocation &dependsItemLocation, const QString &moduleId, const QualifiedId &moduleName, bool isBaseModule, bool isRequired, bool *isModuleDependency); Item *searchAndLoadModuleFile(ProductContext *productContext, const CodeLocation &dependsItemLocation, const QualifiedId &moduleName, const QStringList &extraSearchPaths, bool isRequired, bool *cacheHit); Item *loadModuleFile(ProductContext *productContext, const QString &fullModuleName, bool isBaseModule, const QString &filePath, bool *cacheHit, bool *triedToLoad); void loadBaseModule(ProductContext *productContext, Item *item); void setupBaseModulePrototype(Item *prototype); void instantiateModule(ProductContext *productContext, Item *exportingProductItem, Item *instanceScope, Item *moduleInstance, Item *modulePrototype, const QualifiedId &moduleName, bool isProduct); void createChildInstances(ProductContext *productContext, Item *instance, Item *prototype, QHash *prototypeInstanceMap) const; void resolveProbes(Item *item); void resolveProbe(Item *parent, Item *probe); void checkCancelation() const; bool checkItemCondition(Item *item); void checkItemTypes(Item *item); QStringList readExtraSearchPaths(Item *item, bool *wasSet = 0); void copyProperties(const Item *sourceProject, Item *targetProject); Item *wrapWithProject(Item *item); static QString findExistingModulePath(const QString &searchPath, const QualifiedId &moduleName); static void setScopeForDescendants(Item *item, Item *scope); void overrideItemProperties(Item *item, const QString &buildConfigKey, const QVariantMap &buildConfig); void addTransitiveDependencies(ProductContext *ctx, Item *item); Item *createNonPresentModule(const QString &name, const QString &reason, Item *module); void copyGroupsFromModuleToProduct(const ProductContext &productContext, const Item *modulePrototype); void copyGroupsFromModulesToProduct(const ProductContext &productContext); ScriptEngine *m_engine; ItemPool *m_pool; Logger m_logger; ProgressObserver *m_progressObserver; ItemReader *m_reader; Evaluator *m_evaluator; QStringList m_moduleSearchPaths; QMap m_moduleDirListCache; QHash m_productModuleCache; ModuleItemCache m_modulePrototypeItemCache; QHash > m_validItemPropertyNamesPerItem; QSet m_disabledItems; SetupProjectParameters m_parameters; Version m_qbsVersion; }; } // namespace Internal } // namespace qbs QT_BEGIN_NAMESPACE Q_DECLARE_TYPEINFO(qbs::Internal::ModuleLoaderResult::ProductInfo, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(qbs::Internal::ModuleLoaderResult::ProductInfo::Dependency, Q_MOVABLE_TYPE); QT_END_NAMESPACE #endif // QBS_MODULELOADER_H qbs-src-1.4.5/src/lib/corelib/language/modulemerger.cpp000066400000000000000000000202551266132464200230370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "modulemerger.h" #include "value.h" #include #include namespace qbs { namespace Internal { ModuleMerger::ModuleMerger(const Logger &logger, Item *root, Item *moduleToMerge, const QualifiedId &moduleName) : m_logger(logger) , m_rootItem(root) , m_mergedModuleItem(moduleToMerge) , m_moduleName(moduleName) { } void ModuleMerger::start() { if (!m_mergedModuleItem->isPresentModule()) return; Item::Module m; m.item = m_rootItem; const Item::PropertyMap props = dfs(m, Item::PropertyMap()); Item::PropertyMap mergedProps = m_mergedModuleItem->properties(); Item *moduleProto = m_mergedModuleItem->prototype(); while (moduleProto->prototype()) moduleProto = moduleProto->prototype(); for (auto it = props.constBegin(); it != props.constEnd(); ++it) { appendPrototypeValueToNextChain(moduleProto, it.key(), it.value()); mergedProps[it.key()] = it.value(); } m_mergedModuleItem->setProperties(mergedProps); } Item::PropertyMap ModuleMerger::dfs(const Item::Module &m, Item::PropertyMap props) { Item *moduleInstance = 0; int numberOfOutprops = m.item->modules().count(); foreach (const Item::Module &dep, m.item->modules()) { if (dep.name == m_moduleName) { --numberOfOutprops; moduleInstance = dep.item; pushScalarProperties(&props, moduleInstance); break; } } QVector outprops; outprops.reserve(numberOfOutprops); foreach (const Item::Module &dep, m.item->modules()) { if (dep.item != moduleInstance) outprops << dfs(dep, props); } if (!outprops.isEmpty()) { props = outprops.first(); for (int i = 1; i < outprops.count(); ++i) mergeOutProps(&props, outprops.at(i)); } if (moduleInstance) pullListProperties(&props, moduleInstance); return props; } void ModuleMerger::pushScalarProperties(Item::PropertyMap *dst, Item *srcItem) { Item *origSrcItem = srcItem; do { if (!m_seenInstancesTopDown.contains(srcItem)) { m_seenInstancesTopDown.insert(srcItem); for (auto it = srcItem->properties().constBegin(); it != srcItem->properties().constEnd(); ++it) { const ValuePtr &srcVal = it.value(); if (srcVal->type() != Value::JSSourceValueType) continue; const PropertyDeclaration srcDecl = srcItem->propertyDeclaration(it.key()); if (!srcDecl.isValid() || !srcDecl.isScalar()) continue; ValuePtr &v = (*dst)[it.key()]; if (v) continue; ValuePtr clonedVal = srcVal->clone(); m_decls[clonedVal] = srcDecl; clonedVal->setDefiningItem(origSrcItem); v = clonedVal; } } srcItem = srcItem->prototype(); } while (srcItem && srcItem->isModuleInstance()); } void ModuleMerger::mergeOutProps(Item::PropertyMap *dst, const Item::PropertyMap &src) { for (auto it = src.constBegin(); it != src.constEnd(); ++it) { ValuePtr &v = (*dst)[it.key()]; if (!v) { v = it.value(); QBS_ASSERT(it.value(), continue); continue; } // possible conflict JSSourceValuePtr dstVal = v.dynamicCast(); if (!dstVal) continue; JSSourceValuePtr srcVal = it.value().dynamicCast(); if (!srcVal) continue; const PropertyDeclaration pd = m_decls.value(srcVal); if (!pd.isValid()) continue; if (pd.isScalar()) { if (dstVal->sourceCode() != srcVal->sourceCode() && dstVal->isInExportItem() == srcVal->isInExportItem()) { m_logger.qbsWarning() << Tr::tr("Conflicting scalar values at %1 and %2.").arg( dstVal->location().toString(), srcVal->location().toString()); // TODO: yield error with a hint how to solve the conflict. } if (!dstVal->isInExportItem()) v = it.value(); } else { lastInNextChain(dstVal)->setNext(srcVal); } } } void ModuleMerger::pullListProperties(Item::PropertyMap *dst, Item *instance) { Item *origInstance = instance; do { if (!m_seenInstancesBottomUp.contains(instance)) { m_seenInstancesBottomUp.insert(instance); for (Item::PropertyMap::const_iterator it = instance->properties().constBegin(); it != instance->properties().constEnd(); ++it) { const ValuePtr &srcVal = it.value(); if (srcVal->type() != Value::JSSourceValueType) continue; const PropertyDeclaration srcDecl = instance->propertyDeclaration(it.key()); if (!srcDecl.isValid() || srcDecl.isScalar()) continue; ValuePtr clonedVal = srcVal->clone(); m_decls[clonedVal] = srcDecl; clonedVal->setDefiningItem(origInstance); ValuePtr &v = (*dst)[it.key()]; if (v) { QBS_CHECK(!clonedVal->next()); clonedVal->setNext(v); } v = clonedVal; } } instance = instance->prototype(); } while (instance && instance->isModuleInstance()); } void ModuleMerger::appendPrototypeValueToNextChain(Item *moduleProto, const QString &propertyName, const ValuePtr &sv) { const PropertyDeclaration pd = m_mergedModuleItem->propertyDeclaration(propertyName); if (pd.isScalar()) return; ValuePtr protoValue = moduleProto->property(propertyName); if (!protoValue) return; if (!m_clonedModulePrototype) { m_clonedModulePrototype = moduleProto->clone(); Item * const scope = Item::create(m_clonedModulePrototype->pool()); scope->setFile(m_clonedModulePrototype->file()); m_mergedModuleItem->scope()->copyProperty(QLatin1String("project"), scope); m_mergedModuleItem->scope()->copyProperty(QLatin1String("product"), scope); m_clonedModulePrototype->setScope(scope); } const ValuePtr clonedValue = protoValue->clone(); clonedValue->setDefiningItem(m_clonedModulePrototype); lastInNextChain(sv)->setNext(clonedValue); } ValuePtr ModuleMerger::lastInNextChain(const ValuePtr &v) { ValuePtr n = v; while (n->next()) n = n->next(); return n; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/modulemerger.h000066400000000000000000000053101266132464200224770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_MODULEMERGER_H #define QBS_MODULEMERGER_H #include "item.h" #include "qualifiedid.h" #include #include #include namespace qbs { namespace Internal { class ModuleMerger { public: ModuleMerger(const Logger &logger, Item *root, Item *moduleToMerge, const QualifiedId &moduleName); void start(); private: Item::PropertyMap dfs(const Item::Module &m, Item::PropertyMap props); void pushScalarProperties(Item::PropertyMap *dst, Item *srcItem); void mergeOutProps(Item::PropertyMap *dst, const Item::PropertyMap &src); void pullListProperties(Item::PropertyMap *dst, Item *instance); void appendPrototypeValueToNextChain(Item *moduleProto, const QString &propertyName, const ValuePtr &sv); static ValuePtr lastInNextChain(const ValuePtr &v); const Logger &m_logger; Item * const m_rootItem; Item *m_mergedModuleItem; Item *m_clonedModulePrototype = nullptr; const QualifiedId m_moduleName; QHash m_decls; QSet m_seenInstancesTopDown; QSet m_seenInstancesBottomUp; }; } // namespace Internal } // namespace qbs #endif // QBS_MODULEMERGER_H qbs-src-1.4.5/src/lib/corelib/language/preparescriptobserver.cpp000066400000000000000000000046061266132464200250050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "preparescriptobserver.h" #include "property.h" #include "scriptengine.h" #include namespace qbs { namespace Internal { PrepareScriptObserver::PrepareScriptObserver(ScriptEngine *engine) : m_engine(engine) , m_productObjectId(-1) , m_projectObjectId(-1) { } void PrepareScriptObserver::onPropertyRead(const QScriptValue &object, const QString &name, const QScriptValue &value) { if (object.objectId() == m_productObjectId) { m_engine->addPropertyRequestedInScript( Property(QString(), name, value.toVariant(), Property::PropertyInProduct)); } else if (object.objectId() == m_projectObjectId) { m_engine->addPropertyRequestedInScript( Property(QString(), name, value.toVariant(), Property::PropertyInProject)); } } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/preparescriptobserver.h000066400000000000000000000043171266132464200244510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PREPARESCRIPTOBSERVER_H #define QBS_PREPARESCRIPTOBSERVER_H #include "scriptpropertyobserver.h" namespace qbs { namespace Internal { class ScriptEngine; class PrepareScriptObserver : public ScriptPropertyObserver { public: PrepareScriptObserver(ScriptEngine *engine); void setProductObjectId(qint64 productId) { m_productObjectId = productId; } void setProjectObjectId(qint64 projectId) { m_projectObjectId = projectId; } private: void onPropertyRead(const QScriptValue &object, const QString &name, const QScriptValue &value); ScriptEngine * const m_engine; qint64 m_productObjectId; qint64 m_projectObjectId; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.4.5/src/lib/corelib/language/projectresolver.cpp000066400000000000000000001343111266132464200235770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "projectresolver.h" #include "artifactproperties.h" #include "evaluator.h" #include "filecontext.h" #include "item.h" #include "language.h" #include "modulemerger.h" #include "propertymapinternal.h" #include "resolvedfilecontext.h" #include "scriptengine.h" #include "value.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { extern bool debugProperties; static const FileTag unknownFileTag() { static const FileTag tag("unknown-file-tag"); return tag; } ProjectResolver::ProjectResolver(ModuleLoader *ldr, const Logger &logger) : m_evaluator(ldr->evaluator()) , m_logger(logger) , m_engine(m_evaluator->engine()) , m_progressObserver(0) { } ProjectResolver::~ProjectResolver() { } void ProjectResolver::setProgressObserver(ProgressObserver *observer) { m_progressObserver = observer; } static void checkForDuplicateProductNames(const TopLevelProjectConstPtr &project) { const QList allProducts = project->allProducts(); for (int i = 0; i < allProducts.count(); ++i) { const ResolvedProductConstPtr product1 = allProducts.at(i); const QString productName = product1->uniqueName(); for (int j = i + 1; j < allProducts.count(); ++j) { const ResolvedProductConstPtr product2 = allProducts.at(j); if (product2->uniqueName() == productName) { ErrorInfo error; error.append(Tr::tr("Duplicate product name '%1'.").arg(product1->name)); error.append(Tr::tr("First product defined here."), product1->location); error.append(Tr::tr("Second product defined here."), product2->location); throw error; } } } } TopLevelProjectPtr ProjectResolver::resolve(ModuleLoaderResult &loadResult, const SetupProjectParameters &setupParameters) { QBS_CHECK(FileInfo::isAbsolute(setupParameters.buildRoot())); if (m_logger.traceEnabled()) m_logger.qbsTrace() << "[PR] resolving " << loadResult.root->file()->filePath(); ProjectContext projectContext; projectContext.loadResult = &loadResult; m_setupParams = setupParameters; m_productContext = 0; m_moduleContext = 0; resolveTopLevelProject(loadResult.root, &projectContext); TopLevelProjectPtr top = projectContext.project.staticCast(); checkForDuplicateProductNames(top); top->buildSystemFiles.unite(loadResult.qbsFiles); top->profileConfigs = loadResult.profileConfigs; return top; } void ProjectResolver::checkCancelation() const { if (m_progressObserver && m_progressObserver->canceled()) { throw ErrorInfo(Tr::tr("Project resolving canceled for configuration %1.") .arg(TopLevelProject::deriveId(m_setupParams.topLevelProfile(), m_setupParams.finalBuildConfigurationTree()))); } } QString ProjectResolver::verbatimValue(const ValueConstPtr &value, bool *propertyWasSet) const { QString result; if (value && value->type() == Value::JSSourceValueType) { const JSSourceValueConstPtr sourceValue = value.staticCast(); result = sourceValue->sourceCodeForEvaluation(); if (propertyWasSet) *propertyWasSet = (result != QLatin1String("undefined")); } else { if (propertyWasSet) *propertyWasSet = false; } return result; } QString ProjectResolver::verbatimValue(Item *item, const QString &name, bool *propertyWasSet) const { return verbatimValue(item->property(name), propertyWasSet); } void ProjectResolver::ignoreItem(Item *item, ProjectContext *projectContext) { Q_UNUSED(item); Q_UNUSED(projectContext); } static void makeSubProjectNamesUniqe(const ResolvedProjectPtr &parentProject) { QSet subProjectNames; QSet projectsInNeedOfNameChange; foreach (const ResolvedProjectPtr &p, parentProject->subProjects) { if (subProjectNames.contains(p->name)) projectsInNeedOfNameChange << p; else subProjectNames << p->name; makeSubProjectNamesUniqe(p); } while (!projectsInNeedOfNameChange.isEmpty()) { QSet::Iterator it = projectsInNeedOfNameChange.begin(); while (it != projectsInNeedOfNameChange.end()) { const ResolvedProjectPtr p = *it; p->name += QLatin1Char('_'); if (!subProjectNames.contains(p->name)) { subProjectNames << p->name; it = projectsInNeedOfNameChange.erase(it); } else { ++it; } } } } void ProjectResolver::resolveTopLevelProject(Item *item, ProjectContext *projectContext) { if (m_progressObserver) m_progressObserver->setMaximum(projectContext->loadResult->productInfos.count()); const TopLevelProjectPtr project = TopLevelProject::create(); project->buildDirectory = TopLevelProject::deriveBuildDirectory(m_setupParams.buildRoot(), TopLevelProject::deriveId(m_setupParams.topLevelProfile(), m_setupParams.finalBuildConfigurationTree())); projectContext->project = project; resolveProject(item, projectContext); project->setBuildConfiguration(m_setupParams.finalBuildConfigurationTree()); project->usedEnvironment = m_engine->usedEnvironment(); project->canonicalFilePathResults = m_engine->canonicalFilePathResults(); project->fileExistsResults = m_engine->fileExistsResults(); project->fileLastModifiedResults = m_engine->fileLastModifiedResults(); project->environment = m_engine->environment(); project->buildSystemFiles = m_engine->imports(); makeSubProjectNamesUniqe(project); resolveProductDependencies(projectContext); foreach (const ResolvedProductPtr &product, project->allProducts()) { if (!product->enabled) continue; applyFileTaggers(product); matchArtifactProperties(product, product->allEnabledFiles()); // Let a positive value of qbs.install imply the file tag "installable". foreach (const SourceArtifactPtr &artifact, product->allFiles()) { if (artifact->properties->qbsPropertyValue(QLatin1String("install")).toBool()) artifact->fileTags += "installable"; } } } void ProjectResolver::resolveProject(Item *item, ProjectContext *projectContext) { checkCancelation(); projectContext->project->name = m_evaluator->stringValue(item, QLatin1String("name")); projectContext->project->location = item->location(); if (projectContext->project->name.isEmpty()) projectContext->project->name = FileInfo::baseName(item->location().filePath()); // FIXME: Must also be changed in item? projectContext->project->enabled = m_evaluator->boolValue(item, QLatin1String("condition")); QVariantMap projectProperties; if (!projectContext->project->enabled) { projectProperties.insert(QLatin1String("profile"), m_evaluator->stringValue(item, QLatin1String("profile"))); projectContext->project->setProjectProperties(projectProperties); return; } projectContext->dummyModule = ResolvedModule::create(); for (Item::PropertyDeclarationMap::const_iterator it = item->propertyDeclarations().constBegin(); it != item->propertyDeclarations().constEnd(); ++it) { if (it.value().flags().testFlag(PropertyDeclaration::PropertyNotAvailableInConfig)) continue; const ValueConstPtr v = item->property(it.key()); QBS_ASSERT(v && v->type() != Value::ItemValueType, continue); projectProperties.insert(it.key(), m_evaluator->value(item, it.key()).toVariant()); } projectContext->project->setProjectProperties(projectProperties); ItemFuncMap mapping; mapping["Project"] = &ProjectResolver::resolveProject; mapping["SubProject"] = &ProjectResolver::resolveSubProject; mapping["Product"] = &ProjectResolver::resolveProduct; mapping["FileTagger"] = &ProjectResolver::resolveFileTagger; mapping["Rule"] = &ProjectResolver::resolveRule; mapping["PropertyOptions"] = &ProjectResolver::ignoreItem; foreach (Item *child, item->children()) callItemFunction(mapping, child, projectContext); foreach (const ResolvedProductPtr &product, projectContext->project->products) postProcess(product, projectContext); } void ProjectResolver::resolveSubProject(Item *item, ProjectResolver::ProjectContext *projectContext) { ProjectContext subProjectContext = createProjectContext(projectContext); Item * const projectItem = item->child(QLatin1String("Project")); if (projectItem) { resolveProject(projectItem, &subProjectContext); return; } // No project item was found, which means the project was disabled. subProjectContext.project->enabled = false; Item * const propertiesItem = item->child(QLatin1String("Properties")); if (propertiesItem) { subProjectContext.project->name = m_evaluator->stringValue(propertiesItem, QLatin1String("name")); } } class ModuleNameEquals { QString m_str; public: ModuleNameEquals(const QString &str) : m_str(str) {} bool operator()(const Item::Module &module) { return module.name.count() == 1 && module.name.first() == m_str; } }; void ProjectResolver::resolveProduct(Item *item, ProjectContext *projectContext) { checkCancelation(); ProductContext productContext; m_productContext = &productContext; productContext.item = item; ResolvedProductPtr product = ResolvedProduct::create(); product->project = projectContext->project; m_productItemMap.insert(product, item); projectContext->project->products += product; productContext.product = product; product->name = m_evaluator->stringValue(item, QLatin1String("name")); // product->buildDirectory() isn't valid yet, because the productProperties map is not ready. productContext.buildDirectory = m_evaluator->stringValue(item, QLatin1String("buildDirectory")); product->profile = m_evaluator->stringValue(item, QLatin1String("profile")); QBS_CHECK(!product->profile.isEmpty()); m_logger.qbsTrace() << "[PR] resolveProduct " << product->uniqueName(); if (std::find_if(item->modules().begin(), item->modules().end(), ModuleNameEquals(product->name)) != item->modules().end()) { throw ErrorInfo( Tr::tr("The product name '%1' collides with a module name.").arg(product->name), item->location()); } product->enabled = m_evaluator->boolValue(item, QLatin1String("condition")); product->fileTags = m_evaluator->fileTagsValue(item, QLatin1String("type")); product->targetName = m_evaluator->stringValue(item, QLatin1String("targetName")); product->sourceDirectory = m_evaluator->stringValue(item, QLatin1String("sourceDirectory")); const QString destDirKey = QLatin1String("destinationDirectory"); product->destinationDirectory = m_evaluator->stringValue(item, destDirKey); if (product->destinationDirectory.isEmpty()) { product->destinationDirectory = productContext.buildDirectory; } else { product->destinationDirectory = FileInfo::resolvePath( product->topLevelProject()->buildDirectory, product->destinationDirectory); } product->location = item->location(); product->productProperties = createProductConfig(); product->productProperties.insert(destDirKey, product->destinationDirectory); QVariantMap moduleProperties; moduleProperties.insert(QLatin1String("modules"), product->productProperties.take(QLatin1String("modules"))); product->moduleProperties = PropertyMapInternal::create(); product->moduleProperties->setValue(moduleProperties); ModuleProperties::init(m_evaluator->scriptValue(item), product); QList subItems = item->children(); const ValuePtr filesProperty = item->property(QLatin1String("files")); if (filesProperty) { Item *fakeGroup = Item::create(item->pool()); fakeGroup->setFile(item->file()); fakeGroup->setLocation(item->location()); fakeGroup->setScope(item); fakeGroup->setTypeName(QLatin1String("Group")); fakeGroup->setProperty(QLatin1String("name"), VariantValue::create(product->name)); fakeGroup->setProperty(QLatin1String("files"), filesProperty); fakeGroup->setProperty(QLatin1String("excludeFiles"), item->property(QLatin1String("excludeFiles"))); fakeGroup->setProperty(QLatin1String("overrideTags"), VariantValue::create(false)); fakeGroup->setupForBuiltinType(m_logger); subItems.prepend(fakeGroup); } ItemFuncMap mapping; mapping["Depends"] = &ProjectResolver::ignoreItem; mapping["Rule"] = &ProjectResolver::resolveRule; mapping["FileTagger"] = &ProjectResolver::resolveFileTagger; mapping["Transformer"] = &ProjectResolver::resolveTransformer; mapping["Group"] = &ProjectResolver::resolveGroup; mapping["Export"] = &ProjectResolver::ignoreItem; mapping["Probe"] = &ProjectResolver::ignoreItem; mapping["PropertyOptions"] = &ProjectResolver::ignoreItem; foreach (Item *child, subItems) callItemFunction(mapping, child, projectContext); resolveModules(item, projectContext); product->fileTags += productContext.additionalFileTags; foreach (const ResolvedTransformerPtr &transformer, product->transformers) matchArtifactProperties(product, transformer->outputs); m_productsByName.insert(product->uniqueName(), product); foreach (const FileTag &t, product->fileTags) m_productsByType[t.toString()] << product; m_productContext = 0; if (m_progressObserver) m_progressObserver->incrementProgressValue(); } void ProjectResolver::resolveModules(const Item *item, ProjectContext *projectContext) { // Breadth first search needed here, because the product might set properties on the cpp module, // whose children must be evaluated in that context then. QQueue modules; foreach (const Item::Module &m, item->modules()) modules.enqueue(m); QSet seen; while (!modules.isEmpty()) { const Item::Module m = modules.takeFirst(); if (seen.contains(m.name)) continue; seen.insert(m.name); resolveModule(m.name, m.item, m.isProduct, projectContext); foreach (const Item::Module &childModule, m.item->modules()) modules.enqueue(childModule); } std::sort(m_productContext->product->modules.begin(), m_productContext->product->modules.end(), [](const ResolvedModuleConstPtr &m1, const ResolvedModuleConstPtr &m2) { return m1->name < m2->name; }); } void ProjectResolver::resolveModule(const QualifiedId &moduleName, Item *item, bool isProduct, ProjectContext *projectContext) { checkCancelation(); if (!m_evaluator->boolValue(item, QLatin1String("present"))) return; if (m_productContext->product->enabled && item->delayedError().hasError()) throw item->delayedError(); ModuleContext * const oldModuleContext = m_moduleContext; ModuleContext moduleContext; moduleContext.module = ResolvedModule::create(); m_moduleContext = &moduleContext; const ResolvedModulePtr &module = moduleContext.module; module->name = moduleName.toString(); module->setupBuildEnvironmentScript = scriptFunctionValue(item, QLatin1String("setupBuildEnvironment")); module->setupRunEnvironmentScript = scriptFunctionValue(item, QLatin1String("setupRunEnvironment")); m_productContext->additionalFileTags += m_evaluator->fileTagsValue(item, QLatin1String("additionalProductTypes")); foreach (const Item::Module &m, item->modules()) { if (m_evaluator->boolValue(m.item, QLatin1String("present"))) module->moduleDependencies += m.name.toString(); } if (!isProduct) m_productContext->product->modules += module; ItemFuncMap mapping; mapping["Group"] = &ProjectResolver::ignoreItem; mapping["Rule"] = &ProjectResolver::resolveRule; mapping["FileTagger"] = &ProjectResolver::resolveFileTagger; mapping["Transformer"] = &ProjectResolver::resolveTransformer; mapping["Scanner"] = &ProjectResolver::resolveScanner; mapping["PropertyOptions"] = &ProjectResolver::ignoreItem; mapping["Depends"] = &ProjectResolver::ignoreItem; mapping["Probe"] = &ProjectResolver::ignoreItem; foreach (Item *child, item->children()) callItemFunction(mapping, child, projectContext); m_moduleContext = oldModuleContext; } SourceArtifactPtr ProjectResolver::createSourceArtifact(const ResolvedProductConstPtr &rproduct, const PropertyMapPtr &properties, const QString &fileName, const FileTags &fileTags, bool overrideTags, QList &artifactList) { SourceArtifactPtr artifact = SourceArtifactInternal::create(); artifact->absoluteFilePath = FileInfo::resolvePath(rproduct->sourceDirectory, fileName); artifact->absoluteFilePath = QDir::cleanPath(artifact->absoluteFilePath); // Potentially necessary for groups with prefixes. artifact->fileTags = fileTags; artifact->overrideFileTags = overrideTags; artifact->properties = properties; artifactList += artifact; return artifact; } static bool isSomeModulePropertySet(Item *group) { for (QMap::const_iterator it = group->properties().constBegin(); it != group->properties().constEnd(); ++it) { if (it.value()->type() == Value::ItemValueType) { // An item value is a module value in this case. ItemValuePtr iv = it.value().staticCast(); foreach (ValuePtr ivv, iv->item()->properties()) { if (ivv->type() == Value::JSSourceValueType) return true; } } } return false; } void ProjectResolver::resolveGroup(Item *item, ProjectContext *projectContext) { Q_UNUSED(projectContext); checkCancelation(); PropertyMapPtr moduleProperties = m_productContext->product->moduleProperties; if (isSomeModulePropertySet(item)) { moduleProperties = PropertyMapInternal::create(); m_evaluator->setCachingEnabled(true); moduleProperties->setValue(evaluateModuleValues(item)); m_evaluator->setCachingEnabled(false); } const bool isEnabled = m_evaluator->boolValue(item, QLatin1String("condition")); QStringList files = m_evaluator->stringListValue(item, QLatin1String("files")); const QStringList fileTagsFilter = m_evaluator->stringListValue(item, QLatin1String("fileTagsFilter")); if (!fileTagsFilter.isEmpty()) { if (Q_UNLIKELY(!files.isEmpty())) throw ErrorInfo(Tr::tr("Group.files and Group.fileTagsFilters are exclusive."), item->location()); ProductContext::ArtifactPropertiesInfo apinfo = m_productContext->artifactPropertiesPerFilter.value(fileTagsFilter); if (apinfo.first) { if (apinfo.second.filePath() == item->location().filePath()) { ErrorInfo error(Tr::tr("Conflicting fileTagsFilter in Group items.")); error.append(Tr::tr("First item"), apinfo.second); error.append(Tr::tr("Second item"), item->location()); throw error; } // Discard any Group with the same fileTagsFilter that was defined in a base file. m_productContext->product->artifactProperties.removeAll(apinfo.first); } if (!isEnabled) return; ArtifactPropertiesPtr aprops = ArtifactProperties::create(); aprops->setFileTagsFilter(FileTags::fromStringList(fileTagsFilter)); aprops->setPropertyMapInternal(moduleProperties); m_productContext->product->artifactProperties += aprops; m_productContext->artifactPropertiesPerFilter.insert(fileTagsFilter, ProductContext::ArtifactPropertiesInfo(aprops, item->location())); return; } if (Q_UNLIKELY(files.isEmpty() && !item->hasProperty(QLatin1String("files")))) { // Yield an error if Group without files binding is encountered. // An empty files value is OK but a binding must exist. throw ErrorInfo(Tr::tr("Group without files is not allowed."), item->location()); } QStringList patterns; for (int i = files.count(); --i >= 0;) { if (FileInfo::isPattern(files[i])) patterns.append(files.takeAt(i)); } GroupPtr group = ResolvedGroup::create(); group->prefix = m_evaluator->stringValue(item, QLatin1String("prefix")); if (!group->prefix.isEmpty()) { for (int i = files.count(); --i >= 0;) files[i].prepend(group->prefix); } group->location = item->location(); group->enabled = isEnabled; bool fileTagsSet; group->fileTags = m_evaluator->fileTagsValue(item, QLatin1String("fileTags"), &fileTagsSet); group->overrideTags = m_evaluator->boolValue(item, QLatin1String("overrideTags")); if (group->overrideTags && group->fileTags.isEmpty() && fileTagsSet) group->fileTags.insert(unknownFileTag()); if (!patterns.isEmpty()) { SourceWildCards::Ptr wildcards = SourceWildCards::create(); wildcards->excludePatterns = m_evaluator->stringListValue(item, QLatin1String("excludeFiles")); wildcards->prefix = group->prefix; wildcards->patterns = patterns; QSet files = wildcards->expandPatterns(group, m_productContext->product->sourceDirectory); foreach (const QString &fileName, files) createSourceArtifact(m_productContext->product, moduleProperties, fileName, group->fileTags, group->overrideTags, wildcards->files); group->wildcards = wildcards; } foreach (const QString &fileName, files) createSourceArtifact(m_productContext->product, moduleProperties, fileName, group->fileTags, group->overrideTags, group->files); ErrorInfo fileError; if (group->enabled) { const ValuePtr filesValue = item->property(QLatin1String("files")); foreach (const SourceArtifactConstPtr &a, group->allFiles()) { if (!FileInfo(a->absoluteFilePath).exists()) { fileError.append(Tr::tr("File '%1' does not exist.") .arg(a->absoluteFilePath), item->property(QLatin1String("files"))->location()); } CodeLocation &loc = m_productContext->sourceArtifactLocations[a->absoluteFilePath]; if (loc.isValid()) { fileError.append(Tr::tr("Duplicate source file '%1' at %2 and %3.") .arg(a->absoluteFilePath, loc.toString(), filesValue->location().toString())); } loc = filesValue->location(); } if (fileError.hasError()) throw ErrorInfo(fileError); } group->name = m_evaluator->stringValue(item, QLatin1String("name")); if (group->name.isEmpty()) group->name = Tr::tr("Group %1").arg(m_productContext->product->groups.count()); group->properties = moduleProperties; m_productContext->product->groups += group; } static QString sourceCodeAsFunction(const JSSourceValueConstPtr &value, const PropertyDeclaration &decl) { const QString args = decl.functionArgumentNames().join(QLatin1Char(',')); if (value->hasFunctionForm()) { // Insert the argument list. QString code = value->sourceCodeForEvaluation(); code.insert(10, args); // Remove the function application "()" that has been // added in ItemReaderASTVisitor::visitStatement. return code.left(code.length() - 2); } else { return QLatin1String("(function(") + args + QLatin1String("){return ") + value->sourceCode().toString() + QLatin1String(";})"); } } ScriptFunctionPtr ProjectResolver::scriptFunctionValue(Item *item, const QString &name) const { ScriptFunctionPtr script = ScriptFunction::create(); JSSourceValuePtr value = item->sourceProperty(name); if (value) { const PropertyDeclaration decl = item->propertyDeclaration(name); script->sourceCode = sourceCodeAsFunction(value, decl); script->argumentNames = decl.functionArgumentNames(); script->location = value->location(); script->fileContext = resolvedFileContext(value->file()); } return script; } ResolvedFileContextPtr ProjectResolver::resolvedFileContext(const FileContextConstPtr &ctx) const { ResolvedFileContextPtr &result = m_fileContextMap[ctx]; if (!result) result = ResolvedFileContext::create(*ctx); return result; } void ProjectResolver::resolveRule(Item *item, ProjectContext *projectContext) { checkCancelation(); if (!m_evaluator->boolValue(item, QLatin1String("condition"))) return; RulePtr rule = Rule::create(); // read artifacts bool hasArtifactChildren = false; foreach (Item *child, item->children()) { if (Q_UNLIKELY(child->typeName() != QLatin1String("Artifact"))) throw ErrorInfo(Tr::tr("'Rule' can only have children of type 'Artifact'."), child->location()); hasArtifactChildren = true; resolveRuleArtifact(rule, child); } rule->name = m_evaluator->stringValue(item, QLatin1String("name")); rule->prepareScript = scriptFunctionValue(item, QLatin1String("prepare")); rule->outputArtifactsScript = scriptFunctionValue(item, QLatin1String("outputArtifacts")); if (rule->outputArtifactsScript->isValid()) { if (hasArtifactChildren) throw ErrorInfo(Tr::tr("The Rule.outputArtifacts script is not allowed in rules " "that contain Artifact items."), item->location()); rule->outputFileTags = m_evaluator->fileTagsValue(item, QStringLiteral("outputFileTags")); if (rule->outputFileTags.isEmpty()) throw ErrorInfo(Tr::tr("Rule.outputFileTags must be specified if " "Rule.outputArtifacts is specified."), item->location()); } rule->multiplex = m_evaluator->boolValue(item, QLatin1String("multiplex")); rule->inputs = m_evaluator->fileTagsValue(item, QLatin1String("inputs")); rule->inputsFromDependencies = m_evaluator->fileTagsValue(item, QLatin1String("inputsFromDependencies")); // TODO: Remove in 1.5. foreach (const FileTag &ft, m_evaluator->fileTagsValue(item, QLatin1String("usings"))) rule->inputsFromDependencies << ft; rule->auxiliaryInputs = m_evaluator->fileTagsValue(item, QLatin1String("auxiliaryInputs")); rule->excludedAuxiliaryInputs = m_evaluator->fileTagsValue(item, QLatin1String("excludedAuxiliaryInputs")); rule->explicitlyDependsOn = m_evaluator->fileTagsValue(item, QLatin1String("explicitlyDependsOn")); rule->module = m_moduleContext ? m_moduleContext->module : projectContext->dummyModule; if (m_productContext) m_productContext->product->rules += rule; else projectContext->rules += rule; } class QualifiedIdSet : public std::set { public: typedef std::pair InsertResult; }; void ProjectResolver::resolveRuleArtifact(const RulePtr &rule, Item *item) { RuleArtifactPtr artifact = RuleArtifact::create(); rule->artifacts += artifact; artifact->location = item->location(); artifact->filePath = verbatimValue(item, QLatin1String("filePath")); artifact->fileTags = m_evaluator->fileTagsValue(item, QLatin1String("fileTags")); artifact->alwaysUpdated = m_evaluator->boolValue(item, QLatin1String("alwaysUpdated")); QualifiedIdSet seenBindings; for (Item *obj = item; obj; obj = obj->prototype()) { for (QMap::const_iterator it = obj->properties().constBegin(); it != obj->properties().constEnd(); ++it) { if (it.value()->type() != Value::ItemValueType) continue; resolveRuleArtifactBinding(artifact, it.value().staticCast()->item(), QStringList(it.key()), &seenBindings); } } } void ProjectResolver::resolveRuleArtifactBinding(const RuleArtifactPtr &ruleArtifact, Item *item, const QStringList &namePrefix, QualifiedIdSet *seenBindings) { for (QMap::const_iterator it = item->properties().constBegin(); it != item->properties().constEnd(); ++it) { const QStringList name = QStringList(namePrefix) << it.key(); if (it.value()->type() == Value::ItemValueType) { resolveRuleArtifactBinding(ruleArtifact, it.value().staticCast()->item(), name, seenBindings); } else if (it.value()->type() == Value::JSSourceValueType) { const QualifiedIdSet::InsertResult insertResult = seenBindings->insert(name); if (!insertResult.second) continue; JSSourceValuePtr sourceValue = it.value().staticCast(); RuleArtifact::Binding rab; rab.name = name; rab.code = sourceValue->sourceCodeForEvaluation(); rab.location = sourceValue->location(); ruleArtifact->bindings += rab; } else { QBS_ASSERT(!"unexpected value type", continue); } } } void ProjectResolver::resolveFileTagger(Item *item, ProjectContext *projectContext) { checkCancelation(); QList &fileTaggers = m_productContext ? m_productContext->product->fileTaggers : projectContext->fileTaggers; const QStringList patterns = m_evaluator->stringListValue(item, QLatin1String("patterns")); if (patterns.isEmpty()) throw ErrorInfo(Tr::tr("FileTagger.patterns must be a non-empty list."), item->location()); const FileTags fileTags = m_evaluator->fileTagsValue(item, QLatin1String("fileTags")); if (fileTags.isEmpty()) throw ErrorInfo(Tr::tr("FileTagger.fileTags must not be empty."), item->location()); foreach (const QString &pattern, patterns) { if (pattern.isEmpty()) throw ErrorInfo(Tr::tr("A FileTagger pattern must not be empty."), item->location()); } fileTaggers += FileTagger::create(patterns, fileTags); } void ProjectResolver::resolveTransformer(Item *item, ProjectContext *projectContext) { checkCancelation(); if (!m_evaluator->boolValue(item, QLatin1String("condition"))) { m_logger.qbsTrace() << "[PR] transformer condition is false"; return; } ResolvedTransformerPtr rtrafo = ResolvedTransformer::create(); rtrafo->module = m_moduleContext ? m_moduleContext->module : projectContext->dummyModule; rtrafo->inputs = m_evaluator->stringListValue(item, QLatin1String("inputs")); for (int i = 0; i < rtrafo->inputs.count(); ++i) rtrafo->inputs[i] = FileInfo::resolvePath(m_productContext->product->sourceDirectory, rtrafo->inputs.at(i)); rtrafo->transform = scriptFunctionValue(item, QLatin1String("prepare")); rtrafo->explicitlyDependsOn = m_evaluator->fileTagsValue(item, QLatin1String("explicitlyDependsOn")); foreach (const Item *child, item->children()) { if (Q_UNLIKELY(child->typeName() != QLatin1String("Artifact"))) throw ErrorInfo(Tr::tr("Transformer: wrong child type '%0'.").arg(child->typeName())); SourceArtifactPtr artifact = SourceArtifactInternal::create(); artifact->properties = m_productContext->product->moduleProperties; QString filePath = m_evaluator->stringValue(child, QLatin1String("filePath")); if (Q_UNLIKELY(filePath.isEmpty())) throw ErrorInfo(Tr::tr("Artifact.filePath must not be empty.")); artifact->absoluteFilePath = FileInfo::resolvePath(m_productContext->buildDirectory, filePath); artifact->fileTags = m_evaluator->fileTagsValue(child, QLatin1String("fileTags")); if (artifact->fileTags.isEmpty()) artifact->fileTags.insert(unknownFileTag()); rtrafo->outputs += artifact; } m_productContext->product->transformers += rtrafo; } void ProjectResolver::resolveScanner(Item *item, ProjectResolver::ProjectContext *projectContext) { checkCancelation(); if (!m_evaluator->boolValue(item, QLatin1String("condition"))) { m_logger.qbsTrace() << "[PR] scanner condition is false"; return; } ResolvedScannerPtr scanner = ResolvedScanner::create(); scanner->module = m_moduleContext ? m_moduleContext->module : projectContext->dummyModule; scanner->inputs = m_evaluator->fileTagsValue(item, QLatin1String("inputs")); scanner->recursive = m_evaluator->boolValue(item, QLatin1String("recursive")); scanner->searchPathsScript = scriptFunctionValue(item, QLatin1String("searchPaths")); scanner->scanScript = scriptFunctionValue(item, QLatin1String("scan")); m_productContext->product->scanners += scanner; } QList ProjectResolver::getProductDependencies(const ResolvedProductConstPtr &product, ModuleLoaderResult::ProductInfo *productInfo) { QList usedProducts; for (int i = productInfo->usedProducts.count() - 1; i >= 0; --i) { const ModuleLoaderResult::ProductInfo::Dependency &dependency = productInfo->usedProducts.at(i); QBS_CHECK(dependency.name.isEmpty() != dependency.productTypes.isEmpty()); if (!dependency.productTypes.isEmpty()) { foreach (const QString &tag, dependency.productTypes) { const QList productsForTag = m_productsByType.value(tag); foreach (const ResolvedProductPtr &p, productsForTag) { if (p == product || !p->enabled || (dependency.limitToSubProject && !product->isInParentProject(p))) { continue; } usedProducts << p; ModuleLoaderResult::ProductInfo::Dependency newDependency; newDependency.name = p->name; newDependency.profile = p->profile; productInfo->usedProducts << newDependency; } } productInfo->usedProducts.removeAt(i); } else if (dependency.profile == QLatin1String("*")) { foreach (const ResolvedProductPtr &p, m_productsByName) { if (p->name != dependency.name || p == product || !p->enabled || (dependency.limitToSubProject && !product->isInParentProject(p))) { continue; } usedProducts << p; ModuleLoaderResult::ProductInfo::Dependency newDependency; newDependency.name = p->name; newDependency.profile = p->profile; productInfo->usedProducts << newDependency; } productInfo->usedProducts.removeAt(i); } else { const ResolvedProductPtr &usedProduct = m_productsByName.value(dependency.uniqueName()); QBS_ASSERT(usedProduct, continue); usedProducts << usedProduct; } } return usedProducts; } void ProjectResolver::matchArtifactProperties(const ResolvedProductPtr &product, const QList &artifacts) { foreach (const SourceArtifactPtr &artifact, artifacts) { foreach (const ArtifactPropertiesConstPtr &artifactProperties, product->artifactProperties) { if (artifact->fileTags.matches(artifactProperties->fileTagsFilter())) artifact->properties = artifactProperties->propertyMap(); } } } static bool hasDependencyCycle(QSet *checked, QSet *branch, const ResolvedProductPtr &product, ErrorInfo *error) { if (branch->contains(product.data())) return true; if (checked->contains(product.data())) return false; checked->insert(product.data()); branch->insert(product.data()); foreach (const ResolvedProductPtr &dep, product->dependencies) { if (hasDependencyCycle(checked, branch, dep, error)) { error->prepend(dep->name, dep->location); return true; } } branch->remove(product.data()); return false; } void ProjectResolver::resolveProductDependencies(ProjectContext *projectContext) { // Resolve all inter-product dependencies. QList allProducts = projectContext->project->allProducts(); foreach (const ResolvedProductPtr &rproduct, allProducts) { if (!rproduct->enabled) continue; Item *productItem = m_productItemMap.value(rproduct); ModuleLoaderResult::ProductInfo &productInfo = projectContext->loadResult->productInfos[productItem]; foreach (const ResolvedProductPtr &usedProduct, getProductDependencies(rproduct, &productInfo)) { rproduct->dependencies.insert(usedProduct); } } // Check for cyclic dependencies. QSet checked; foreach (const ResolvedProductPtr &rproduct, allProducts) { QSet branch; ErrorInfo error; if (hasDependencyCycle(&checked, &branch, rproduct, &error)) { error.prepend(rproduct->name, rproduct->location); error.prepend(Tr::tr("Cyclic dependencies detected.")); throw error; } } } void ProjectResolver::postProcess(const ResolvedProductPtr &product, ProjectContext *projectContext) const { product->fileTaggers += projectContext->fileTaggers; foreach (const RulePtr &rule, projectContext->rules) product->rules += rule; } void ProjectResolver::applyFileTaggers(const ResolvedProductPtr &product) const { foreach (const SourceArtifactPtr &artifact, product->allEnabledFiles()) applyFileTaggers(artifact, product, m_logger); } void ProjectResolver::applyFileTaggers(const SourceArtifactPtr &artifact, const ResolvedProductConstPtr &product, const Logger &logger) { if (!artifact->overrideFileTags || artifact->fileTags.isEmpty()) { const QString fileName = FileInfo::fileName(artifact->absoluteFilePath); const FileTags fileTags = product->fileTagsForFileName(fileName); artifact->fileTags.unite(fileTags); if (artifact->fileTags.isEmpty()) artifact->fileTags.insert(unknownFileTag()); if (logger.traceEnabled()) logger.qbsTrace() << "[PR] adding file tags " << artifact->fileTags << " to " << fileName; } } QVariantMap ProjectResolver::evaluateModuleValues(Item *item, bool lookupPrototype) const { QVariantMap moduleValues; foreach (const Item::Module &module, item->modules()) { const QString fullName = module.name.toString(); moduleValues[fullName] = evaluateProperties(module.item, lookupPrototype); } QVariantMap result; result[QLatin1String("modules")] = moduleValues; return result; } QVariantMap ProjectResolver::evaluateProperties(Item *item, bool lookupPrototype) const { const QVariantMap tmplt; return evaluateProperties(item, item, tmplt, lookupPrototype); } QVariantMap ProjectResolver::evaluateProperties(Item *item, Item *propertiesContainer, const QVariantMap &tmplt, bool lookupPrototype) const { QVariantMap result = tmplt; for (QMap::const_iterator it = propertiesContainer->properties().begin(); it != propertiesContainer->properties().end(); ++it) { checkCancelation(); switch (it.value()->type()) { case Value::ItemValueType: { // Ignore items. Those point to module instances // and are handled in evaluateModuleValues(). break; } case Value::JSSourceValueType: { if (result.contains(it.key())) break; const PropertyDeclaration pd = item->propertyDeclaration(it.key()); if (pd.type() == PropertyDeclaration::Verbatim || pd.flags().testFlag(PropertyDeclaration::PropertyNotAvailableInConfig)) { break; } const QScriptValue scriptValue = m_evaluator->property(item, it.key()); if (Q_UNLIKELY(m_evaluator->engine()->hasErrorOrException(scriptValue))) { throw ErrorInfo(m_evaluator->engine()->lastErrorString(scriptValue), it.value()->location()); } // NOTE: Loses type information if scriptValue.isUndefined == true, // as such QScriptValues become invalid QVariants. QVariant v = scriptValue.toVariant(); if (pd.type() == PropertyDeclaration::Path) v = convertPathProperty(v.toString(), m_productContext->product->sourceDirectory); else if (pd.type() == PropertyDeclaration::PathList) v = convertPathListProperty(v.toStringList(), m_productContext->product->sourceDirectory); else if (pd.type() == PropertyDeclaration::StringList) v = v.toStringList(); result[it.key()] = v; break; } case Value::VariantValueType: { if (result.contains(it.key())) break; VariantValuePtr vvp = it.value().staticCast(); result[it.key()] = vvp->value(); break; } case Value::BuiltinValueType: // ignore break; } } return lookupPrototype && propertiesContainer->prototype() ? evaluateProperties(item, propertiesContainer->prototype(), result, true) : result; } QVariantMap ProjectResolver::createProductConfig() const { foreach (const Item::Module &module, m_productContext->item->modules()) { ModuleMerger merger(m_logger, m_productContext->item, module.item, module.name); merger.start(); } m_evaluator->setCachingEnabled(true); QVariantMap cfg = evaluateModuleValues(m_productContext->item); cfg = evaluateProperties(m_productContext->item, m_productContext->item, cfg); m_evaluator->setCachingEnabled(false); return cfg; } QString ProjectResolver::convertPathProperty(const QString &path, const QString &dirPath) const { return path.isEmpty() ? path : QDir::cleanPath(FileInfo::resolvePath(dirPath, path)); } QStringList ProjectResolver::convertPathListProperty(const QStringList &paths, const QString &dirPath) const { QStringList result; foreach (const QString &path, paths) result += convertPathProperty(path, dirPath); return result; } void ProjectResolver::callItemFunction(const ItemFuncMap &mappings, Item *item, ProjectContext *projectContext) { const QByteArray typeName = item->typeName().toLocal8Bit(); ItemFuncPtr f = mappings.value(typeName); QBS_CHECK(f); if (typeName == "Project") { ProjectContext subProjectContext = createProjectContext(projectContext); (this->*f)(item, &subProjectContext); } else { (this->*f)(item, projectContext); } } ProjectResolver::ProjectContext ProjectResolver::createProjectContext(ProjectContext *parentProjectContext) const { ProjectContext subProjectContext; subProjectContext.project = ResolvedProject::create(); parentProjectContext->project->subProjects += subProjectContext.project; subProjectContext.project->parentProject = parentProjectContext->project; subProjectContext.loadResult = parentProjectContext->loadResult; return subProjectContext; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/projectresolver.h000066400000000000000000000156401266132464200232470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef PROJECTRESOLVER_H #define PROJECTRESOLVER_H #include "filetags.h" #include "moduleloader.h" #include #include #include #include namespace qbs { namespace Internal { class Evaluator; class Item; class ProgressObserver; class ScriptEngine; class QualifiedIdSet; class ProjectResolver { public: ProjectResolver(ModuleLoader *ldr, const Logger &logger); ~ProjectResolver(); void setProgressObserver(ProgressObserver *observer); TopLevelProjectPtr resolve(ModuleLoaderResult &loadResult, const SetupProjectParameters &setupParameters); static void applyFileTaggers(const SourceArtifactPtr &artifact, const ResolvedProductConstPtr &product, const Logger &logger); static SourceArtifactPtr createSourceArtifact(const ResolvedProductConstPtr &rproduct, const PropertyMapPtr &properties, const QString &fileName, const FileTags &fileTags, bool overrideTags, QList &artifactList); private: struct ProjectContext { ResolvedProjectPtr project; QList fileTaggers; ModuleLoaderResult *loadResult; QList rules; ResolvedModulePtr dummyModule; }; struct ProductContext { ResolvedProductPtr product; QString buildDirectory; FileTags additionalFileTags; Item *item; typedef QPair ArtifactPropertiesInfo; QHash artifactPropertiesPerFilter; QHash sourceArtifactLocations; }; struct ModuleContext { ResolvedModulePtr module; }; void checkCancelation() const; QString verbatimValue(const ValueConstPtr &value, bool *propertyWasSet = 0) const; QString verbatimValue(Item *item, const QString &name, bool *propertyWasSet = 0) const; ScriptFunctionPtr scriptFunctionValue(Item *item, const QString &name) const; ResolvedFileContextPtr resolvedFileContext(const FileContextConstPtr &ctx) const; void ignoreItem(Item *item, ProjectContext *projectContext); void resolveTopLevelProject(Item *item, ProjectContext *projectContext); void resolveProject(Item *item, ProjectContext *projectContext); void resolveSubProject(Item *item, ProjectContext *projectContext); void resolveProduct(Item *item, ProjectContext *projectContext); void resolveModules(const Item *item, ProjectContext *projectContext); void resolveModule(const QualifiedId &moduleName, Item *item, bool isProduct, ProjectContext *projectContext); void resolveGroup(Item *item, ProjectContext *projectContext); void resolveRule(Item *item, ProjectContext *projectContext); void resolveRuleArtifact(const RulePtr &rule, Item *item); static void resolveRuleArtifactBinding(const RuleArtifactPtr &ruleArtifact, Item *item, const QStringList &namePrefix, QualifiedIdSet *seenBindings); void resolveFileTagger(Item *item, ProjectContext *projectContext); void resolveTransformer(Item *item, ProjectContext *projectContext); void resolveScanner(Item *item, ProjectContext *projectContext); void resolveProductDependencies(ProjectContext *projectContext); void postProcess(const ResolvedProductPtr &product, ProjectContext *projectContext) const; void applyFileTaggers(const ResolvedProductPtr &product) const; QVariantMap evaluateModuleValues(Item *item, bool lookupPrototype = true) const; struct EvalResult { EvalResult(const QVariant &v, bool s) : value(v), strongPrecedence(s) {} EvalResult() : strongPrecedence(false) {} QVariant value; bool strongPrecedence; }; QVariantMap evaluateProperties(Item *item, bool lookupPrototype = true) const; QVariantMap evaluateProperties(Item *item, Item *propertiesContainer, const QVariantMap &tmplt, bool lookupPrototype = true) const; QVariantMap createProductConfig() const; QString convertPathProperty(const QString &path, const QString &dirPath) const; QStringList convertPathListProperty(const QStringList &paths, const QString &dirPath) const; ProjectContext createProjectContext(ProjectContext *parentProjectContext) const; QList getProductDependencies(const ResolvedProductConstPtr &product, ModuleLoaderResult::ProductInfo *productInfo); static void matchArtifactProperties(const ResolvedProductPtr &product, const QList &artifacts); Evaluator *m_evaluator; Logger m_logger; ScriptEngine *m_engine; ProgressObserver *m_progressObserver; ProductContext *m_productContext; ModuleContext *m_moduleContext; QMap m_productsByName; QHash > m_productsByType; QHash m_productItemMap; mutable QHash m_fileContextMap; SetupProjectParameters m_setupParams; typedef void (ProjectResolver::*ItemFuncPtr)(Item *item, ProjectContext *projectContext); typedef QMap ItemFuncMap; void callItemFunction(const ItemFuncMap &mappings, Item *item, ProjectContext *projectContext); }; } // namespace Internal } // namespace qbs #endif // PROJECTRESOLVER_H qbs-src-1.4.5/src/lib/corelib/language/property.h000066400000000000000000000046631266132464200217060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROPERTY_H #define QBS_PROPERTY_H #include #include #include namespace qbs { namespace Internal { class Property { public: enum Kind { PropertyInModule, PropertyInProduct, PropertyInProject }; Property() : kind(PropertyInModule) { } Property(const QString &m, const QString &p, const QVariant &v, Kind k = PropertyInModule) : moduleName(m), propertyName(p), value(v), kind(k) { } QString moduleName; QString propertyName; QVariant value; Kind kind; }; inline bool operator==(const Property &p1, const Property &p2) { return p1.moduleName == p2.moduleName && p1.propertyName == p2.propertyName; } inline uint qHash(const Property &p) { return QT_PREPEND_NAMESPACE(qHash)(p.moduleName + p.propertyName); } typedef QSet PropertySet; } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-1.4.5/src/lib/corelib/language/propertydeclaration.cpp000066400000000000000000000125021266132464200244360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "propertydeclaration.h" #include "deprecationinfo.h" #include #include #include namespace qbs { namespace Internal { class PropertyDeclarationData : public QSharedData { public: PropertyDeclarationData() : type(PropertyDeclaration::UnknownType) , flags(PropertyDeclaration::DefaultFlags) { } QString name; PropertyDeclaration::Type type; PropertyDeclaration::Flags flags; QScriptValue allowedValues; QString description; QString initialValueSource; QStringList functionArgumentNames; DeprecationInfo deprecationInfo; }; PropertyDeclaration::PropertyDeclaration() : d(new PropertyDeclarationData) { } PropertyDeclaration::PropertyDeclaration(const QString &name, Type type, Flags flags) : d(new PropertyDeclarationData) { d->name = name; d->type = type; d->flags = flags; } PropertyDeclaration::PropertyDeclaration(const PropertyDeclaration &other) : d(other.d) { } PropertyDeclaration::~PropertyDeclaration() { } PropertyDeclaration &PropertyDeclaration::operator=(const PropertyDeclaration &other) { d = other.d; return *this; } bool PropertyDeclaration::isValid() const { return d && d->type != UnknownType; } bool PropertyDeclaration::isScalar() const { // ### Should be determined by a PropertyOption in the future. return d->type != PathList && d->type != StringList; } PropertyDeclaration::Type PropertyDeclaration::propertyTypeFromString(const QString &typeName) { if (typeName == QLatin1String("bool")) return PropertyDeclaration::Boolean; if (typeName == QLatin1String("int")) return PropertyDeclaration::Integer; if (typeName == QLatin1String("path")) return PropertyDeclaration::Path; if (typeName == QLatin1String("pathList")) return PropertyDeclaration::PathList; if (typeName == QLatin1String("string")) return PropertyDeclaration::String; if (typeName == QLatin1String("stringList")) return PropertyDeclaration::StringList; if (typeName == QLatin1String("var") || typeName == QLatin1String("variant")) return PropertyDeclaration::Variant; return PropertyDeclaration::UnknownType; } const QString &PropertyDeclaration::name() const { return d->name; } void PropertyDeclaration::setName(const QString &name) { d->name = name; } PropertyDeclaration::Type PropertyDeclaration::type() const { return d->type; } void PropertyDeclaration::setType(PropertyDeclaration::Type t) { d->type = t; } PropertyDeclaration::Flags PropertyDeclaration::flags() const { return d->flags; } void PropertyDeclaration::setFlags(Flags f) { d->flags = f; } const QScriptValue &PropertyDeclaration::allowedValues() const { return d->allowedValues; } void PropertyDeclaration::setAllowedValues(const QScriptValue &v) { d->allowedValues = v; } const QString &PropertyDeclaration::description() const { return d->description; } void PropertyDeclaration::setDescripton(const QString &str) { d->description = str; } const QString &PropertyDeclaration::initialValueSource() const { return d->initialValueSource; } void PropertyDeclaration::setInitialValueSource(const QString &str) { d->initialValueSource = str; } const QStringList &PropertyDeclaration::functionArgumentNames() const { return d->functionArgumentNames; } void PropertyDeclaration::setFunctionArgumentNames(const QStringList &lst) { d->functionArgumentNames = lst; } bool PropertyDeclaration::isDeprecated() const { return d->deprecationInfo.isValid(); } const DeprecationInfo &PropertyDeclaration::deprecationInfo() const { return d->deprecationInfo; } void PropertyDeclaration::setDeprecationInfo(const DeprecationInfo &deprecationInfo) { d->deprecationInfo = deprecationInfo; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/propertydeclaration.h000066400000000000000000000067041266132464200241120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROPERTYDECLARATION_H #define QBS_PROPERTYDECLARATION_H #include QT_BEGIN_NAMESPACE class QScriptValue; class QString; class QStringList; QT_END_NAMESPACE namespace qbs { namespace Internal { class DeprecationInfo; class PropertyDeclarationData; class PropertyDeclaration { public: enum Type { UnknownType, Boolean, Integer, Path, PathList, String, StringList, Variant, Verbatim }; enum Flag { DefaultFlags = 0, ListProperty = 0x1, PropertyNotAvailableInConfig = 0x2 // Is this property part of a project, product or file configuration? }; Q_DECLARE_FLAGS(Flags, Flag) PropertyDeclaration(); PropertyDeclaration(const QString &name, Type type, Flags flags = DefaultFlags); PropertyDeclaration(const PropertyDeclaration &other); ~PropertyDeclaration(); PropertyDeclaration &operator=(const PropertyDeclaration &other); bool isValid() const; bool isScalar() const; static Type propertyTypeFromString(const QString &typeName); const QString &name() const; void setName(const QString &name); Type type() const; void setType(Type t); Flags flags() const; void setFlags(Flags f); const QScriptValue &allowedValues() const; void setAllowedValues(const QScriptValue &v); const QString &description() const; void setDescripton(const QString &str); const QString &initialValueSource() const; void setInitialValueSource(const QString &str); const QStringList &functionArgumentNames() const; void setFunctionArgumentNames(const QStringList &lst); bool isDeprecated() const; const DeprecationInfo &deprecationInfo() const; void setDeprecationInfo(const DeprecationInfo &deprecationInfo); private: QSharedDataPointer d; }; } // namespace Internal } // namespace qbs #endif // QBS_PROPERTYDECLARATION_H qbs-src-1.4.5/src/lib/corelib/language/propertymapinternal.cpp000066400000000000000000000072511266132464200244700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "propertymapinternal.h" #include #include #include namespace qbs { namespace Internal { /*! * \class PropertyMapInternal * \brief The \c PropertyMapInternal class contains a set of properties and their values. * An instance of this class is attached to every \c ResolvedProduct. * \c ResolvedGroups inherit their properties from the respective \c ResolvedProduct, \c SourceArtifacts * inherit theirs from the respective \c ResolvedGroup. \c ResolvedGroups can override the value of an * inherited property, \c SourceArtifacts cannot. If a property value is overridden, a new * \c PropertyMapInternal object is allocated, otherwise the pointer is shared. * \sa ResolvedGroup * \sa ResolvedProduct * \sa SourceArtifact */ PropertyMapInternal::PropertyMapInternal() { } PropertyMapInternal::PropertyMapInternal(const PropertyMapInternal &other) : PersistentObject(other), m_value(other.m_value) { } QVariant PropertyMapInternal::qbsPropertyValue(const QString &key) const { return PropertyFinder().propertyValue(value(), QLatin1String("qbs"), key); } void PropertyMapInternal::setValue(const QVariantMap &map) { m_value = map; } static QString toJSLiteral_impl(const QVariantMap &vm, int level = 0) { QString indent; for (int i = 0; i < level; ++i) indent += QLatin1String(" "); QString str; for (QVariantMap::const_iterator it = vm.begin(); it != vm.end(); ++it) { if (it.value().type() == QVariant::Map) { str += indent + it.key() + QLatin1String(": {\n"); str += toJSLiteral_impl(it.value().toMap(), level + 1); str += indent + QLatin1String("}\n"); } else { str += indent + it.key() + QLatin1String(": ") + toJSLiteral(it.value()) + QLatin1Char('\n'); } } return str; } QString PropertyMapInternal::toJSLiteral() const { return toJSLiteral_impl(m_value); } void PropertyMapInternal::load(PersistentPool &pool) { m_value = pool.loadVariantMap(); } void PropertyMapInternal::store(PersistentPool &pool) const { pool.store(m_value); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/propertymapinternal.h000066400000000000000000000046331266132464200241360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROPERTYMAPINTERNAL_H #define QBS_PROPERTYMAPINTERNAL_H #include "forward_decls.h" #include #include namespace qbs { namespace Internal { class PropertyMapInternal : public PersistentObject { public: static PropertyMapPtr create() { return PropertyMapPtr(new PropertyMapInternal); } PropertyMapPtr clone() const { return PropertyMapPtr(new PropertyMapInternal(*this)); } const QVariantMap &value() const { return m_value; } QVariant qbsPropertyValue(const QString &key) const; // Convenience function. void setValue(const QVariantMap &value); QString toJSLiteral() const; private: PropertyMapInternal(); PropertyMapInternal(const PropertyMapInternal &other); void load(PersistentPool &); void store(PersistentPool &) const; QVariantMap m_value; }; } // namespace Internal } // namespace qbs #endif // QBS_PROPERTYMAPINTERNAL_H qbs-src-1.4.5/src/lib/corelib/language/qualifiedid.cpp000066400000000000000000000044641266132464200226340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "qualifiedid.h" namespace qbs { namespace Internal { QualifiedId::QualifiedId() { } QualifiedId::QualifiedId(const QString &singlePartName) : QStringList(singlePartName) { } QualifiedId::QualifiedId(const QStringList &nameParts) : QStringList(nameParts) { } QualifiedId QualifiedId::fromString(const QString &str) { return QualifiedId(str.split(QLatin1Char('.'))); } QString QualifiedId::toString() const { return join(QLatin1Char('.')); } bool operator<(const QualifiedId &a, const QualifiedId &b) { const int c = qMin(a.count(), b.count()); for (int i = 0; i < c; ++i) { int n = a.at(i).compare(b.at(i)); if (n < 0) return true; if (n > 0) return false; } return a.count() < b.count(); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/qualifiedid.h000066400000000000000000000037531266132464200223010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_QUALIFIEDID_H #define QBS_QUALIFIEDID_H #include namespace qbs { namespace Internal { class QualifiedId : public QStringList { public: QualifiedId(); QualifiedId(const QString &singlePartName); QualifiedId(const QStringList &nameParts); static QualifiedId fromString(const QString &str); QString toString() const; }; bool operator<(const QualifiedId &a, const QualifiedId &b); } // namespace Internal } // namespace qbs #endif // QBS_QUALIFIEDID_H qbs-src-1.4.5/src/lib/corelib/language/resolvedfilecontext.cpp000066400000000000000000000055231266132464200244410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "resolvedfilecontext.h" #include "jsimports.h" #include namespace qbs { namespace Internal { ResolvedFileContext::ResolvedFileContext(const FileContextBase &ctx) : FileContextBase(ctx) { } void ResolvedFileContext::load(PersistentPool &pool) { m_filePath = pool.idLoadString(); m_jsExtensions = pool.idLoadStringList(); m_searchPaths = pool.idLoadStringList(); int count; pool.stream() >> count; for (int i = 0; i < count; ++i) { JsImport jsi; jsi.scopeName = pool.idLoadString(); jsi.filePaths = pool.idLoadStringList(); jsi.location.load(pool); m_jsImports << jsi; } } void ResolvedFileContext::store(PersistentPool &pool) const { pool.storeString(m_filePath); pool.storeStringList(m_jsExtensions); pool.storeStringList(m_searchPaths); pool.stream() << m_jsImports.count(); foreach (const JsImport &jsi, m_jsImports) { pool.storeString(jsi.scopeName); pool.storeStringList(jsi.filePaths); jsi.location.store(pool); } } bool operator==(const ResolvedFileContext &a, const ResolvedFileContext &b) { return a.filePath() == b.filePath() && a.jsExtensions().toSet() == b.jsExtensions().toSet() && a.jsImports().toSet() == b.jsImports().toSet(); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/resolvedfilecontext.h000066400000000000000000000047541266132464200241130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_RESOLVEDFILECONTEXT_H #define QBS_RESOLVEDFILECONTEXT_H #include "forward_decls.h" #include "filecontextbase.h" #include namespace qbs { namespace Internal { class ResolvedFileContext : public FileContextBase, public PersistentObject { public: static ResolvedFileContextPtr create() { return ResolvedFileContextPtr(new ResolvedFileContext); } static ResolvedFileContextPtr create(const FileContextBase &baseContext) { return ResolvedFileContextPtr(new ResolvedFileContext(baseContext)); } private: ResolvedFileContext() {} ResolvedFileContext(const FileContextBase &ctx); void load(PersistentPool &pool); void store(PersistentPool &pool) const; }; bool operator==(const ResolvedFileContext &a, const ResolvedFileContext &b); inline bool operator!=(const ResolvedFileContext &a, const ResolvedFileContext &b) { return !(a == b); } } // namespace Internal } // namespace qbs #endif // QBS_RESOLVEDFILECONTEXT_H qbs-src-1.4.5/src/lib/corelib/language/scriptengine.cpp000066400000000000000000000522651266132464200230500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "scriptengine.h" #include "evaluatorscriptclass.h" #include "filecontextbase.h" #include "jsimports.h" #include "propertymapinternal.h" #include "scriptpropertyobserver.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { const bool debugJSImports = false; bool operator==(const ScriptEngine::PropertyCacheKey &lhs, const ScriptEngine::PropertyCacheKey &rhs) { return lhs.m_oneValue == rhs.m_oneValue && lhs.m_propertyMap == rhs.m_propertyMap && lhs.m_moduleName == rhs.m_moduleName && lhs.m_propertyName == rhs.m_propertyName; } static inline uint combineHash(uint h1, uint h2, uint seed) { // stolen from qHash(QPair) return ((h1 << 16) | (h1 >> 16)) ^ h2 ^ seed; } uint qHash(const ScriptEngine::PropertyCacheKey &k, uint seed = 0) { return combineHash(qHash(k.m_moduleName), combineHash(qHash(k.m_propertyName), combineHash(qHash(k.m_oneValue), qHash(k.m_propertyMap), seed), seed), seed); } ScriptEngine::ScriptEngine(const Logger &logger, QObject *parent) : QScriptEngine(parent), m_propertyCacheEnabled(true), m_logger(logger) { setProcessEventsInterval(1000); // For the cancelation mechanism to work. m_cancelationError = currentContext()->throwValue(tr("Execution canceled")); QScriptValue objectProto = globalObject().property(QLatin1String("Object")); m_definePropertyFunction = objectProto.property(QLatin1String("defineProperty")); QBS_ASSERT(m_definePropertyFunction.isFunction(), /* ignore */); m_emptyFunction = evaluate(QLatin1String("(function(){})")); QBS_ASSERT(m_emptyFunction.isFunction(), /* ignore */); // Initially push a new context to turn off scope chain insanity mode. QScriptEngine::pushContext(); installQbsBuiltins(); extendJavaScriptBuiltins(); } ScriptEngine::~ScriptEngine() { qDeleteAll(m_ownedVariantMaps); } void ScriptEngine::import(const FileContextBaseConstPtr &fileCtx, QScriptValue scope, QScriptValue targetObject) { installImportFunctions(); m_currentDirPathStack.push(FileInfo::path(fileCtx->filePath())); m_extensionSearchPathsStack.push(fileCtx->searchPaths()); const JsImports jsImports = fileCtx->jsImports(); for (JsImports::const_iterator it = jsImports.begin(); it != jsImports.end(); ++it) { import(*it, scope, targetObject); } m_currentDirPathStack.pop(); m_extensionSearchPathsStack.pop(); uninstallImportFunctions(); } void ScriptEngine::import(const JsImport &jsImport, QScriptValue scope, QScriptValue targetObject) { QBS_ASSERT(!scope.isValid() || scope.isObject(), return); QBS_ASSERT(targetObject.isObject(), return); QBS_ASSERT(targetObject.engine() == this, return); if (debugJSImports) qDebug() << "[ENGINE] import into " << jsImport.scopeName; QScriptValue jsImportValue = m_jsImportCache.value(jsImport); if (jsImportValue.isValid()) { if (debugJSImports) qDebug() << "[ENGINE] " << jsImport.filePaths << " (cache hit)"; } else { if (debugJSImports) qDebug() << "[ENGINE] " << jsImport.filePaths << " (cache miss)"; foreach (const QString &filePath, jsImport.filePaths) importFile(filePath, scope, &jsImportValue); m_jsImportCache.insert(jsImport, jsImportValue); } targetObject.setProperty(jsImport.scopeName, jsImportValue); } void ScriptEngine::clearImportsCache() { m_jsImportCache.clear(); } void ScriptEngine::addPropertyRequestedFromArtifact(const Artifact *artifact, const Property &property) { m_propertiesRequestedFromArtifact[artifact->filePath()] << property; } void ScriptEngine::addToPropertyCache(const QString &moduleName, const QString &propertyName, bool oneValue, const PropertyMapConstPtr &propertyMap, const QVariant &value) { m_propertyCache.insert(PropertyCacheKey(moduleName, propertyName, oneValue, propertyMap), value); } QVariant ScriptEngine::retrieveFromPropertyCache(const QString &moduleName, const QString &propertyName, bool oneValue, const PropertyMapConstPtr &propertyMap) { return m_propertyCache.value(PropertyCacheKey(moduleName, propertyName, oneValue, propertyMap)); } void ScriptEngine::defineProperty(QScriptValue &object, const QString &name, const QScriptValue &descriptor) { QScriptValue arguments = newArray(); arguments.setProperty(0, object); arguments.setProperty(1, name); arguments.setProperty(2, descriptor); QScriptValue result = m_definePropertyFunction.call(QScriptValue(), arguments); QBS_ASSERT(!hasErrorOrException(result), qDebug() << name << result.toString()); } static QScriptValue js_observedGet(QScriptContext *context, QScriptEngine *, void *arg) { ScriptPropertyObserver * const observer = static_cast(arg); const QScriptValue data = context->callee().property(QLatin1String("qbsdata")); const QScriptValue value = data.property(2); observer->onPropertyRead(data.property(0), data.property(1).toVariant().toString(), value); return value; } void ScriptEngine::setObservedProperty(QScriptValue &object, const QString &name, const QScriptValue &value, ScriptPropertyObserver *observer) { if (!observer) { object.setProperty(name, value); return; } QScriptValue data = newArray(); data.setProperty(0, object); data.setProperty(1, name); data.setProperty(2, value); QScriptValue getterFunc = newFunction(js_observedGet, observer); getterFunc.setProperty(QLatin1String("qbsdata"), data); object.setProperty(name, getterFunc, QScriptValue::PropertyGetter); } static QScriptValue js_deprecatedGet(QScriptContext *context, QScriptEngine *qtengine) { ScriptEngine *engine = static_cast(qtengine); const QScriptValue data = context->callee().property(QLatin1String("qbsdata")); engine->logger().qbsWarning() << ScriptEngine::tr("Property %1 is deprecated. Please use %2 instead.").arg( data.property(0).toString(), data.property(1).toString()); return data.property(2); } void ScriptEngine::setDeprecatedProperty(QScriptValue &object, const QString &oldName, const QString &newName, const QScriptValue &value) { QScriptValue data = newArray(); data.setProperty(0, oldName); data.setProperty(1, newName); data.setProperty(2, value); QScriptValue getterFunc = newFunction(js_deprecatedGet); getterFunc.setProperty(QLatin1String("qbsdata"), data); object.setProperty(oldName, getterFunc, QScriptValue::PropertyGetter | QScriptValue::SkipInEnumeration); } QProcessEnvironment ScriptEngine::environment() const { return m_environment; } void ScriptEngine::setEnvironment(const QProcessEnvironment &env) { m_environment = env; } QScriptValue ScriptEngine::importFile(const QString &filePath, const QScriptValue &scope, QScriptValue *targetObject) { QFile file(filePath); if (Q_UNLIKELY(!file.open(QFile::ReadOnly))) throw ErrorInfo(tr("Cannot open '%1'.").arg(filePath)); const QString sourceCode = QTextStream(&file).readAll(); file.close(); QScriptProgram program(sourceCode, filePath); QScriptValue obj; if (!targetObject) obj = newObject(); m_currentDirPathStack.push(FileInfo::path(filePath)); importProgram(program, scope, targetObject ? *targetObject : obj); m_currentDirPathStack.pop(); return targetObject ? *targetObject : obj; } void ScriptEngine::importProgram(const QScriptProgram &program, const QScriptValue &scope, QScriptValue &targetObject) { QSet globalPropertyNames; { QScriptValueIterator it(globalObject()); while (it.hasNext()) { it.next(); globalPropertyNames += it.name(); } } pushContext(); if (scope.isObject()) currentContext()->pushScope(scope); QScriptValue result = evaluate(program); QScriptValue activationObject = currentContext()->activationObject(); if (scope.isObject()) currentContext()->popScope(); popContext(); if (Q_UNLIKELY(hasErrorOrException(result))) throw ErrorInfo(tr("Error when importing '%1': %2").arg(program.fileName(), result.toString())); // If targetObject is already an object, it doesn't get overwritten but enhanced by the // contents of the .js file. // This is necessary for library imports that consist of multiple js files. if (!targetObject.isObject()) targetObject = newObject(); // Copy every property of the activation object to the target object. // We do not just save a reference to the activation object, because QScriptEngine contains // special magic for activation objects that leads to unanticipated results. { QScriptValueIterator it(activationObject); while (it.hasNext()) { it.next(); if (debugJSImports) qDebug() << "[ENGINE] Copying property " << it.name(); targetObject.setProperty(it.name(), it.value()); } } // Copy new global properties to the target object and remove them from // the global object. This is to support direct variable assignments // without the 'var' keyword in JavaScript files. QScriptValueIterator it(globalObject()); while (it.hasNext()) { it.next(); if (globalPropertyNames.contains(it.name())) continue; if (debugJSImports) { qDebug() << "[ENGINE] inserting global property " << it.name() << " " << it.value().toString(); } targetObject.setProperty(it.name(), it.value()); it.remove(); } } static QString findExtensionDir(const QStringList &searchPaths, const QString &extensionPath) { foreach (const QString &searchPath, searchPaths) { const QString dirPath = searchPath + QStringLiteral("/imports/") + extensionPath; QFileInfo fi(dirPath); if (fi.exists() && fi.isDir()) return dirPath; } return QString(); } static QScriptValue mergeExtensionObjects(const QScriptValueList &lst) { QScriptValue result; foreach (const QScriptValue &v, lst) { if (!result.isValid()) { result = v; continue; } QScriptValueIterator svit(v); while (svit.hasNext()) { svit.next(); result.setProperty(svit.name(), svit.value()); } } return result; } static QScriptValue loadInternalExtension(QScriptContext *context, ScriptEngine *engine, const QString &uri) { const QString name = uri.mid(4); // remove the "qbs." part QScriptValue extensionObj = JsExtensions::loadExtension(engine, name); if (!extensionObj.isValid()) { return context->throwError(ScriptEngine::tr("loadExtension: " "cannot load extension '%1'.").arg(uri)); } return extensionObj; } QScriptValue ScriptEngine::js_loadExtension(QScriptContext *context, QScriptEngine *qtengine) { ScriptEngine *engine = static_cast(qtengine); if (context->argumentCount() < 1) { return context->throwError( ScriptEngine::tr("The loadExtension function requires " "an extension name.")); } if (engine->m_extensionSearchPathsStack.isEmpty()) return context->throwError( ScriptEngine::tr("loadExtension: internal error. No search paths.")); const QString uri = context->argument(0).toVariant().toString(); if (engine->m_logger.debugEnabled()) { engine->m_logger.qbsDebug() << "[loadExtension] loading extension " << uri; } QString uriAsPath = uri; uriAsPath.replace(QLatin1Char('.'), QLatin1Char('/')); const QStringList searchPaths = engine->m_extensionSearchPathsStack.top(); const QString dirPath = findExtensionDir(searchPaths, uriAsPath); if (dirPath.isEmpty()) { if (uri.startsWith(QLatin1String("qbs."))) return loadInternalExtension(context, engine, uri); return context->throwError( ScriptEngine::tr("loadExtension: Cannot find extension '%1'. " "Search paths: %2.").arg(uri, searchPaths.join( QLatin1String(", ")))); } QDirIterator dit(dirPath, QDir::Files | QDir::Readable); QScriptValueList values; try { while (dit.hasNext()) { const QString filePath = dit.next(); if (engine->m_logger.debugEnabled()) { engine->m_logger.qbsDebug() << "[loadExtension] importing file " << filePath; } values << engine->importFile(filePath, QScriptValue()); } } catch (const ErrorInfo &e) { return context->throwError(e.toString()); } return mergeExtensionObjects(values); } QScriptValue ScriptEngine::js_loadFile(QScriptContext *context, QScriptEngine *qtengine) { ScriptEngine *engine = static_cast(qtengine); if (context->argumentCount() < 1) { return context->throwError( ScriptEngine::tr("The loadFile function requires a file path.")); } if (engine->m_currentDirPathStack.isEmpty()) { return context->throwError( ScriptEngine::tr("loadFile: internal error. No current directory.")); } QScriptValue result; const QString relativeFilePath = context->argument(0).toVariant().toString(); try { const QString filePath = FileInfo::resolvePath(engine->m_currentDirPathStack.top(), relativeFilePath); result = engine->importFile(filePath, QScriptValue()); } catch (const ErrorInfo &e) { result = context->throwError(e.toString()); } return result; } void ScriptEngine::addEnvironmentVariable(const QString &name, const QString &value) { m_usedEnvironment.insert(name, value); } void ScriptEngine::addCanonicalFilePathResult(const QString &filePath, const QString &resultFilePath) { m_canonicalFilePathResult.insert(filePath, resultFilePath); } void ScriptEngine::addFileExistsResult(const QString &filePath, bool exists) { m_fileExistsResult.insert(filePath, exists); } void ScriptEngine::addFileLastModifiedResult(const QString &filePath, const FileTime &fileTime) { m_fileLastModifiedResult.insert(filePath, fileTime); } QSet ScriptEngine::imports() const { QSet filePaths; foreach (const JsImport &jsImport, m_jsImportCache.keys()) { foreach (const QString &filePath, jsImport.filePaths) filePaths << filePath; } return filePaths; } QScriptValueList ScriptEngine::argumentList(const QStringList &argumentNames, const QScriptValue &context) { QScriptValueList result; for (int i = 0; i < argumentNames.count(); ++i) result += context.property(argumentNames.at(i)); return result; } void ScriptEngine::cancel() { QMetaObject::invokeMethod(this, "abort", Qt::QueuedConnection); } void ScriptEngine::abort() { abortEvaluation(m_cancelationError); } class JSTypeExtender { public: JSTypeExtender(ScriptEngine *engine, const QString &typeName) : m_engine(engine) { m_proto = engine->globalObject().property(typeName) .property(QLatin1String("prototype")); QBS_ASSERT(m_proto.isObject(), return); m_descriptor = engine->newObject(); } void addFunction(const QString &name, const QString &code) { QScriptValue f = m_engine->evaluate(code); QBS_ASSERT(f.isFunction(), return); m_descriptor.setProperty(QLatin1String("value"), f); m_engine->defineProperty(m_proto, name, m_descriptor); } private: ScriptEngine *const m_engine; QScriptValue m_proto; QScriptValue m_descriptor; }; void ScriptEngine::installQbsBuiltins() { globalObject().setProperty(QLatin1String("qbs"), m_qbsObject = newObject()); installQbsFunction(QLatin1String("getNativeSetting"), EvaluatorScriptClass::js_getNativeSetting); installQbsFunction(QLatin1String("getEnv"), EvaluatorScriptClass::js_getEnv); installQbsFunction(QLatin1String("currentEnv"), EvaluatorScriptClass::js_currentEnv); installQbsFunction(QLatin1String("canonicalArchitecture"), EvaluatorScriptClass::js_canonicalArchitecture); installQbsFunction(QLatin1String("rfc1034Identifier"), EvaluatorScriptClass::js_rfc1034identifier); installQbsFunction(QLatin1String("getHash"), EvaluatorScriptClass::js_getHash); } void ScriptEngine::extendJavaScriptBuiltins() { JSTypeExtender arrayExtender(this, QLatin1String("Array")); arrayExtender.addFunction(QLatin1String("contains"), QLatin1String("(function(e){return this.indexOf(e) !== -1;})")); arrayExtender.addFunction(QLatin1String("uniqueConcat"), QLatin1String("(function(other){" "var r = this.concat();" "var s = {};" "r.forEach(function(x){ s[x] = true; });" "other.forEach(function(x){" "if (!s[x]) {" "s[x] = true;" "r.push(x);" "}" "});" "return r;})")); JSTypeExtender stringExtender(this, QLatin1String("String")); stringExtender.addFunction(QLatin1String("contains"), QLatin1String("(function(e){return this.indexOf(e) !== -1;})")); stringExtender.addFunction(QLatin1String("startsWith"), QLatin1String("(function(e){return this.slice(0, e.length) === e;})")); stringExtender.addFunction(QLatin1String("endsWith"), QLatin1String("(function(e){return this.slice(-e.length) === e;})")); } void ScriptEngine::installFunction(const QString &name, QScriptValue *functionValue, FunctionSignature f, QScriptValue *targetObject = 0) { if (!functionValue->isValid()) *functionValue = newFunction(f); (targetObject ? *targetObject : globalObject()).setProperty(name, *functionValue); } void ScriptEngine::installQbsFunction(const QString &name, FunctionSignature f) { QScriptValue functionValue; installFunction(name, &functionValue, f, &m_qbsObject); } void ScriptEngine::installImportFunctions() { installFunction(QLatin1String("loadFile"), &m_loadFileFunction, js_loadFile); installFunction(QLatin1String("loadExtension"), &m_loadExtensionFunction, js_loadExtension); } void ScriptEngine::uninstallImportFunctions() { globalObject().setProperty(QLatin1String("loadFile"), QScriptValue()); globalObject().setProperty(QLatin1String("loadExtension"), QScriptValue()); } ScriptEngine::PropertyCacheKey::PropertyCacheKey(const QString &moduleName, const QString &propertyName, bool oneValue, const PropertyMapConstPtr &propertyMap) : m_moduleName(moduleName), m_propertyName(propertyName), m_oneValue(oneValue), m_propertyMap(propertyMap) { } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/scriptengine.h000066400000000000000000000171671266132464200225170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_SCRIPTENGINE_H #define QBS_SCRIPTENGINE_H #include "forward_decls.h" #include "property.h" #include #include #include #include #include #include #include #include namespace qbs { namespace Internal { class Artifact; class JsImport; class ScriptPropertyObserver; class ScriptEngine : public QScriptEngine { Q_OBJECT public: ScriptEngine(const Logger &logger, QObject *parent = 0); ~ScriptEngine(); void setLogger(const Logger &logger) { m_logger = logger; } const Logger &logger() const { return m_logger; } void import(const FileContextBaseConstPtr &fileCtx, QScriptValue scope, QScriptValue targetObject); void import(const JsImport &jsImport, QScriptValue scope, QScriptValue targetObject); void clearImportsCache(); void addPropertyRequestedInScript(const Property &property) { m_propertiesRequestedInScript += property; } void addPropertyRequestedFromArtifact(const Artifact *artifact, const Property &property); void clearRequestedProperties() { m_propertiesRequestedInScript.clear(); m_propertiesRequestedFromArtifact.clear(); } PropertySet propertiesRequestedInScript() const { return m_propertiesRequestedInScript; } QHash propertiesRequestedFromArtifact() const { return m_propertiesRequestedFromArtifact; } void setPropertyCacheEnabled(bool enable) { m_propertyCacheEnabled = enable; } bool isPropertyCacheEnabled() const { return m_propertyCacheEnabled; } void addToPropertyCache(const QString &moduleName, const QString &propertyName, bool oneValue, const PropertyMapConstPtr &propertyMap, const QVariant &value); QVariant retrieveFromPropertyCache(const QString &moduleName, const QString &propertyName, bool oneValue, const PropertyMapConstPtr &propertyMap); void defineProperty(QScriptValue &object, const QString &name, const QScriptValue &descriptor); void setObservedProperty(QScriptValue &object, const QString &name, const QScriptValue &value, ScriptPropertyObserver *observer); void setDeprecatedProperty(QScriptValue &object, const QString &name, const QString &newName, const QScriptValue &value); QProcessEnvironment environment() const; void setEnvironment(const QProcessEnvironment &env); void addEnvironmentVariable(const QString &name, const QString &value); QHash usedEnvironment() const { return m_usedEnvironment; } void addCanonicalFilePathResult(const QString &filePath, const QString &resultFilePath); void addFileExistsResult(const QString &filePath, bool exists); void addFileLastModifiedResult(const QString &filePath, const FileTime &fileTime); QHash canonicalFilePathResults() const { return m_canonicalFilePathResult; } QHash fileExistsResults() const { return m_fileExistsResult; } QHash fileLastModifiedResults() const { return m_fileLastModifiedResult; } QSet imports() const; static QScriptValueList argumentList(const QStringList &argumentNames, const QScriptValue &context); void registerOwnedVariantMap(QVariantMap *vm) { m_ownedVariantMaps.append(vm); } bool hasErrorOrException(const QScriptValue &v) const { return v.isError() || hasUncaughtException(); } QScriptValue lastErrorValue(const QScriptValue &v) const { return v.isError() ? v : uncaughtException(); } QString lastErrorString(const QScriptValue &v) const { return lastErrorValue(v).toString(); } void cancel(); private: Q_INVOKABLE void abort(); void installQbsBuiltins(); void extendJavaScriptBuiltins(); void installFunction(const QString &name, QScriptValue *functionValue, FunctionSignature f, QScriptValue *targetObject); void installQbsFunction(const QString &name, FunctionSignature f); void installImportFunctions(); void uninstallImportFunctions(); QScriptValue importFile(const QString &filePath, const QScriptValue &scope, QScriptValue *targetObject = nullptr); void importProgram(const QScriptProgram &program, const QScriptValue &scope, QScriptValue &targetObject); static QScriptValue js_loadExtension(QScriptContext *context, QScriptEngine *qtengine); static QScriptValue js_loadFile(QScriptContext *context, QScriptEngine *qtengine); class PropertyCacheKey { public: PropertyCacheKey(const QString &moduleName, const QString &propertyName, bool oneValue, const PropertyMapConstPtr &propertyMap); private: const QString &m_moduleName; const QString &m_propertyName; const bool m_oneValue; const PropertyMapConstPtr &m_propertyMap; friend bool operator==(const PropertyCacheKey &lhs, const PropertyCacheKey &rhs); friend uint qHash(const ScriptEngine::PropertyCacheKey &k, uint seed); }; friend bool operator==(const PropertyCacheKey &lhs, const PropertyCacheKey &rhs); friend uint qHash(const ScriptEngine::PropertyCacheKey &k, uint seed); QHash m_jsImportCache; bool m_propertyCacheEnabled; QHash m_propertyCache; PropertySet m_propertiesRequestedInScript; QHash m_propertiesRequestedFromArtifact; Logger m_logger; QScriptValue m_definePropertyFunction; QScriptValue m_emptyFunction; QProcessEnvironment m_environment; QHash m_usedEnvironment; QHash m_canonicalFilePathResult; QHash m_fileExistsResult; QHash m_fileLastModifiedResult; QStack m_currentDirPathStack; QStack m_extensionSearchPathsStack; QScriptValue m_loadFileFunction; QScriptValue m_loadExtensionFunction; QScriptValue m_qbsObject; QScriptValue m_cancelationError; QList m_ownedVariantMaps; }; } // namespace Internal } // namespace qbs #endif // QBS_SCRIPTENGINE_H qbs-src-1.4.5/src/lib/corelib/language/scriptpropertyobserver.h000066400000000000000000000037231266132464200246770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_SCRIPTPROPERTYOBSERVER_H #define QBS_SCRIPTPROPERTYOBSERVER_H #include QT_BEGIN_NAMESPACE class QScriptValue; class QString; QT_END_NAMESPACE namespace qbs { namespace Internal { class ScriptPropertyObserver { public: virtual void onPropertyRead(const QScriptValue &object, const QString &name, const QScriptValue &value) = 0; }; } // namespace Internal } // namespace qbs #endif // QBS_SCRIPTPROPERTYOBSERVER_H qbs-src-1.4.5/src/lib/corelib/language/testdata/000077500000000000000000000000001266132464200214515ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/Banana000066400000000000000000000000321266132464200225470ustar00rootroot00000000000000Peanut butter jelly time! qbs-src-1.4.5/src/lib/corelib/language/testdata/aboutdialog.cpp000066400000000000000000000000001266132464200244350ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/baseproperty.qbs000066400000000000000000000002221266132464200246730ustar00rootroot00000000000000import "baseproperty_base.qbs" as BaseProduct BaseProduct { name: "product1" narf: base.concat(["boo"]) zort: base.concat(["boo"]) } qbs-src-1.4.5/src/lib/corelib/language/testdata/baseproperty_base.qbs000066400000000000000000000001011266132464200256610ustar00rootroot00000000000000Product { property var narf property var zort: ["bar"] } qbs-src-1.4.5/src/lib/corelib/language/testdata/buildconfigstringlistsyntax.qbs000066400000000000000000000000601266132464200300330ustar00rootroot00000000000000Project { property stringList someStrings } qbs-src-1.4.5/src/lib/corelib/language/testdata/builtinFunctionInSearchPathsProperty.qbs000066400000000000000000000002121266132464200315110ustar00rootroot00000000000000import qbs Project { qbsSearchPaths: { if (!qbs.getEnv("PATH")) throw "qbs.getEnv doesn't seem to work"; } } qbs-src-1.4.5/src/lib/corelib/language/testdata/canonicalArchitecture.qbs000066400000000000000000000000701266132464200264470ustar00rootroot00000000000000Product { name: qbs.canonicalArchitecture("i386") } qbs-src-1.4.5/src/lib/corelib/language/testdata/conditionaldepends.qbs000066400000000000000000000033271266132464200260330ustar00rootroot00000000000000import qbs 1.0 import "conditionaldepends_base.qbs" as CondBase Project { CondBase { name: 'conditionaldepends_derived' someProp: true } CondBase { name: 'conditionaldepends_derived_false' someProp: "knolf" === "narf" } Product { name: "product_props_true" property bool someTrueProp: true Depends { condition: someTrueProp; name: "dummy"} } Product { name: "product_props_false" property bool someFalseProp: false Depends { condition: someFalseProp; name: "dummy"} } property bool someTruePrjProp: true Product { name: "project_props_true" Depends { condition: project.someTruePrjProp; name: "dummy"} } property bool someFalsePrjProp: false Product { name: "project_props_false" Depends { condition: project.someFalsePrjProp; name: "dummy"} } Product { name: "module_props_true" Depends { name: "dummy2" } Depends { condition: dummy2.someTrueProp; name: "dummy" } } Product { name: "module_props_false" Depends { name: "dummy2" } Depends { condition: dummy2.someFalseProp; name: "dummy" } } Product { name: "contradictory_conditions1" Depends { condition: false; name: "dummy" } Depends { condition: true; name: "dummy" } // this one wins } Product { name: "contradictory_conditions2" Depends { condition: true; name: "dummy" } // this one wins Depends { condition: false; name: "dummy" } } Product { name: "unknown_dependency_condition_false" Depends { condition: false; name: "doesonlyexistifhellfreezesover" } } } qbs-src-1.4.5/src/lib/corelib/language/testdata/conditionaldepends_base.qbs000066400000000000000000000002541266132464200270210ustar00rootroot00000000000000import qbs 1.0 Application { name: 'conditionaldepends_base' property bool someProp: false Depends { condition: someProp name: 'dummy' } } qbs-src-1.4.5/src/lib/corelib/language/testdata/defaultvalue/000077500000000000000000000000001266132464200241325ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/defaultvalue/egon.qbs000066400000000000000000000003251266132464200255710ustar00rootroot00000000000000import qbs Project { Product { name: "dep" Export { Depends { name: "higher" } } } Product { name: "egon" Depends { name: "dep" } lower.prop1: "blubb" } } qbs-src-1.4.5/src/lib/corelib/language/testdata/defaultvalue/modules/000077500000000000000000000000001266132464200256025ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/defaultvalue/modules/higher/000077500000000000000000000000001266132464200270505ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/defaultvalue/modules/higher/higher.qbs000066400000000000000000000002661266132464200310310ustar00rootroot00000000000000import qbs Module { Depends { name: "lower" } lower.prop2: lower.prop1 === "egon" ? "withEgon" : original lower.listProp: lower.prop1 === "egon" ? ["egon"] : original } qbs-src-1.4.5/src/lib/corelib/language/testdata/defaultvalue/modules/lower/000077500000000000000000000000001266132464200267325ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/defaultvalue/modules/lower/lower.qbs000066400000000000000000000003221266132464200305660ustar00rootroot00000000000000import qbs Module { property string prop1 property string prop2: prop1 === "blubb" ? "withBlubb" : "withoutBlubb" property stringList listProp: prop1 === "blubb" ? ["blubb", "other"] : ["other"] } qbs-src-1.4.5/src/lib/corelib/language/testdata/defaultvalue/test.txt000066400000000000000000000000001266132464200256400ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/dependencyOnAllProfiles.qbs000066400000000000000000000004511266132464200267300ustar00rootroot00000000000000import qbs Project { property string profile1 property string profile2 Product { name: "dep" profiles: [project.profile1, project.profile2] } Product { name: "main" Depends { name: "dep" profiles: [] } } } qbs-src-1.4.5/src/lib/corelib/language/testdata/drawline.asm000066400000000000000000000000001266132464200237460ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/dummy.txt000066400000000000000000000000001266132464200233330ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/environmentvariable.qbs000066400000000000000000000000611266132464200262270ustar00rootroot00000000000000Product { name: qbs.getEnv("PRODUCT_NAME") } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/000077500000000000000000000000001266132464200234725ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/ParentItem.qbs000066400000000000000000000000561266132464200262520ustar00rootroot00000000000000import qbs Product { property bool cpp } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/conflicting_fileTagsFilter.qbs000066400000000000000000000003061266132464200314630ustar00rootroot00000000000000import qbs 1.0 Application { Group { fileTagsFilter: "application" qbs.install: true } Group { fileTagsFilter: "application" qbs.install: false } } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/dependency_cycle.qbs000066400000000000000000000005151266132464200274770ustar00rootroot00000000000000import qbs Project { CppApplication { name: "A" Depends { name: "B" } files: ["main.cpp"] } CppApplication { name: "B" Depends { name: "C" } files: ["main.cpp"] } CppApplication { name: "C" Depends { name: "A" } files: ["main.cpp"] } } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/duplicate_sources.qbs000066400000000000000000000001361266132464200277160ustar00rootroot00000000000000import qbs Product { files: ["main.cpp"] Group { files: ["main.cpp"] } } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/duplicate_sources_wildcards.qbs000066400000000000000000000001621266132464200317510ustar00rootroot00000000000000import qbs Product { files: ["*.qbs"] Group { files: ["duplicate_sources_wildcards.qbs"] } } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/importloop1.qbs000066400000000000000000000000641266132464200264660ustar00rootroot00000000000000import qbs 1.0 import "importloop2.qbs" as X X {} qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/importloop2.qbs000066400000000000000000000000641266132464200264670ustar00rootroot00000000000000import qbs 1.0 import "importloop1.qbs" as X X {} qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/invalid_child_item_type.qbs000066400000000000000000000000711266132464200310470ustar00rootroot00000000000000import qbs 1.0 Project { Depends { name: "foo" } } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/invalid_file.qbs000066400000000000000000000000771266132464200266320ustar00rootroot00000000000000import qbs Application { files: ["main.cpp", "other.h"] } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/invalid_property_type.qbs000066400000000000000000000000671266132464200306370ustar00rootroot00000000000000import qbs Product { property nonsense esnesnon } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/invalid_stringlist_element.qbs000066400000000000000000000000571266132464200316240ustar00rootroot00000000000000Product { files: ["foo", ["zoo"], "bar"] } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/main.cpp000066400000000000000000000000171266132464200251200ustar00rootroot00000000000000int main() { } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/misused-inherited-property.qbs000066400000000000000000000000711266132464200315030ustar00rootroot00000000000000import qbs ParentItem { cpp.compilerName: "blubb" } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/multiple_exports.qbs000066400000000000000000000000501266132464200276130ustar00rootroot00000000000000Product { Export {} Export {} } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/multiple_properties_in_subproject.qbs000066400000000000000000000001741266132464200332400ustar00rootroot00000000000000import qbs Project { SubProject { Properties { condition: false } Properties { name: "blubb" } } } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/nonexistentouter.qbs000066400000000000000000000001041266132464200276310ustar00rootroot00000000000000import qbs 1.0 Project { Product { name: outer } } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/oldQbsVersion.qbs000066400000000000000000000001531266132464200267720ustar00rootroot00000000000000import qbs Project { minimumQbsVersion: "999.5.4" Product { qbs.enableSound: true } } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/properties-item-with-invalid-condition.qbs000066400000000000000000000002501266132464200337070ustar00rootroot00000000000000import qbs Product { Depends { name: "cpp" } Properties { condition: cpp.nonexistingproperty.contains("somevalue") cpp.defines: ["ABC"] } } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/references_cycle.qbs000066400000000000000000000001071266132464200274770ustar00rootroot00000000000000import qbs 1.0 Project { references: ["references_cycle2.qbs"] } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/references_cycle2.qbs000066400000000000000000000001071266132464200275610ustar00rootroot00000000000000import qbs 1.0 Project { references: ["references_cycle3.qbs"] } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/references_cycle3.qbs000066400000000000000000000001061266132464200275610ustar00rootroot00000000000000import qbs 1.0 Project { references: ["references_cycle.qbs"] } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/reserved_name_in_import.qbs000066400000000000000000000001001266132464200310670ustar00rootroot00000000000000import qbs import "../idusagebase.qbs" as TextFile Product { } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/subproject_cycle.qbs000066400000000000000000000001361266132464200275400ustar00rootroot00000000000000import qbs 1.0 Project { SubProject { filePath: "subproject_cycle2.qbs" } } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/subproject_cycle2.qbs000066400000000000000000000001361266132464200276220ustar00rootroot00000000000000import qbs 1.0 Project { SubProject { filePath: "subproject_cycle3.qbs" } } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/subproject_cycle3.qbs000066400000000000000000000001351266132464200276220ustar00rootroot00000000000000import qbs 1.0 Project { SubProject { filePath: "subproject_cycle.qbs" } } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/throw_in_property_binding.qbs000066400000000000000000000001221266132464200314630ustar00rootroot00000000000000import qbs 1.0 Product { name: { throw "something is wrong"; } } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/undeclared_item.qbs000066400000000000000000000000751266132464200273270ustar00rootroot00000000000000import qbs 1.0 Product { cpp.defines: ["SUPERCRAZY"] } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/undeclared_property.qbs000066400000000000000000000000621266132464200302510ustar00rootroot00000000000000import qbs 1.0 Product { doesntexist: 123 } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/undeclared_property_in_Properties_item.qbs000066400000000000000000000001361266132464200341730ustar00rootroot00000000000000import qbs Product { Properties { condition: true blubb.bla: "x" } } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/undeclared_property_in_export_item.qbs000066400000000000000000000003141266132464200333560ustar00rootroot00000000000000import qbs Project { Product { name: "p1" Export { Depends { name: "cpp" } cpp.blubb: "x" } } Product { Depends { name: "p1" } } } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/undeclared_property_in_export_item2.qbs000066400000000000000000000002561266132464200334450ustar00rootroot00000000000000import qbs Project { Product { name: "p1" Export { something.other: "x" } } Product { Depends { name: "p1" } } } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/undeclared_property_in_export_item3.qbs000066400000000000000000000002061266132464200334410ustar00rootroot00000000000000import qbs Project { Product { name: "p1" Export { blubb: false } } Product { Depends { name: "p1" } } } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/undeclared_property_wrapper.qbs000066400000000000000000000001031266132464200320050ustar00rootroot00000000000000import qbs SubProject { filePath: "undeclared_property.qbs" } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/undefined_stringlist_element.qbs000066400000000000000000000001071266132464200321330ustar00rootroot00000000000000Product { property string blubb files: ["foo", blubb, "bar"] } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/unknown_item_type.qbs000066400000000000000000000001431266132464200277550ustar00rootroot00000000000000Narf { zort: 1 // This invalid binding should not hide the "Unexpected item type" error. } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/unknown_module.qbs000066400000000000000000000000741266132464200272460ustar00rootroot00000000000000Product { Depends { name: "neitherModuleNorProduct" } } qbs-src-1.4.5/src/lib/corelib/language/testdata/erroneous/wrongQbsVersionFormat.qbs000066400000000000000000000000761266132464200305250ustar00rootroot00000000000000import qbs Project { minimumQbsVersion: "hfyh1234wat?" } qbs-src-1.4.5/src/lib/corelib/language/testdata/exports.qbs000066400000000000000000000026571266132464200236760ustar00rootroot00000000000000import qbs 1.0 import "exports_product.qbs" as ProductWithInheritedExportItem Project { Application { name: "myapp" Depends { name: "mylib" } Depends { name: "dummy" } dummy.defines: ["BUILD_" + product.name.toUpperCase()] dummy.includePaths: ["./app"] } references: [ "subdir/exports-mylib.qbs", "subdir2/exports-mylib2.qbs" ] Application { name: "A" Depends { name: "B" } } StaticLibrary { name: "B" Export { Depends { name: "C" } } } StaticLibrary { name: "C" Export { Depends { name: "D" } } } StaticLibrary { name: "D" } Application { name: "myapp2" Depends { name: "productWithInheritedExportItem" } } ProductWithInheritedExportItem { name: "productWithInheritedExportItem" Export { dummy.cxxFlags: ["-bar"] } } Application { name: "myapp3" Depends { name: "productWithInheritedExportItem" } } Project { name: "sub1" Product { name: "sub p1" Export { Depends { name: "dummy" } dummy.someString: project.name } } } Project { name: "sub2" Product { name: "sub p2" Depends { name: "sub p1" } } } } qbs-src-1.4.5/src/lib/corelib/language/testdata/exports_product.qbs000066400000000000000000000002011266132464200254150ustar00rootroot00000000000000Product { Export { Depends { name: "dummy" } dummy.cxxFlags: ["-foo"] dummy.defines: ["ABC"] } } qbs-src-1.4.5/src/lib/corelib/language/testdata/filecontextproperties.qbs000066400000000000000000000001431266132464200266170ustar00rootroot00000000000000Product { name: "product1" property string narf: filePath property string zort: path } qbs-src-1.4.5/src/lib/corelib/language/testdata/filetags.qbs000066400000000000000000000022161266132464200237570ustar00rootroot00000000000000import qbs 1.0 Project { FileTagger { patterns: "*.cpp" fileTags: ["cpp"] } Product { name: "filetagger_project_scope" files: ["main.cpp"] } Product { name: "filetagger_product_scope" files: ["drawline.asm"] FileTagger { patterns: "*.asm" fileTags: ["asm"] } } Product { name: "filetagger_static_pattern" files: "Banana" FileTagger { patterns: "Banana" fileTags: ["yellow"] } } Product { name: "unknown_file_tag" files: "narf.zort" } Product { name: "set_file_tag_via_group" Group { files: ["main.cpp"] fileTags: ["c++"] } } Product { name: "override_file_tag_via_group" Group { files: "main.cpp" // gets file tag "cpp" through the FileTagger fileTags: ["c++"] } } Product { name: "add_file_tag_via_group" Group { overrideTags: false files: "main.cpp" fileTags: ["zzz"] } } } qbs-src-1.4.5/src/lib/corelib/language/testdata/getNativeSetting.qbs000066400000000000000000000014541266132464200254500ustar00rootroot00000000000000import qbs.FileInfo Project { Product { name: { if (qbs.hostOS.contains("osx")) { return qbs.getNativeSetting("/System/Library/CoreServices/SystemVersion.plist", "ProductName"); } else if (qbs.hostOS.contains("windows")) { var productName = qbs.getNativeSetting("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion", "ProductName"); if (productName.contains("Windows")) { return "Windows"; } return undefined; } else { return qbs.getNativeSetting(FileInfo.joinPaths(path, "nativesettings.ini"), "osname"); } } } Product { name: qbs.getNativeSetting("/dev/null", undefined, "fallback"); } } qbs-src-1.4.5/src/lib/corelib/language/testdata/groupconditions.qbs000066400000000000000000000021601266132464200254050ustar00rootroot00000000000000import qbs 1.0 Project { property bool someTrueProperty: true Product { name: "no_condition_no_group" files: ["main.cpp"] } Product { name: "no_condition" Group { files: ["main.cpp"] } } Product { name: "true_condition" Group { condition: true files: ["main.cpp"] } } Product { name: "false_condition" Group { condition: false files: ["main.cpp"] } } Product { name: "true_condition_from_product" property bool anotherTrueProperty: true Group { condition: anotherTrueProperty files: ["main.cpp"] } } Product { name: "true_condition_from_project" Group { condition: project.someTrueProperty files: ["main.cpp"] } } Product { name: "condition_accessing_module_property" Group { condition: qbs.targetOS.contains("narf") files: ["main.cpp"] qbs.install: false } } } qbs-src-1.4.5/src/lib/corelib/language/testdata/groupname.qbs000066400000000000000000000005411266132464200241550ustar00rootroot00000000000000Project { Product { name: "MyProduct" Group { name: product.name + ".MyGroup" files: "*" } } Product { name: "My2ndProduct" Group { name: product.name + ".MyGroup" files: ["narf"] } Group { files: ["zort"] } } } qbs-src-1.4.5/src/lib/corelib/language/testdata/homeDirectory.qbs000066400000000000000000000007011266132464200247730ustar00rootroot00000000000000import qbs 1.0 Project { Product { name: "home" // These should resolve property path home: "~" property path homeSlash: "~/" property path homeUp: "~/.." property path homeFile: "~/a" // These are sanity checks and should not property path bogus1: "a~b" property path bogus2: "a/~/bb" property path user: "~foo/bar" // we don't resolve other-user paths } } qbs-src-1.4.5/src/lib/corelib/language/testdata/idusage.qbs000066400000000000000000000006411266132464200236020ustar00rootroot00000000000000import qbs 1.0 import "idusagebase.qbs" as DerivedProduct Project { id: theProject property int initialNr: 0 DerivedProduct { id: product1 } Product { id: product2 property int nr: theProject.initialNr + product1.nr + 1 name: "product2_" + nr } Product { id: product3 property int nr: product2.nr + 1 name: "product3_" + nr } } qbs-src-1.4.5/src/lib/corelib/language/testdata/idusagebase.qbs000066400000000000000000000001511266132464200244310ustar00rootroot00000000000000Product { id: baseProduct property int nr: theProject.initialNr + 1 name: "product1_" + nr } qbs-src-1.4.5/src/lib/corelib/language/testdata/import-collection/000077500000000000000000000000001266132464200251145ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/import-collection/collection/000077500000000000000000000000001266132464200272475ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/import-collection/collection/file1.js000066400000000000000000000000411266132464200306000ustar00rootroot00000000000000function f1() { return "C2f1"; } qbs-src-1.4.5/src/lib/corelib/language/testdata/import-collection/collection/file2.js000066400000000000000000000000411266132464200306010ustar00rootroot00000000000000function f2() { return "C2f2"; } qbs-src-1.4.5/src/lib/corelib/language/testdata/import-collection/imports/000077500000000000000000000000001266132464200266115ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/import-collection/imports/Collection/000077500000000000000000000000001266132464200307045ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/import-collection/imports/Collection/file1.js000066400000000000000000000000411266132464200322350ustar00rootroot00000000000000function f1() { return "C1f1"; } qbs-src-1.4.5/src/lib/corelib/language/testdata/import-collection/imports/Collection/file2.js000066400000000000000000000000411266132464200322360ustar00rootroot00000000000000function f2() { return "C1f2"; } qbs-src-1.4.5/src/lib/corelib/language/testdata/import-collection/product.qbs000066400000000000000000000003021266132464200272760ustar00rootroot00000000000000import Collection as Collection1 import "collection" as Collection2 Product { name: "da product" targetName: Collection1.f1() + Collection1.f2() + Collection2.f1() + Collection2.f2() } qbs-src-1.4.5/src/lib/corelib/language/testdata/import-collection/project.qbs000066400000000000000000000000711266132464200272670ustar00rootroot00000000000000import qbs Project { references: ["product.qbs"] } qbs-src-1.4.5/src/lib/corelib/language/testdata/invalidBindingInDisabledItem.qbs000066400000000000000000000005351266132464200276420ustar00rootroot00000000000000import qbs 1.0 Project { Product { name: "product1" condition: false someNonsense: "Bitte stellen Sie die Tassen auf den Tisch." } Product { name: "product2" Group { condition: false moreNonsense: "Follen. Follen. Hünuntergefollen. Auf dön Töppüch." } } } qbs-src-1.4.5/src/lib/corelib/language/testdata/jsextensions.js000066400000000000000000000042261266132464200245470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ (function() { // Function wrapper to keep the environment clean. /* * poor man's JS test suite */ var testctx = {}; function initTestContext(name) { testctx.nr = 1; testctx.name = name; } function verify(c) { if (!c) throw testctx.name + ": verification #" + testctx.nr + " failed."; testctx.nr++; } /* * Tests for extensions of JavaScript builtin types. */ var a = ["one", "two", "three"]; initTestContext("Array.prototype.contains"); for (var k in a) verify(k !== "contains"); verify(a.contains("one")); verify(a.contains("two")); verify(a.contains("three")); verify(!a.contains("four")); })() // END function wrapper qbs-src-1.4.5/src/lib/corelib/language/testdata/jsimportsinmultiplescopes.js000066400000000000000000000003011266132464200273530ustar00rootroot00000000000000function getName(qbsModule) { if (qbsModule.debugInformation) return "MyProduct_debug"; else return "MyProduct"; } function getInstallDir() { return "somewhere"; } qbs-src-1.4.5/src/lib/corelib/language/testdata/jsimportsinmultiplescopes.qbs000066400000000000000000000002531266132464200275320ustar00rootroot00000000000000import "jsimportsinmultiplescopes.js" as MyFunctions Product { name: MyFunctions.getName(qbs) qbs.installDir: MyFunctions.getInstallDir() files: "main.cpp" } qbs-src-1.4.5/src/lib/corelib/language/testdata/main.cpp000066400000000000000000000000001266132464200230670ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/moduleproperties.qbs000066400000000000000000000021141266132464200255600ustar00rootroot00000000000000import qbs 1.0 Project { Product { name: "merge_lists" Depends { name: "dummyqt"; submodules: ["gui", "network"] } Depends { name: "dummy" } dummy.defines: ["THE_PRODUCT"] } Product { name: "merge_lists_and_values" Depends { name: "dummyqt"; submodules: ["network", "gui"] } Depends { name: "dummy" } dummy.defines: "THE_PRODUCT" } Product { name: "merge_lists_with_duplicates" Depends { name: "dummy" } dummy.cxxFlags: ["-foo", "BAR", "-foo", "BAZ"] } Product { name: "merge_lists_with_prototype_values" Depends { name: "dummyqt"; submodules: ["gui", "network"] } Depends { name: "dummy" } } Product { name: "list_property_that_references_product" type: ["blubb"] Depends { name: "dummy" } dummy.listProp: ["x"] } Product { name: "list_property_depending_on_overridden_property" Depends { name: "dummy" } dummy.listProp2: ["PRODUCT_STUFF"] dummy.controllingProp: true } } qbs-src-1.4.5/src/lib/corelib/language/testdata/modules.qbs000066400000000000000000000025361266132464200236360ustar00rootroot00000000000000Project { Product { name: "no_modules" property var foo } Product { name: "qt_core" dummyqt.core.version: "1.2.3" property var foo: dummyqt.core.coreVersion Depends { name: "dummyqt.core" } } Product { name: "qt_gui" property var foo: dummyqt.gui.guiProperty Depends { name: "dummyqt.gui" } } Product { name: "qt_gui_network" property var foo: dummyqt.gui.guiProperty + ',' + dummyqt.network.networkProperty Depends { name: "dummyqt" submodules: ["gui", "network"] } } Product { name: "deep_module_name" property var foo: dummy.deep.moat.depth Depends { name: "dummy.deep.moat" } } Product { name: "deep_module_name_submodule_syntax1" property var foo: dummy.deep.moat.depth Depends { name: "dummy.deep" submodules: ["moat"] } } Product { name: "deep_module_name_submodule_syntax2" property var foo: dummy.deep.moat.depth Depends { name: "dummy" submodules: ["deep.moat"] } } Product { name: "dummy_twice" Depends { name: "dummy" } Depends { name: "dummy" } } } qbs-src-1.4.5/src/lib/corelib/language/testdata/modules/000077500000000000000000000000001266132464200231215ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/modules/dummy/000077500000000000000000000000001266132464200242545ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/modules/dummy/deep/000077500000000000000000000000001266132464200251715ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/modules/dummy/deep/moat/000077500000000000000000000000001266132464200261315ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/modules/dummy/deep/moat/dummydeepmoat.qbs000066400000000000000000000001161266132464200315100ustar00rootroot00000000000000Module { property string depth: "abysmal" Depends { name: "dummy" } } qbs-src-1.4.5/src/lib/corelib/language/testdata/modules/dummy/dummy.qbs000066400000000000000000000012761266132464200261240ustar00rootroot00000000000000import "dummy_base.qbs" as DummyBase DummyBase { condition: true property stringList defines property stringList cFlags property stringList cxxFlags property stringList rpaths: ["$ORIGIN"] property string someString property string productName: product.name property string upperCaseProductName: productName.toUpperCase() property string zort: "zort in dummy" property pathList includePaths property stringList listProp: product.type.contains("blubb") ? ["123"] : ["456"] property bool controllingProp: false property stringList listProp2: controllingProp ? ["DEFAULT_STUFF", "EXTRA_STUFF"] : ["DEFAULT_STUFF"] } qbs-src-1.4.5/src/lib/corelib/language/testdata/modules/dummy/dummy_base.qbs000066400000000000000000000001031266132464200271020ustar00rootroot00000000000000Module { condition: false property pathList includePaths } qbs-src-1.4.5/src/lib/corelib/language/testdata/modules/dummy2/000077500000000000000000000000001266132464200243365ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/modules/dummy2/dummy2.qbs000066400000000000000000000001761266132464200262660ustar00rootroot00000000000000import qbs 1.0 Module { property var defines property var someTrueProp: true property var someFalseProp: false } qbs-src-1.4.5/src/lib/corelib/language/testdata/modules/dummyqt/000077500000000000000000000000001266132464200246215ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/modules/dummyqt/core/000077500000000000000000000000001266132464200255515ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/modules/dummyqt/core/dummycore.qbs000066400000000000000000000007641266132464200302730ustar00rootroot00000000000000import qbs 1.0 Module { id: qtcore property int versionMajor: 5 property int versionMinor: 0 property int versionPatch: 0 property string version: versionMajor.toString() + "." + versionMinor.toString() + "." + versionPatch.toString() property string coreProperty: "coreProperty" property string coreVersion: qtcore.version property string zort: "zort in dummyqt.core" Depends { name: "dummy" } dummy.defines: ["QT_CORE"] dummy.rpaths: ["/opt/qt/lib"] } qbs-src-1.4.5/src/lib/corelib/language/testdata/modules/dummyqt/gui/000077500000000000000000000000001266132464200254055ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/modules/dummyqt/gui/dummygui.qbs000066400000000000000000000004361266132464200277570ustar00rootroot00000000000000import qbs 1.0 Module { Depends { name: "dummyqt.core" } property string guiProperty: "guiProperty" property string someString: "ene mene muh" Depends { name: "dummy" } dummy.defines: ["QT_GUI"] dummy.someString: someString dummy.zort: dummyqt.core.zort } qbs-src-1.4.5/src/lib/corelib/language/testdata/modules/dummyqt/network/000077500000000000000000000000001266132464200263125ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/modules/dummyqt/network/dummynetwork.qbs000066400000000000000000000003111266132464200315610ustar00rootroot00000000000000import qbs 1.0 Module { Depends { name: "dummyqt"; submodules: ["core"] } property string networkProperty: "networkProperty" Depends { name: "dummy" } dummy.defines: ["QT_NETWORK"] } qbs-src-1.4.5/src/lib/corelib/language/testdata/modules/scopemod/000077500000000000000000000000001266132464200247325ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/modules/scopemod/scopemod.qbs000066400000000000000000000003231266132464200272500ustar00rootroot00000000000000import qbs 1.0 Module { property int a: 1 property int b: 1 property int c: a + 1 property int d: b + 1 property int e: 1 property int f: 1 property int g: 1 property int h: 1 } qbs-src-1.4.5/src/lib/corelib/language/testdata/modulescope.qbs000066400000000000000000000004171266132464200245010ustar00rootroot00000000000000import qbs 1.0 import "modulescope_base.qbs" as MyProduct Project { MyProduct { name: "product1" property int e: 12 property int f: 13 scopemod.a: 2 scopemod.f: 2 scopemod.g: e * f scopemod.h: base + 2 } } qbs-src-1.4.5/src/lib/corelib/language/testdata/modulescope_base.qbs000066400000000000000000000001231266132464200254650ustar00rootroot00000000000000import qbs 1.0 Product { Depends { name: "scopemod" } scopemod.h: e * f } qbs-src-1.4.5/src/lib/corelib/language/testdata/narf000066400000000000000000000000001266132464200223100ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/narf.zort000066400000000000000000000000001266132464200233050ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/nativesettings.ini000066400000000000000000000000161266132464200252160ustar00rootroot00000000000000osname = Unix qbs-src-1.4.5/src/lib/corelib/language/testdata/outerInGroup.qbs000066400000000000000000000004351266132464200246240ustar00rootroot00000000000000import qbs 1.0 Project { Product { name: "OuterInGroup" qbs.installDir: "/somewhere" files: ["main.cpp"] Group { name: "Special Group" files: ["aboutdialog.cpp"] qbs.installDir: outer + "/else" } } } qbs-src-1.4.5/src/lib/corelib/language/testdata/pathproperties.qbs000066400000000000000000000004231266132464200252300ustar00rootroot00000000000000import "subdir/pathproperties_base.qbs" as ProductBase ProductBase { name: "product1" property path projectFileDir: "." property pathList filesInProjectFileDir: ["./aboutdialog.h", "aboutdialog.cpp"] Depends { name: "dummy" } dummy.includePaths: ["."] } qbs-src-1.4.5/src/lib/corelib/language/testdata/productconditions.qbs000066400000000000000000000006171266132464200257360ustar00rootroot00000000000000import qbs 1.0 Project { Product { name: "product_no_condition" } Product { name: "product_true_condition" condition: 1 === 1 } Product { name: "product_false_condition" condition: 1 === 2 } Product { name: "product_condition_dependent_of_module" condition: qbs.architecture !== (qbs.architecture + "foo") } } qbs-src-1.4.5/src/lib/corelib/language/testdata/productdirectories.qbs000066400000000000000000000000561266132464200260760ustar00rootroot00000000000000import qbs 1.0 Product { name: "MyApp" } qbs-src-1.4.5/src/lib/corelib/language/testdata/profilevaluesandoverriddenvalues.qbs000066400000000000000000000014341266132464200310270ustar00rootroot00000000000000import qbs 1.0 Project { Application { name: "product1" type: { if (!(dummy.cFlags instanceof Array)) throw new Error("dummy.cFlags: Array type expected."); if (!(dummy.cxxFlags instanceof Array)) throw new Error("dummy.cxxFlags: Array type expected."); if (!(dummy.defines instanceof Array)) throw new Error("dummy.defines: Array type expected."); return "application"; } consoleApplication: true Depends { name: "dummy" } // dummy.cxxFlags is set via profile and is not overridden dummy.defines: ["IN_FILE"] // set in profile, overridden in file dummy.cFlags: ["IN_FILE"] // set in profile, overridden on command line } } qbs-src-1.4.5/src/lib/corelib/language/testdata/properties-block-in-group.qbs000066400000000000000000000005331266132464200272030ustar00rootroot00000000000000import qbs Product { name: "in-group" property bool featureEnabled: true Depends { name: "dummy" } dummy.defines: ["BASEDEF"] Group { name: "the group" files: ["dummy.txt" ] Properties { condition: featureEnabled dummy.defines: outer.concat("FEATURE_ENABLED") } } } qbs-src-1.4.5/src/lib/corelib/language/testdata/propertiesblocks.qbs000066400000000000000000000110041266132464200255460ustar00rootroot00000000000000import qbs 1.0 import "propertiesblocks_base.qbs" as ProductBase Project { Product { name: "property_overwrite" Depends { id: cpp; name: "dummy" } cpp.defines: ["SOMETHING"] Properties { condition: true cpp.defines: ["OVERWRITTEN"] } } Product { name: "property_overwrite_no_outer" Depends { id: cpp; name: "dummy" } Properties { condition: true cpp.defines: ["OVERWRITTEN"] } } Product { name: "property_append_to_outer" Depends { id: cpp; name: "dummy" } cpp.defines: ["ONE"] Properties { condition: true cpp.defines: outer.concat(["TWO"]) } } Product { name: "multiple_exclusive_properties" Depends { id: cpp; name: "dummy" } cpp.defines: ["SOMETHING"] Properties { condition: true cpp.defines: ["OVERWRITTEN"] } Properties { condition: false cpp.defines: ["IMPOSSIBLE"] } } Product { name: "multiple_exclusive_properties_no_outer" Depends { id: cpp; name: "dummy" } Properties { condition: true cpp.defines: ["OVERWRITTEN"] } Properties { condition: false cpp.defines: ["IMPOSSIBLE"] } } Product { name: "multiple_exclusive_properties_append_to_outer" Depends { id: cpp; name: "dummy" } cpp.defines: ["ONE"] Properties { condition: true cpp.defines: outer.concat(["TWO"]) } Properties { condition: false cpp.defines: ["IMPOSSIBLE"] } } Product { name: "ambiguous_properties" Depends { id: cpp; name: "dummy" } cpp.defines: ["ONE"] Properties { condition: true cpp.defines: outer.concat(["TWO"]) } Properties { condition: false cpp.defines: outer.concat(["IMPOSSIBLE"]) } Properties { // will be ignored condition: true cpp.defines: outer.concat(["THREE"]) } } Product { name: "condition_refers_to_product_property" property string narf: true property string someString: "SOMETHING" Depends { name: "dummy" } Properties { condition: narf dummy.defines: ["OVERWRITTEN"] someString: "OVERWRITTEN" } } property string zort: true Product { name: "condition_refers_to_project_property" property string someString: "SOMETHING" Depends { name: "dummy" } Properties { condition: project.zort dummy.defines: ["OVERWRITTEN"] someString: "OVERWRITTEN" } } ProductBase { name: "inheritance_overwrite_in_subitem" dummy.defines: ["OVERWRITTEN_IN_SUBITEM"] } ProductBase { name: "inheritance_retain_base1" dummy.defines: base.concat("SUB") } ProductBase { name: "inheritance_retain_base2" Properties { condition: true dummy.defines: base.concat("SUB") } dummy.defines: ["GNAMPF"] } ProductBase { name: "inheritance_retain_base3" Properties { condition: true dummy.defines: base.concat("SUB") } // no dummy.defines binding } ProductBase { name: "inheritance_retain_base4" Properties { condition: false dummy.defines: ["NEVERMORE"] } // no "else case" for dummy.defines. The value is derived from ProductBase. } ProductBase { name: "inheritance_condition_in_subitem1" defineBase: false dummy.defines: base.concat("SUB") } ProductBase { name: "inheritance_condition_in_subitem2" defineBase: false // no dummy.defines binding } Product { id: knolf name: "gnampf" } Product { name: "condition_references_id" Depends { id: cpp; name: "dummy" } Properties { condition: knolf.name === "gnampf" cpp.defines: ["OVERWRITTEN"] } } Product { name: "conditional-depends" Depends { name: "dummy" condition: false } Properties { condition: false dummy.defines: ["a string"] } } } qbs-src-1.4.5/src/lib/corelib/language/testdata/propertiesblocks_base.qbs000066400000000000000000000003231266132464200265420ustar00rootroot00000000000000import qbs 1.0 Product { property bool defineBase: true Depends { name: "dummy" } Properties { condition: defineBase dummy.defines: ["BASE"] } dummy.defines: ["SOMETHING"] } qbs-src-1.4.5/src/lib/corelib/language/testdata/qbs-properties-in-project-condition.qbs000066400000000000000000000001741266132464200311750ustar00rootroot00000000000000import qbs Project { condition: qbs.targetOS.contains("whatever") Product { name: "never reached" } } qbs-src-1.4.5/src/lib/corelib/language/testdata/recursive-dependencies/000077500000000000000000000000001266132464200261045ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/recursive-dependencies/recursive-dependencies.qbs000066400000000000000000000004441266132464200332500ustar00rootroot00000000000000import qbs Project { Product { name: "p1" Depends { name: "p3" } } Product { name: "p2" Depends { name: "p3" } } Product { name: "p3" Export { Depends { name: "p4" } } } Product { name: "p4" } } qbs-src-1.4.5/src/lib/corelib/language/testdata/rfc1034identifier.qbs000066400000000000000000000003261266132464200253060ustar00rootroot00000000000000import qbs CppApplication { name: qbs.rfc1034Identifier("this!has@special#characters$uh-oh,Undersc0r3s_Are.Bad") bundle.infoPlist: { return {"CFBundleIdentifier": "$(PRODUCT_NAME:rfc1034identifier)"}; } } qbs-src-1.4.5/src/lib/corelib/language/testdata/subdir/000077500000000000000000000000001266132464200227415ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/subdir/exports-mylib.qbs000066400000000000000000000005731266132464200262730ustar00rootroot00000000000000import qbs StaticLibrary { name: "mylib" Depends { name: "dummy" } dummy.defines: ["BUILD_" + product.name.toUpperCase()] property string definePrefix: "USE_" Export { Depends { name: "dummy" } Depends { name: "mylib2" } dummy.defines: [product.definePrefix + product.name.toUpperCase()] dummy.includePaths: ["./lib"] } } qbs-src-1.4.5/src/lib/corelib/language/testdata/subdir/pathproperties_base.qbs000066400000000000000000000001661266132464200275160ustar00rootroot00000000000000Product { property path base_fileInProductDir: "foo" property path base_fileInBaseProductDir: path + "/bar" } qbs-src-1.4.5/src/lib/corelib/language/testdata/subdir2/000077500000000000000000000000001266132464200230235ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/testdata/subdir2/exports-mylib2.qbs000066400000000000000000000005311266132464200264310ustar00rootroot00000000000000import qbs StaticLibrary { name: "mylib2" Depends { name: "dummy" } dummy.defines: ["BUILD_" + product.name.toUpperCase()] property string definePrefix: "USE_" Export { Depends { name: "dummy" } dummy.defines: [product.definePrefix + product.name.toUpperCase()] dummy.includePaths: ["./lib"] } } qbs-src-1.4.5/src/lib/corelib/language/testdata/zort000066400000000000000000000000001266132464200223600ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/language/tst_language.cpp000066400000000000000000002172431266132464200230320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #undef QT_NO_CAST_FROM_ASCII // I am qmake, and I approve this hack. #include "tst_language.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include Q_DECLARE_METATYPE(QList) namespace qbs { namespace Internal { static QString testDataDir() { return FileInfo::resolvePath(QLatin1String(SRCDIR), QLatin1String("language/testdata")); } static QString testProject(const char *fileName) { return testDataDir() + QLatin1Char('/') + QLatin1String(fileName); } TestLanguage::TestLanguage(ILogSink *logSink) : m_logSink(logSink) , m_wildcardsTestDirPath(QDir::tempPath() + QLatin1String("/_wildcards_test_dir_")) { qsrand(QTime::currentTime().msec()); qRegisterMetaType >("QList"); defaultParameters.setBuildRoot("/some/build/directory"); defaultParameters.setPropertyCheckingMode(SetupProjectParameters::PropertyCheckingStrict); } TestLanguage::~TestLanguage() { } QHash TestLanguage::productsFromProject(ResolvedProjectPtr project) { QHash result; foreach (const ResolvedProductPtr &product, project->allProducts()) result.insert(product->name, product); return result; } ResolvedModuleConstPtr TestLanguage::findModuleByName(ResolvedProductPtr product, const QString &name) { foreach (const ResolvedModuleConstPtr &module, product->modules) if (module->name == name) return module; return ResolvedModuleConstPtr(); } QVariant TestLanguage::productPropertyValue(ResolvedProductPtr product, QString propertyName) { QStringList propertyNameComponents = propertyName.split(QLatin1Char('.')); QVariantMap properties; if (propertyNameComponents.count() > 1) { propertyNameComponents.prepend(QLatin1String("modules")); properties = product->moduleProperties->value(); } else { properties = product->productProperties; } return getConfigProperty(properties, propertyNameComponents); } void TestLanguage::handleInitCleanupDataTags(const char *projectFileName, bool *handled) { const QByteArray dataTag = QTest::currentDataTag(); if (dataTag == "init") { *handled = true; bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject(projectFileName)); project = loader->loadProject(defaultParameters); QVERIFY(project); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } else if (dataTag == "cleanup") { *handled = true; project.clear(); } else { *handled = false; } } #define HANDLE_INIT_CLEANUP_DATATAGS(fn) {\ bool handled;\ handleInitCleanupDataTags(fn, &handled);\ if (handled)\ return;\ QVERIFY(project);\ } void TestLanguage::initTestCase() { m_logger = Logger(m_logSink); m_engine = new ScriptEngine(m_logger, this); loader = new Loader(m_engine, m_logger); loader->setSearchPaths(QStringList() << QLatin1String(SRCDIR "/../../../share/qbs")); defaultParameters.setTopLevelProfile("qbs_autotests"); defaultParameters.setBuildVariant("debug"); defaultParameters.expandBuildConfiguration(); QVERIFY(QFileInfo(m_wildcardsTestDirPath).isAbsolute()); } void TestLanguage::cleanupTestCase() { delete loader; } void TestLanguage::baseProperty() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("baseproperty.qbs")); project = loader->loadProject(defaultParameters); QVERIFY(project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value("product1"); QVERIFY(product); QVariantMap cfg = product->productProperties; QCOMPARE(cfg.value("narf").toStringList(), QStringList() << "boo"); QCOMPARE(cfg.value("zort").toStringList(), QStringList() << "bar" << "boo"); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::buildConfigStringListSyntax() { bool exceptionCaught = false; try { SetupProjectParameters parameters = defaultParameters; QVariantMap overriddenValues; overriddenValues.insert("project.someStrings", "foo,bar,baz"); parameters.setOverriddenValues(overriddenValues); parameters.setProjectFilePath(testProject("buildconfigstringlistsyntax.qbs")); project = loader->loadProject(parameters); QVERIFY(project); QCOMPARE(project->projectProperties().value("someStrings").toStringList(), QStringList() << "foo" << "bar" << "baz"); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::builtinFunctionInSearchPathsProperty() { bool exceptionCaught = false; try { SetupProjectParameters parameters = defaultParameters; parameters.setProjectFilePath(testProject("builtinFunctionInSearchPathsProperty.qbs")); QVERIFY(loader->loadProject(parameters)); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::canonicalArchitecture() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("canonicalArchitecture.qbs")); project = loader->loadProject(defaultParameters); QVERIFY(project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value(QLatin1String("x86")); QVERIFY(product); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::rfc1034Identifier() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("rfc1034identifier.qbs")); project = loader->loadProject(defaultParameters); QVERIFY(project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value(QLatin1String("this-has-special-characters-" "uh-oh-Undersc0r3s-Are.Bad")); QVERIFY(product); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::conditionalDepends() { bool exceptionCaught = false; ResolvedProductPtr product; ResolvedModuleConstPtr dependency; try { defaultParameters.setProjectFilePath(testProject("conditionaldepends.qbs")); project = loader->loadProject(defaultParameters); QVERIFY(project); QHash products = productsFromProject(project); product = products.value("conditionaldepends_derived"); QVERIFY(product); dependency = findModuleByName(product, "dummy"); QVERIFY(dependency); product = products.value("conditionaldepends_derived_false"); QVERIFY(product); dependency = findModuleByName(product, "dummy"); QCOMPARE(dependency, ResolvedModuleConstPtr()); product = products.value("product_props_true"); QVERIFY(product); dependency = findModuleByName(product, "dummy"); QVERIFY(dependency); product = products.value("product_props_false"); QVERIFY(product); dependency = findModuleByName(product, "dummy"); QCOMPARE(dependency, ResolvedModuleConstPtr()); product = products.value("project_props_true"); QVERIFY(product); dependency = findModuleByName(product, "dummy"); QVERIFY(dependency); product = products.value("project_props_false"); QVERIFY(product); dependency = findModuleByName(product, "dummy"); QCOMPARE(dependency, ResolvedModuleConstPtr()); product = products.value("module_props_true"); QVERIFY(product); dependency = findModuleByName(product, "dummy2"); QVERIFY(dependency); dependency = findModuleByName(product, "dummy"); QVERIFY(dependency); product = products.value("module_props_false"); QVERIFY(product); dependency = findModuleByName(product, "dummy2"); QVERIFY(dependency); dependency = findModuleByName(product, "dummy"); QCOMPARE(dependency, ResolvedModuleConstPtr()); product = products.value("contradictory_conditions1"); QVERIFY(product); dependency = findModuleByName(product, "dummy"); QVERIFY(dependency); product = products.value("contradictory_conditions2"); QVERIFY(product); dependency = findModuleByName(product, "dummy"); QVERIFY(dependency); product = products.value("unknown_dependency_condition_false"); QVERIFY(product); dependency = findModuleByName(product, "doesonlyexistifhellfreezesover"); QVERIFY(!dependency); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void qbs::Internal::TestLanguage::dependencyOnAllProfiles() { bool exceptionCaught = false; try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("dependencyOnAllProfiles.qbs")); Settings settings((QString())); TemporaryProfile p1("p1", &settings); p1.p.setValue("qbs.architecture", "arch1"); TemporaryProfile p2("p2", &settings); p2.p.setValue("qbs.architecture", "arch2"); QVariantMap overriddenValues; overriddenValues.insert("project.profile1", "p1"); overriddenValues.insert("project.profile2", "p2"); params.setOverriddenValues(overriddenValues); project = loader->loadProject(params); QVERIFY(project); QCOMPARE(project->products.count(), 3); const ResolvedProductConstPtr mainProduct = productsFromProject(project).value("main"); QVERIFY(mainProduct); QCOMPARE(mainProduct->dependencies.count(), 2); foreach (const ResolvedProductConstPtr &p, mainProduct->dependencies) { QCOMPARE(p->name, QLatin1String("dep")); QVERIFY(p->profile == "p1" || p->profile == "p2"); } } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::defaultValue() { bool exceptionCaught = false; try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("defaultvalue/egon.qbs")); QFETCH(QString, prop1Value); QVariantMap overridden; if (!prop1Value.isEmpty()) overridden.insert("lower.prop1", prop1Value); params.setOverriddenValues(overridden); TopLevelProjectPtr project = loader->loadProject(params); QVERIFY(project); QHash products = productsFromProject(project); QCOMPARE(products.count(), 2); const ResolvedProductPtr product = products.value("egon"); QVERIFY(product); QStringList propertyName = QStringList() << "modules" << "lower" << "prop2"; QVariant propertyValue = getConfigProperty(product->moduleProperties->value(), propertyName); QFETCH(QVariant, expectedProp2Value); QCOMPARE(propertyValue, expectedProp2Value); propertyName = QStringList() << "modules" << "lower" << "listProp"; propertyValue = getConfigProperty(product->moduleProperties->value(), propertyName); QFETCH(QVariant, expectedListPropValue); QEXPECT_FAIL("controlling property not overwritten", "QBS-845", Continue); QCOMPARE(propertyValue.toStringList(), expectedListPropValue.toStringList()); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::defaultValue_data() { QTest::addColumn("prop1Value"); QTest::addColumn("expectedProp2Value"); QTest::addColumn("expectedListPropValue"); QTest::newRow("controlling property with random value") << "random" << QVariant("withoutBlubb") << QVariant(QStringList({"other", "other"})); QTest::newRow("controlling property with blubb value") << "blubb" << QVariant("withBlubb") << QVariant(QStringList({"blubb", "other", "blubb", "other"})); QTest::newRow("controlling property with egon value") << "egon" << QVariant("withEgon") << QVariant(QStringList({"egon", "other"})); QTest::newRow("controlling property not overwritten") << "" << QVariant("withBlubb") << QVariant(QStringList({"blubb", "other", "blubb", "other"})); } void TestLanguage::environmentVariable() { bool exceptionCaught = false; try { // Create new environment: const QString varName = QLatin1String("PRODUCT_NAME"); const QString productName = QLatin1String("MyApp") + QString::number(qrand()); QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert(varName, productName); QProcessEnvironment origEnv = defaultParameters.environment(); // store orig environment defaultParameters.setEnvironment(env); defaultParameters.setProjectFilePath(testProject("environmentvariable.qbs")); project = loader->loadProject(defaultParameters); defaultParameters.setEnvironment(origEnv); // reset environment QVERIFY(project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value(productName); QVERIFY(product); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::erroneousFiles_data() { QTest::addColumn("errorMessage"); QTest::newRow("unknown_module") << "Product dependency 'neitherModuleNorProduct' not found"; QTest::newRow("multiple_exports") << "Multiple Export items in one product are prohibited."; QTest::newRow("multiple_properties_in_subproject") << "Multiple instances of item 'Properties' found where at most one " "is allowed."; QTest::newRow("importloop1") << "Loop detected when importing"; QTest::newRow("nonexistentouter") << "Can't find variable: outer"; QTest::newRow("invalid_file") << "does not exist"; QTest::newRow("invalid_property_type") << "Unknown type 'nonsense' in property declaration."; QTest::newRow("reserved_name_in_import") << "Cannot reuse the name of built-in extension 'TextFile'."; QTest::newRow("throw_in_property_binding") << "something is wrong"; QTest::newRow("dependency_cycle") << "Cyclic dependencies detected."; QTest::newRow("references_cycle") << "Cycle detected while referencing file 'references_cycle.qbs'."; QTest::newRow("subproject_cycle") << "Cycle detected while loading subproject file 'subproject_cycle.qbs'."; QTest::newRow("invalid_stringlist_element") << "Expected array element of type String at index 1."; QTest::newRow("undefined_stringlist_element") << "Array element at index 1 is undefined. String expected."; QTest::newRow("undeclared_item") << "Item 'cpp' is not declared."; QTest::newRow("undeclared_property_wrapper") << "Property 'doesntexist' is not declared."; QTest::newRow("undeclared_property_in_export_item") << "Property 'blubb' is not declared."; QTest::newRow("undeclared_property_in_export_item2") << "Item 'something' is not declared."; QTest::newRow("undeclared_property_in_export_item3") << "Property 'blubb' is not declared."; QTest::newRow("unknown_item_type") << "Unexpected item type 'Narf'"; QTest::newRow("invalid_child_item_type") << "Items of type 'Project' cannot contain items of type 'Depends'."; QTest::newRow("conflicting_fileTagsFilter") << "Conflicting fileTagsFilter in Group items"; QTest::newRow("duplicate_sources") << "Duplicate source file '.*main.cpp' " "at .*duplicate_sources.qbs:4:12 and .*duplicate_sources.qbs:6:16."; QTest::newRow("duplicate_sources_wildcards") << "Duplicate source file '.*duplicate_sources_wildcards.qbs' " "at .*duplicate_sources_wildcards.qbs:4:12 " "and .*duplicate_sources_wildcards.qbs:6:16."; QTest::newRow("oldQbsVersion") << "The project requires at least qbs version \\d+\\.\\d+.\\d+, " "but this is qbs version " QBS_VERSION "."; QTest::newRow("wrongQbsVersionFormat") << "The value '.*' of Project.minimumQbsVersion is not a valid version string."; QTest::newRow("properties-item-with-invalid-condition") << "TypeError: Result of expression 'cpp.nonexistingproperty'"; QTest::newRow("misused-inherited-property") << "Binding to non-item property"; QTest::newRow("undeclared_property_in_Properties_item") << "Item 'blubb' is not declared"; } void TestLanguage::erroneousFiles() { QFETCH(QString, errorMessage); QString fileName = QString::fromLocal8Bit(QTest::currentDataTag()) + QLatin1String(".qbs"); try { defaultParameters.setProjectFilePath(testProject("/erroneous/") + fileName); loader->loadProject(defaultParameters); } catch (const ErrorInfo &e) { if (!e.toString().contains(QRegExp(errorMessage))) { qDebug() << "Message: " << e.toString(); qDebug() << "Expected: " << errorMessage; QFAIL("Unexpected error message."); } return; } QEXPECT_FAIL("misused-inherited-property", "QBS-847", Continue); QEXPECT_FAIL("undeclared_property_in_Properties_item", "Too expensive to check", Continue); QVERIFY(!"No error thrown on invalid input."); } void TestLanguage::exports() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("exports.qbs")); TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(project); QHash products = productsFromProject(project); QCOMPARE(products.count(), 12); ResolvedProductPtr product; product = products.value("myapp"); QVERIFY(product); QStringList propertyName = QStringList() << "modules" << "dummy" << "defines"; QVariant propertyValue = getConfigProperty(product->moduleProperties->value(), propertyName); QCOMPARE(propertyValue.toStringList(), QStringList() << "BUILD_MYAPP" << "USE_MYLIB" << "USE_MYLIB2"); propertyName = QStringList() << "modules" << "dummy" << "includePaths"; QVariantList propertyValues = getConfigProperty(product->moduleProperties->value(), propertyName).toList(); QCOMPARE(propertyValues.count(), 3); QVERIFY(propertyValues.at(0).toString().endsWith("/app")); QVERIFY(propertyValues.at(1).toString().endsWith("/subdir/lib")); QVERIFY(propertyValues.at(2).toString().endsWith("/subdir2/lib")); QCOMPARE(PropertyFinder().propertyValue(product->moduleProperties->value(), "dummy", "productName").toString(), QString("myapp")); product = products.value("mylib"); QVERIFY(product); propertyName = QStringList() << "modules" << "dummy" << "defines"; propertyValue = getConfigProperty(product->moduleProperties->value(), propertyName); QCOMPARE(propertyValue.toStringList(), QStringList() << "BUILD_MYLIB"); product = products.value("mylib2"); QVERIFY(product); propertyName = QStringList() << "modules" << "dummy" << "defines"; propertyValue = getConfigProperty(product->moduleProperties->value(), propertyName); QCOMPARE(propertyValue.toStringList(), QStringList() << "BUILD_MYLIB2"); product = products.value("A"); QVERIFY(product); QVERIFY(product->dependencies.contains(products.value("B"))); QVERIFY(product->dependencies.contains(products.value("C"))); QVERIFY(product->dependencies.contains(products.value("D"))); product = products.value("B"); QVERIFY(product); QVERIFY(product->dependencies.isEmpty()); product = products.value("C"); QVERIFY(product); QVERIFY(product->dependencies.isEmpty()); product = products.value("D"); QVERIFY(product); QVERIFY(product->dependencies.isEmpty()); product = products.value("myapp2"); QVERIFY(product); propertyName = QStringList() << "modules" << "dummy" << "cxxFlags"; propertyValue = getConfigProperty(product->moduleProperties->value(), propertyName); QCOMPARE(propertyValue.toStringList(), QStringList() << "-bar"); propertyName = QStringList() << "modules" << "dummy" << "defines"; propertyValue = getConfigProperty(product->moduleProperties->value(), propertyName); QCOMPARE(propertyValue.toStringList(), QStringList() << "ABC"); QCOMPARE(PropertyFinder().propertyValue(product->moduleProperties->value(), "dummy", "productName").toString(), QString("myapp2")); QCOMPARE(PropertyFinder().propertyValue(product->moduleProperties->value(), "dummy", "upperCaseProductName").toString(), QString("MYAPP2")); // Check whether we're returning incorrect cached values. product = products.value("myapp3"); QVERIFY(product); QCOMPARE(PropertyFinder().propertyValue(product->moduleProperties->value(), "dummy", "productName").toString(), QString("myapp3")); QCOMPARE(PropertyFinder().propertyValue(product->moduleProperties->value(), "dummy", "upperCaseProductName").toString(), QString("MYAPP3")); // Verify we refer to the right "project" variable. product = products.value("sub p2"); QVERIFY(product); QCOMPARE(PropertyFinder().propertyValue(product->moduleProperties->value(), "dummy", "someString").toString(), QString("sub1")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::fileContextProperties() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("filecontextproperties.qbs")); project = loader->loadProject(defaultParameters); QVERIFY(project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value("product1"); QVERIFY(product); QVariantMap cfg = product->productProperties; QCOMPARE(cfg.value("narf").toString(), defaultParameters.projectFilePath()); QString dirPath = QFileInfo(defaultParameters.projectFilePath()).absolutePath(); QCOMPARE(cfg.value("zort").toString(), dirPath); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::getNativeSetting() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("getNativeSetting.qbs")); project = loader->loadProject(defaultParameters); QString expectedProductName; if (HostOsInfo::isOsxHost()) expectedProductName = QLatin1String("Mac OS X"); else if (HostOsInfo::isWindowsHost()) expectedProductName = QLatin1String("Windows"); else expectedProductName = QLatin1String("Unix"); QVERIFY(project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value(expectedProductName); QVERIFY(product); ResolvedProductPtr product2 = products.value(QLatin1String("fallback")); QVERIFY(product2); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::groupConditions_data() { QTest::addColumn("groupCount"); QTest::addColumn >("groupEnabled"); QTest::newRow("init") << 0 << QList(); QTest::newRow("no_condition_no_group") << 1 << (QList() << true); QTest::newRow("no_condition") << 2 << (QList() << true << true); QTest::newRow("true_condition") << 2 << (QList() << true << true); QTest::newRow("false_condition") << 2 << (QList() << true << false); QTest::newRow("true_condition_from_product") << 2 << (QList() << true << true); QTest::newRow("true_condition_from_project") << 2 << (QList() << true << true); QTest::newRow("condition_accessing_module_property") << 2 << (QList() << true << false); QTest::newRow("cleanup") << 0 << QList(); } void TestLanguage::groupConditions() { HANDLE_INIT_CLEANUP_DATATAGS("groupconditions.qbs"); QFETCH(int, groupCount); QFETCH(QList, groupEnabled); QCOMPARE(groupCount, groupEnabled.count()); const QHash products = productsFromProject(project); const QString productName = QString::fromLocal8Bit(QTest::currentDataTag()); ResolvedProductPtr product = products.value(productName); QVERIFY(product); QCOMPARE(product->name, productName); QCOMPARE(product->groups.count(), groupCount); for (int i = 0; i < groupCount; ++i) { if (product->groups.at(i)->enabled != groupEnabled.at(i)) { QFAIL(qPrintable( QString("groups.at(%1)->enabled != %2").arg(i).arg(groupEnabled.at(i)))); } } } void TestLanguage::groupName() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("groupname.qbs")); TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(project); QHash products = productsFromProject(project); QCOMPARE(products.count(), 2); ResolvedProductPtr product = products.value("MyProduct"); QVERIFY(product); QCOMPARE(product->groups.count(), 2); GroupConstPtr group = product->groups.at(0); QVERIFY(group); QCOMPARE(group->name, QString("MyProduct")); group = product->groups.at(1); QVERIFY(group); QCOMPARE(group->name, QString("MyProduct.MyGroup")); product = products.value("My2ndProduct"); QVERIFY(product); QCOMPARE(product->groups.count(), 3); group = product->groups.at(0); QVERIFY(group); QCOMPARE(group->name, QString("My2ndProduct")); group = product->groups.at(1); QVERIFY(group); QCOMPARE(group->name, QString("My2ndProduct.MyGroup")); group = product->groups.at(2); QVERIFY(group); QCOMPARE(group->name, QString("Group 2")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::homeDirectory() { try { defaultParameters.setProjectFilePath(testProject("homeDirectory.qbs")); ResolvedProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(project); QHash products = productsFromProject(project); QCOMPARE(products.count(), 1); ResolvedProductPtr product = products.value("home"); QVERIFY(product); QDir dir = QDir::home(); QCOMPARE(product->productProperties.value("home").toString(), dir.canonicalPath()); QCOMPARE(product->productProperties.value("homeSlash").toString(), dir.canonicalPath()); dir.cdUp(); QCOMPARE(product->productProperties.value("homeUp").toString(), dir.canonicalPath()); dir = QDir::home(); QCOMPARE(product->productProperties.value("homeFile").toString(), dir.filePath("a")); QCOMPARE(product->productProperties.value("bogus1").toString(), FileInfo::resolvePath(product->sourceDirectory, QLatin1String("a~b"))); QCOMPARE(product->productProperties.value("bogus2").toString(), FileInfo::resolvePath(product->sourceDirectory, QLatin1String("a/~/bb"))); QCOMPARE(product->productProperties.value("user").toString(), FileInfo::resolvePath(product->sourceDirectory, QLatin1String("~foo/bar"))); } catch (const ErrorInfo &e) { qDebug() << e.toString(); } } void TestLanguage::identifierSearch_data() { QTest::addColumn("expectedHasNarf"); QTest::addColumn("expectedHasZort"); QTest::addColumn("sourceCode"); QTest::newRow("no narf, no zort") << false << false << QString( "Product {\n" " name: {\n" " var foo = 'bar';\n" " print(foo);\n" " return foo;\n" " }\n" "}\n"); QTest::newRow("narf, no zort") << true << false << QString( "Product {\n" " name: {\n" " var foo = 'zort';\n" " print(narf + foo);\n" " return foo;\n" " }\n" "}\n"); QTest::newRow("no narf, zort") << false << true << QString( "Product {\n" " name: {\n" " var foo = 'narf';\n" " print(zort + foo);\n" " return foo;\n" " }\n" "}\n"); QTest::newRow("narf, zort") << true << true << QString( "Product {\n" " name: {\n" " var foo = narf;\n" " foo = foo + zort;\n" " return foo;\n" " }\n" "}\n"); QTest::newRow("2 narfs, 1 zort") << true << true << QString( "Product {\n" " name: {\n" " var foo = narf;\n" " foo = narf + foo + zort;\n" " return foo;\n" " }\n" "}\n"); } void TestLanguage::identifierSearch() { QFETCH(bool, expectedHasNarf); QFETCH(bool, expectedHasZort); QFETCH(QString, sourceCode); bool hasNarf = !expectedHasNarf; bool hasZort = !expectedHasZort; IdentifierSearch isearch; isearch.add("narf", &hasNarf); isearch.add("zort", &hasZort); QbsQmlJS::Engine engine; QbsQmlJS::Lexer lexer(&engine); lexer.setCode(sourceCode, 1); QbsQmlJS::Parser parser(&engine); QVERIFY(parser.parse()); QVERIFY(parser.ast()); isearch.start(parser.ast()); QCOMPARE(hasNarf, expectedHasNarf); QCOMPARE(hasZort, expectedHasZort); } void TestLanguage::idUsage() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("idusage.qbs")); TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(project); QHash products = productsFromProject(project); QCOMPARE(products.count(), 3); QVERIFY(products.contains("product1_1")); QVERIFY(products.contains("product2_2")); QVERIFY(products.contains("product3_3")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QVERIFY(!exceptionCaught); } void TestLanguage::importCollection() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("import-collection/project.qbs")); const TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(project); QHash products = productsFromProject(project); const ResolvedProductConstPtr product = products.value("da product"); QCOMPARE(product->productProperties.value("targetName").toString(), QLatin1String("C1f1C1f2C2f1C2f2")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QVERIFY(!exceptionCaught); } void TestLanguage::invalidBindingInDisabledItem() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("invalidBindingInDisabledItem.qbs")); TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(project); QHash products = productsFromProject(project); QCOMPARE(products.count(), 2); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QVERIFY(!exceptionCaught); } class JSSourceValueCreator { FileContextPtr m_fileContext; QList m_strings; public: JSSourceValueCreator(const FileContextPtr &fileContext) : m_fileContext(fileContext) { } ~JSSourceValueCreator() { qDeleteAll(m_strings); } JSSourceValuePtr create(const QString &sourceCode) { JSSourceValuePtr value = JSSourceValue::create(); value->setFile(m_fileContext); QString *str = new QString(sourceCode); m_strings += str; value->setSourceCode(QStringRef(str)); return value; } }; void TestLanguage::itemPrototype() { FileContextPtr fileContext = FileContext::create(); JSSourceValueCreator sourceValueCreator(fileContext); ItemPool pool; Item *proto = Item::create(&pool); proto->setProperty("x", sourceValueCreator.create("1")); proto->setProperty("y", sourceValueCreator.create("1")); Item *item = Item::create(&pool); item->setPrototype(proto); item->setProperty("y", sourceValueCreator.create("x + 1")); item->setProperty("z", sourceValueCreator.create("2")); Evaluator evaluator(m_engine, m_logger); QCOMPARE(evaluator.property(proto, "x").toVariant().toInt(), 1); QCOMPARE(evaluator.property(proto, "y").toVariant().toInt(), 1); QVERIFY(!evaluator.property(proto, "z").isValid()); QCOMPARE(evaluator.property(item, "x").toVariant().toInt(), 1); QCOMPARE(evaluator.property(item, "y").toVariant().toInt(), 2); QCOMPARE(evaluator.property(item, "z").toVariant().toInt(), 2); } void TestLanguage::itemScope() { FileContextPtr fileContext = FileContext::create(); JSSourceValueCreator sourceValueCreator(fileContext); ItemPool pool; Item *scope1 = Item::create(&pool); scope1->setProperty("x", sourceValueCreator.create("1")); Item *scope2 = Item::create(&pool); scope2->setScope(scope1); scope2->setProperty("y", sourceValueCreator.create("x + 1")); Item *item = Item::create(&pool); item->setScope(scope2); item->setProperty("z", sourceValueCreator.create("x + y")); Evaluator evaluator(m_engine, m_logger); QCOMPARE(evaluator.property(scope1, "x").toVariant().toInt(), 1); QCOMPARE(evaluator.property(scope2, "y").toVariant().toInt(), 2); QVERIFY(!evaluator.property(scope2, "x").isValid()); QCOMPARE(evaluator.property(item, "z").toVariant().toInt(), 3); } void TestLanguage::jsExtensions() { QFile file(testProject("jsextensions.js")); QVERIFY(file.open(QFile::ReadOnly)); QTextStream ts(&file); QString code = ts.readAll(); QVERIFY(!code.isEmpty()); QScriptValue evaluated = m_engine->evaluate(code, file.fileName(), 1); if (m_engine->hasErrorOrException(evaluated)) { qDebug() << m_engine->uncaughtExceptionBacktrace(); QFAIL(qPrintable(m_engine->lastErrorString(evaluated))); } } void TestLanguage::jsImportUsedInMultipleScopes_data() { QTest::addColumn("buildVariant"); QTest::addColumn("expectedProductName"); QTest::newRow("debug") << QString("debug") << QString("MyProduct_debug"); QTest::newRow("release") << QString("release") << QString("MyProduct"); } void TestLanguage::jsImportUsedInMultipleScopes() { QFETCH(QString, buildVariant); QFETCH(QString, expectedProductName); bool exceptionCaught = false; try { SetupProjectParameters params = defaultParameters; params.setProjectFilePath(testProject("jsimportsinmultiplescopes.qbs")); params.setBuildVariant(buildVariant); params.expandBuildConfiguration(); TopLevelProjectPtr project = loader->loadProject(params); QVERIFY(project); QHash products = productsFromProject(project); QCOMPARE(products.count(), 1); ResolvedProductPtr product = products.values().first(); QVERIFY(product); QCOMPARE(product->name, expectedProductName); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QVERIFY(!exceptionCaught); } void TestLanguage::moduleProperties_data() { QTest::addColumn("propertyName"); QTest::addColumn("expectedValues"); QTest::newRow("init") << QString() << QStringList(); QTest::newRow("merge_lists") << "defines" << (QStringList() << "THE_PRODUCT" << "QT_CORE" << "QT_GUI" << "QT_NETWORK"); QTest::newRow("merge_lists_and_values") << "defines" << (QStringList() << "THE_PRODUCT" << "QT_CORE" << "QT_GUI" << "QT_NETWORK"); QTest::newRow("merge_lists_with_duplicates") << "cxxFlags" << (QStringList() << "-foo" << "BAR" << "-foo" << "BAZ"); QTest::newRow("merge_lists_with_prototype_values") << "rpaths" << (QStringList() << "/opt/qt/lib" << "$ORIGIN"); QTest::newRow("list_property_that_references_product") << "listProp" << (QStringList() << "x" << "123"); QTest::newRow("list_property_depending_on_overridden_property") << "listProp2" << (QStringList() << "PRODUCT_STUFF" << "DEFAULT_STUFF" << "EXTRA_STUFF"); QTest::newRow("cleanup") << QString() << QStringList(); } void TestLanguage::moduleProperties() { HANDLE_INIT_CLEANUP_DATATAGS("moduleproperties.qbs"); QFETCH(QString, propertyName); QFETCH(QStringList, expectedValues); QHash products = productsFromProject(project); const QString productName = QString::fromLocal8Bit(QTest::currentDataTag()); ResolvedProductPtr product = products.value(productName); QVERIFY(product); QVariantList values = PropertyFinder().propertyValues(product->moduleProperties->value(), "dummy", propertyName); QStringList valueStrings; foreach (const QVariant &v, values) valueStrings += v.toString(); QEXPECT_FAIL("list_property_depending_on_overridden_property", "QBS-845", Continue); QCOMPARE(valueStrings, expectedValues); } void TestLanguage::moduleScope() { class IntPropertyFinder { const QVariantMap &m_properties; public: IntPropertyFinder(const QVariantMap &properties) : m_properties(properties) {} int intValue(const QString &name) { return PropertyFinder().propertyValue(m_properties, "scopemod", name).toInt(); } }; bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("modulescope.qbs")); TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(project); QHash products = productsFromProject(project); QCOMPARE(products.count(), 1); ResolvedProductPtr product = products.value("product1"); QVERIFY(product); IntPropertyFinder ipf(product->moduleProperties->value()); QCOMPARE(ipf.intValue("a"), 2); // overridden in module instance QCOMPARE(ipf.intValue("b"), 1); // genuine QCOMPARE(ipf.intValue("c"), 3); // genuine, dependent on overridden value QCOMPARE(ipf.intValue("d"), 2); // genuine, dependent on genuine value QCOMPARE(ipf.intValue("e"), 1); // genuine QCOMPARE(ipf.intValue("f"), 2); // overridden QCOMPARE(ipf.intValue("g"), 156); // overridden, dependent on product properties QCOMPARE(ipf.intValue("h"), 158); // overridden, base dependent on product properties } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::modules_data() { QTest::addColumn("expectedModulesInProduct"); QTest::addColumn("expectedProductProperty"); QTest::newRow("init") << QStringList(); QTest::newRow("no_modules") << (QStringList() << "qbs") << QString(); QTest::newRow("qt_core") << (QStringList() << "qbs" << "dummy" << "dummyqt.core") << QString("1.2.3"); QTest::newRow("qt_gui") << (QStringList() << "qbs" << "dummy" << "dummyqt.core" << "dummyqt.gui") << QString("guiProperty"); QTest::newRow("qt_gui_network") << (QStringList() << "qbs" << "dummy" << "dummyqt.core" << "dummyqt.gui" << "dummyqt.network") << QString("guiProperty,networkProperty"); QTest::newRow("deep_module_name") << (QStringList() << "qbs" << "dummy" << "dummy.deep.moat") << QString("abysmal"); QTest::newRow("deep_module_name_submodule_syntax1") << (QStringList() << "qbs" << "dummy" << "dummy.deep.moat") << QString("abysmal"); QTest::newRow("deep_module_name_submodule_syntax2") << (QStringList() << "qbs" << "dummy" << "dummy.deep.moat") << QString("abysmal"); QTest::newRow("dummy_twice") << (QStringList() << "qbs" << "dummy") << QString(); QTest::newRow("cleanup") << QStringList(); } void TestLanguage::modules() { HANDLE_INIT_CLEANUP_DATATAGS("modules.qbs"); QFETCH(QStringList, expectedModulesInProduct); QFETCH(QString, expectedProductProperty); QHash products = productsFromProject(project); const QString productName = QString::fromLocal8Bit(QTest::currentDataTag()); ResolvedProductPtr product = products.value(productName); QVERIFY(product); QCOMPARE(product->name, productName); QStringList modulesInProduct; foreach (ResolvedModuleConstPtr m, product->modules) modulesInProduct += m->name; modulesInProduct.sort(); expectedModulesInProduct.sort(); QCOMPARE(modulesInProduct, expectedModulesInProduct); QCOMPARE(product->productProperties.value("foo").toString(), expectedProductProperty); } void TestLanguage::outerInGroup() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("outerInGroup.qbs")); TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(project); QHash products = productsFromProject(project); QCOMPARE(products.count(), 1); ResolvedProductPtr product = products.value("OuterInGroup"); QVERIFY(product); QCOMPARE(product->groups.count(), 2); GroupPtr group = product->groups.at(0); QVERIFY(group); QCOMPARE(group->name, product->name); QCOMPARE(group->files.count(), 1); SourceArtifactConstPtr artifact = group->files.first(); QVariant installDir = artifact->properties->qbsPropertyValue("installDir"); QCOMPARE(installDir.toString(), QString("/somewhere")); group = product->groups.at(1); QVERIFY(group); QCOMPARE(group->name, QString("Special Group")); QCOMPARE(group->files.count(), 1); artifact = group->files.first(); installDir = artifact->properties->qbsPropertyValue("installDir"); QCOMPARE(installDir.toString(), QString("/somewhere/else")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::pathProperties() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("pathproperties.qbs")); project = loader->loadProject(defaultParameters); QVERIFY(project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value("product1"); QVERIFY(product); QString projectFileDir = QFileInfo(defaultParameters.projectFilePath()).absolutePath(); const QVariantMap productProps = product->productProperties; const QVariantMap moduleProps = product->moduleProperties->value(); QCOMPARE(productProps.value("projectFileDir").toString(), projectFileDir); QStringList filesInProjectFileDir = QStringList() << FileInfo::resolvePath(projectFileDir, "aboutdialog.h") << FileInfo::resolvePath(projectFileDir, "aboutdialog.cpp"); QCOMPARE(productProps.value("filesInProjectFileDir").toStringList(), filesInProjectFileDir); QStringList includePaths = getConfigProperty(moduleProps, QStringList() << "modules" << "dummy" << "includePaths").toStringList(); QCOMPARE(includePaths, QStringList() << projectFileDir); QCOMPARE(productProps.value("base_fileInProductDir").toString(), FileInfo::resolvePath(projectFileDir, QLatin1String("foo"))); QCOMPARE(productProps.value("base_fileInBaseProductDir").toString(), FileInfo::resolvePath(projectFileDir, QLatin1String("subdir/bar"))); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::profileValuesAndOverriddenValues() { bool exceptionCaught = false; try { Settings settings((QString())); TemporaryProfile tp(QLatin1String("tst_lang_profile"), &settings); Profile profile = tp.p; profile.setValue("dummy.defines", "IN_PROFILE"); profile.setValue("dummy.cFlags", "IN_PROFILE"); profile.setValue("dummy.cxxFlags", "IN_PROFILE"); profile.setValue("qbs.architecture", "x86"); SetupProjectParameters parameters = defaultParameters; parameters.setTopLevelProfile(profile.name()); QVariantMap overriddenValues; overriddenValues.insert("dummy.cFlags", "OVERRIDDEN"); parameters.setOverriddenValues(overriddenValues); parameters.setProjectFilePath(testProject("profilevaluesandoverriddenvalues.qbs")); parameters.expandBuildConfiguration(); project = loader->loadProject(parameters); QVERIFY(project); QHash products = productsFromProject(project); ResolvedProductPtr product = products.value("product1"); QVERIFY(product); PropertyFinder pf; QVariantList values; values = pf.propertyValues(product->moduleProperties->value(), "dummy", "cxxFlags"); QCOMPARE(values.length(), 1); QCOMPARE(values.first().toString(), QString("IN_PROFILE")); values = pf.propertyValues(product->moduleProperties->value(), "dummy", "defines"); QCOMPARE(values, QVariantList() << QLatin1String("IN_FILE") << QLatin1String("IN_PROFILE")); values = pf.propertyValues(product->moduleProperties->value(), "dummy", "cFlags"); QCOMPARE(values.length(), 1); QCOMPARE(values.first().toString(), QString("OVERRIDDEN")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::productConditions() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("productconditions.qbs")); TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(project); QHash products = productsFromProject(project); QCOMPARE(products.count(), 4); ResolvedProductPtr product; product = products.value("product_no_condition"); QVERIFY(product); QVERIFY(product->enabled); product = products.value("product_true_condition"); QVERIFY(product); QVERIFY(product->enabled); product = products.value("product_condition_dependent_of_module"); QVERIFY(product); QVERIFY(product->enabled); product = products.value("product_false_condition"); QVERIFY(product); QVERIFY(!product->enabled); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::productDirectories() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("productdirectories.qbs")); ResolvedProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(project); QHash products = productsFromProject(project); QCOMPARE(products.count(), 1); ResolvedProductPtr product; product = products.value("MyApp"); QVERIFY(product); const QVariantMap config = product->productProperties; QCOMPARE(config.value(QLatin1String("buildDirectory")).toString(), product->buildDirectory()); QCOMPARE(config.value(QLatin1String("sourceDirectory")).toString(), testDataDir()); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::propertiesBlocks_data() { QTest::addColumn("propertyName"); QTest::addColumn("expectedValues"); QTest::addColumn("expectedStringValue"); QTest::newRow("init") << QString() << QStringList() << QString(); QTest::newRow("property_overwrite") << QString("dummy.defines") << QStringList("OVERWRITTEN") << QString(); QTest::newRow("property_overwrite_no_outer") << QString("dummy.defines") << QStringList("OVERWRITTEN") << QString(); QTest::newRow("property_append_to_outer") << QString("dummy.defines") << (QStringList() << QString("ONE") << QString("TWO")) << QString(); QTest::newRow("multiple_exclusive_properties") << QString("dummy.defines") << QStringList("OVERWRITTEN") << QString(); QTest::newRow("multiple_exclusive_properties_no_outer") << QString("dummy.defines") << QStringList("OVERWRITTEN") << QString(); QTest::newRow("multiple_exclusive_properties_append_to_outer") << QString("dummy.defines") << (QStringList() << QString("ONE") << QString("TWO")) << QString(); QTest::newRow("condition_refers_to_product_property") << QString("dummy.defines") << QStringList("OVERWRITTEN") << QString("OVERWRITTEN"); QTest::newRow("condition_refers_to_project_property") << QString("dummy.defines") << QStringList("OVERWRITTEN") << QString("OVERWRITTEN"); QTest::newRow("ambiguous_properties") << QString("dummy.defines") << (QStringList() << QString("ONE") << QString("TWO")) << QString(); QTest::newRow("inheritance_overwrite_in_subitem") << QString("dummy.defines") << (QStringList() << QString("OVERWRITTEN_IN_SUBITEM")) << QString(); QTest::newRow("inheritance_retain_base1") << QString("dummy.defines") << (QStringList() << QString("BASE") << QString("SUB")) << QString(); QTest::newRow("inheritance_retain_base2") << QString("dummy.defines") << (QStringList() << QString("BASE") << QString("SUB")) << QString(); QTest::newRow("inheritance_retain_base3") << QString("dummy.defines") << (QStringList() << QString("BASE") << QString("SUB")) << QString(); QTest::newRow("inheritance_retain_base4") << QString("dummy.defines") << (QStringList() << QString("BASE")) << QString(); QTest::newRow("inheritance_condition_in_subitem1") << QString("dummy.defines") << (QStringList() << QString("SOMETHING") << QString("SUB")) << QString(); QTest::newRow("inheritance_condition_in_subitem2") << QString("dummy.defines") << (QStringList() << QString("SOMETHING")) << QString(); QTest::newRow("condition_references_id") << QString("dummy.defines") << (QStringList() << QString("OVERWRITTEN")) << QString(); QTest::newRow("conditional-depends") << QString("dummy.defines") << QStringList() << QString(); QTest::newRow("cleanup") << QString() << QStringList() << QString(); } void TestLanguage::propertiesBlocks() { HANDLE_INIT_CLEANUP_DATATAGS("propertiesblocks.qbs"); QFETCH(QString, propertyName); QFETCH(QStringList, expectedValues); QFETCH(QString, expectedStringValue); QVERIFY(project); QHash products = productsFromProject(project); const QString productName = QString::fromLocal8Bit(QTest::currentDataTag()); ResolvedProductPtr product = products.value(productName); QVERIFY(product); QCOMPARE(product->name, productName); QVariant v = productPropertyValue(product, propertyName); QCOMPARE(v.toStringList(), expectedValues); if (!expectedStringValue.isEmpty()) { v = productPropertyValue(product, "someString"); QCOMPARE(v.toString(), expectedStringValue); } } void TestLanguage::propertiesBlockInGroup() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("properties-block-in-group.qbs")); const TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(project); QCOMPARE(project->allProducts().count(), 1); const ResolvedProductConstPtr product = project->allProducts().first(); const auto groupIt = std::find_if(product->groups.constBegin(), product->groups.constEnd(), [](const GroupConstPtr &g) { return g->name == "the group"; }); QVERIFY(groupIt != product->groups.constEnd()); const QVariantMap propertyMap = (*groupIt)->properties->value(); const QVariantList value = PropertyFinder().propertyValues(propertyMap, "dummy", "defines"); QStringList stringListValue; std::transform(value.constBegin(), value.constEnd(), std::back_inserter(stringListValue), [](const QVariant &v) { return v.toString(); }); QCOMPARE(stringListValue, QStringList() << "BASEDEF" << "FEATURE_ENABLED"); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::qbsPropertiesInProjectCondition() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath( testProject("qbs-properties-in-project-condition.qbs")); const TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(project); const QHash products = productsFromProject(project); QCOMPARE(products.count(), 0); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::qualifiedId() { QString str = "foo.bar.baz"; QualifiedId id = QualifiedId::fromString(str); QCOMPARE(id.count(), 3); QCOMPARE(id.toString(), str); id = QualifiedId("blubb.di.blubb"); // c'tor does not split QCOMPARE(id.count(), 1); QList ids; ids << QualifiedId::fromString("a") << QualifiedId::fromString("a.a") << QualifiedId::fromString("b") << QualifiedId::fromString("c.a") << QualifiedId::fromString("c.b.a") << QualifiedId::fromString("c.c"); QList sorted = ids; std::sort(sorted.begin(), sorted.end()); QCOMPARE(ids, sorted); } void TestLanguage::recursiveProductDependencies() { bool exceptionCaught = false; try { defaultParameters.setProjectFilePath( testProject("recursive-dependencies/recursive-dependencies.qbs")); const TopLevelProjectPtr project = loader->loadProject(defaultParameters); QVERIFY(project); const QHash products = productsFromProject(project); QCOMPARE(products.count(), 4); const ResolvedProductConstPtr p1 = products.value("p1"); QVERIFY(p1); const ResolvedProductConstPtr p2 = products.value("p2"); QVERIFY(p2); const ResolvedProductPtr p3 = products.value("p3"); QVERIFY(p3); const ResolvedProductPtr p4 = products.value("p4"); QVERIFY(p4); QVERIFY(p1->dependencies == QSet() << p3 << p4); QVERIFY(p2->dependencies == QSet() << p3 << p4); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } void TestLanguage::fileTags_data() { QTest::addColumn("numberOfGroups"); QTest::addColumn("expectedFileTags"); QTest::newRow("init") << 0 << QStringList(); QTest::newRow("filetagger_project_scope") << 1 << (QStringList() << "cpp"); QTest::newRow("filetagger_product_scope") << 1 << (QStringList() << "asm"); QTest::newRow("filetagger_static_pattern") << 1 << (QStringList() << "yellow"); QTest::newRow("unknown_file_tag") << 1 << (QStringList() << "unknown-file-tag"); QTest::newRow("set_file_tag_via_group") << 2 << (QStringList() << "c++"); QTest::newRow("override_file_tag_via_group") << 2 << (QStringList() << "c++"); QTest::newRow("add_file_tag_via_group") << 2 << (QStringList() << "cpp" << "zzz"); QTest::newRow("cleanup") << 0 << QStringList(); } void TestLanguage::fileTags() { HANDLE_INIT_CLEANUP_DATATAGS("filetags.qbs"); QFETCH(int, numberOfGroups); QFETCH(QStringList, expectedFileTags); QHash products = productsFromProject(project); ResolvedProductPtr product; const QString productName = QString::fromLocal8Bit(QTest::currentDataTag()); QVERIFY(product = products.value(productName)); QCOMPARE(product->groups.count(), numberOfGroups); GroupPtr group = product->groups.last(); QVERIFY(group); QCOMPARE(group->files.count(), 1); SourceArtifactConstPtr sourceFile = group->files.first(); QStringList fileTags = sourceFile->fileTags.toStringList(); fileTags.sort(); QCOMPARE(fileTags, expectedFileTags); } void TestLanguage::wildcards_data() { QTest::addColumn("useGroup"); QTest::addColumn("filesToCreate"); QTest::addColumn("projectFileSubDir"); QTest::addColumn("prefix"); QTest::addColumn("patterns"); QTest::addColumn("excludePatterns"); QTest::addColumn("expected"); const bool useGroup = true; for (int i = 0; i <= 1; ++i) { const bool useGroup = i; const QByteArray dataTagSuffix = useGroup ? " group" : " nogroup"; QTest::newRow(QByteArray("simple 1") + dataTagSuffix) << useGroup << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp") << QString() << QString() << (QStringList() << "*.h") << QStringList() << (QStringList() << "foo.h" << "bar.h"); QTest::newRow(QByteArray("simple 2") + dataTagSuffix) << useGroup << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp") << QString() << QString() << (QStringList() << "foo.*") << QStringList() << (QStringList() << "foo.h" << "foo.cpp"); QTest::newRow(QByteArray("simple 3") + dataTagSuffix) << useGroup << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp") << QString() << QString() << (QStringList() << "*.h" << "*.cpp") << QStringList() << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp"); QTest::newRow(QByteArray("exclude 1") + dataTagSuffix) << useGroup << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp") << QString() << QString() << (QStringList() << "*.h" << "*.cpp") << (QStringList() << "bar*") << (QStringList() << "foo.h" << "foo.cpp"); QTest::newRow(QByteArray("exclude 2") + dataTagSuffix) << useGroup << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp") << QString() << QString() << (QStringList() << "*") << (QStringList() << "*.qbs") << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp"); QTest::newRow(QByteArray("non-recursive") + dataTagSuffix) << useGroup << (QStringList() << "a/foo.h" << "a/foo.cpp" << "a/b/bar.h" << "a/b/bar.cpp") << QString() << QString() << (QStringList() << "a/*") << QStringList() << (QStringList() << "a/foo.h" << "a/foo.cpp"); QTest::newRow(QByteArray("absolute paths") + dataTagSuffix) << useGroup << (QStringList() << "foo.h" << "foo.cpp" << "bar.h" << "bar.cpp") << QString() << QString() << (QStringList() << m_wildcardsTestDirPath + "/?oo.*") << QStringList() << (QStringList() << "foo.h" << "foo.cpp"); QTest::newRow(QByteArray("relative paths with dotdot") + dataTagSuffix) << useGroup << (QStringList() << "bar.h" << "bar.cpp") << QString("TheLaughingLlama") << QString() << (QStringList() << "../bar.*") << QStringList() << (QStringList() << "bar.h" << "bar.cpp"); } QTest::newRow(QByteArray("recursive 1")) << useGroup << (QStringList() << "a/foo.h" << "a/foo.cpp" << "a/b/bar.h" << "a/b/bar.cpp") << QString() << QString() << (QStringList() << "a/**") << QStringList() << (QStringList() << "a/foo.h" << "a/foo.cpp" << "a/b/bar.h" << "a/b/bar.cpp"); QTest::newRow(QByteArray("recursive 2")) << useGroup << (QStringList() << "d/1.h" << "b/d/1.h" << "b/c/d/1.h" << "d/e/1.h" << "b/d/e/1.h" << "b/c/d/e/1.h" << "a/d/1.h" << "a/b/d/1.h" << "a/b/c/d/1.h" << "a/d/e/1.h" << "a/b/d/e/1.h" << "a/b/c/d/e/1.h" << "a/d/1.cpp" << "a/b/d/1.cpp" << "a/b/c/d/1.h" << "a/d/e/1.cpp" << "a/b/d/e/1.cpp" << "a/b/c/d/e/1.cpp") << QString() << QString() << (QStringList() << "a/**/d/*.h") << QStringList() << (QStringList() << "a/d/1.h" << "a/b/d/1.h" << "a/b/c/d/1.h"); QTest::newRow(QByteArray("recursive 3")) << useGroup << (QStringList() << "a/foo.h" << "a/foo.cpp" << "a/b/bar.h" << "a/b/bar.cpp") << QString() << QString() << (QStringList() << "a/**/**/**") << QStringList() << (QStringList() << "a/foo.h" << "a/foo.cpp" << "a/b/bar.h" << "a/b/bar.cpp"); QTest::newRow(QByteArray("prefix")) << useGroup << (QStringList() << "subdir/foo.h" << "subdir/foo.cpp" << "subdir/bar.h" << "subdir/bar.cpp") << QString() << QString("subdir/") << (QStringList() << "*.h") << QStringList() << (QStringList() << "subdir/foo.h" << "subdir/bar.h"); QTest::newRow(QByteArray("non-existing absolute path")) << useGroup << QStringList() << QString() << QString("/dir") << (QStringList() << "*.whatever") << QStringList() << QStringList(); } void TestLanguage::wildcards() { QFETCH(bool, useGroup); QFETCH(QStringList, filesToCreate); QFETCH(QString, projectFileSubDir); QFETCH(QString, prefix); QFETCH(QStringList, patterns); QFETCH(QStringList, excludePatterns); QFETCH(QStringList, expected); // create test directory QDir::setCurrent(QDir::tempPath()); { QString errorMessage; if (QFile::exists(m_wildcardsTestDirPath)) { if (!removeDirectoryWithContents(m_wildcardsTestDirPath, &errorMessage)) { qDebug() << errorMessage; QVERIFY2(false, "removeDirectoryWithContents failed"); } } QVERIFY(QDir().mkdir(m_wildcardsTestDirPath)); } // create project file const QString groupName = "Keks"; QString dataTag = QString::fromLocal8Bit(QTest::currentDataTag()); dataTag.replace(' ', '_'); if (!projectFileSubDir.isEmpty()) { if (!projectFileSubDir.startsWith('/')) projectFileSubDir.prepend('/'); if (projectFileSubDir.endsWith('/')) projectFileSubDir.chop(1); QVERIFY(QDir().mkpath(m_wildcardsTestDirPath + projectFileSubDir)); } const QString projectFilePath = m_wildcardsTestDirPath + projectFileSubDir + "/test_" + dataTag + ".qbs"; { QFile projectFile(projectFilePath); QVERIFY(projectFile.open(QIODevice::WriteOnly)); QTextStream s(&projectFile); s << "import qbs.base 1.0" << endl << endl << "Application {" << endl << " name: \"MyProduct\"" << endl; if (useGroup) { s << " Group {" << endl << " name: " << toJSLiteral(groupName) << endl; } if (!prefix.isEmpty()) s << " prefix: " << toJSLiteral(prefix) << endl; if (!patterns.isEmpty()) s << " files: " << toJSLiteral(patterns) << endl; if (!excludePatterns.isEmpty()) s << " excludeFiles: " << toJSLiteral(excludePatterns) << endl; if (useGroup) s << " }" << endl; s << "}" << endl << endl; } // create files foreach (QString filePath, filesToCreate) { filePath.prepend(m_wildcardsTestDirPath + '/'); QFileInfo fi(filePath); if (!QDir(fi.path()).exists()) QVERIFY(QDir().mkpath(fi.path())); QFile file(filePath); QVERIFY(file.open(QIODevice::WriteOnly)); } // read the project bool exceptionCaught = false; ResolvedProductPtr product; try { defaultParameters.setProjectFilePath(projectFilePath); project = loader->loadProject(defaultParameters); QVERIFY(project); const QHash products = productsFromProject(project); product = products.value("MyProduct"); QVERIFY(product); GroupPtr group; if (useGroup) { QCOMPARE(product->groups.count(), 2); foreach (const GroupPtr &rg, product->groups) { if (rg->name == groupName) { group = rg; break; } } } else { QCOMPARE(product->groups.count(), 1); group = product->groups.first(); } QVERIFY(group); QCOMPARE(group->files.count(), 0); SourceWildCards::Ptr wildcards = group->wildcards; QVERIFY(wildcards); QStringList actualFilePaths; foreach (const SourceArtifactConstPtr &artifact, wildcards->files) { QString str = artifact->absoluteFilePath; int idx = str.indexOf(m_wildcardsTestDirPath); if (idx != -1) str.remove(0, idx + m_wildcardsTestDirPath.count() + 1); actualFilePaths << str; } actualFilePaths.sort(); expected.sort(); QCOMPARE(actualFilePaths, expected); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/tst_language.h000066400000000000000000000100411266132464200224620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef TST_LANGUAGE_H #define TST_LANGUAGE_H #include #include #include #include #include #include namespace qbs { namespace Internal { class QBS_EXPORT TestLanguage : public QObject { Q_OBJECT public: TestLanguage(ILogSink *logSink); ~TestLanguage(); private: ILogSink *m_logSink; Logger m_logger; ScriptEngine *m_engine; Loader *loader; TopLevelProjectPtr project; SetupProjectParameters defaultParameters; const QString m_wildcardsTestDirPath; QHash productsFromProject(ResolvedProjectPtr project); ResolvedModuleConstPtr findModuleByName(ResolvedProductPtr product, const QString &name); QVariant productPropertyValue(ResolvedProductPtr product, QString propertyName); void handleInitCleanupDataTags(const char *projectFileName, bool *handled); private slots: void initTestCase(); void cleanupTestCase(); void baseProperty(); void buildConfigStringListSyntax(); void builtinFunctionInSearchPathsProperty(); void canonicalArchitecture(); void conditionalDepends(); void dependencyOnAllProfiles(); void environmentVariable(); void erroneousFiles_data(); void erroneousFiles(); void exports(); void fileContextProperties(); void fileTags_data(); void fileTags(); void groupConditions_data(); void groupConditions(); void groupName(); void getNativeSetting(); void homeDirectory(); void identifierSearch_data(); void identifierSearch(); void idUsage(); void importCollection(); void invalidBindingInDisabledItem(); void itemPrototype(); void itemScope(); void jsExtensions(); void jsImportUsedInMultipleScopes_data(); void jsImportUsedInMultipleScopes(); void moduleProperties_data(); void moduleProperties(); void moduleScope(); void modules_data(); void modules(); void outerInGroup(); void pathProperties(); void productConditions(); void productDirectories(); void profileValuesAndOverriddenValues(); void propertiesBlocks_data(); void propertiesBlocks(); void propertiesBlockInGroup(); void qbsPropertiesInProjectCondition(); void defaultValue(); void defaultValue_data(); void qualifiedId(); void recursiveProductDependencies(); void rfc1034Identifier(); void wildcards_data(); void wildcards(); }; } // namespace Internal } // namespace qbs #endif // TST_LANGUAGE_H qbs-src-1.4.5/src/lib/corelib/language/value.cpp000066400000000000000000000107031266132464200214610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "value.h" #include "filecontext.h" #include "item.h" #include namespace qbs { namespace Internal { Value::Value(Type t, bool createdByPropertiesBlock) : m_type(t), m_definingItem(0), m_createdByPropertiesBlock(createdByPropertiesBlock) { } Value::~Value() { } Item *Value::definingItem() const { return m_definingItem; } void Value::setDefiningItem(Item *item) { m_definingItem = item; } ValuePtr Value::next() const { return m_next; } void Value::setNext(const ValuePtr &next) { QBS_ASSERT(next.data() != this, return); m_next = next; } JSSourceValue::JSSourceValue(bool createdByPropertiesBlock) : Value(JSSourceValueType, createdByPropertiesBlock) , m_line(-1) , m_column(-1) , m_exportScope(nullptr) { } JSSourceValuePtr JSSourceValue::create(bool createdByPropertiesBlock) { return JSSourceValuePtr(new JSSourceValue(createdByPropertiesBlock)); } JSSourceValue::~JSSourceValue() { } ValuePtr JSSourceValue::clone() const { return JSSourceValuePtr(new JSSourceValue(*this)); } QString JSSourceValue::sourceCodeForEvaluation() const { if (!hasFunctionForm()) return m_sourceCode.toString(); // rewrite blocks to be able to use return statements in property assignments static const QString prefix = QStringLiteral("(function()"); static const QString suffix = QStringLiteral(")()"); return prefix + m_sourceCode.toString() + suffix; } void JSSourceValue::setLocation(int line, int column) { m_line = line; m_column = column; } CodeLocation JSSourceValue::location() const { return CodeLocation(m_file->filePath(), m_line, m_column); } void JSSourceValue::setHasFunctionForm(bool b) { if (b) m_flags |= HasFunctionForm; else m_flags &= ~HasFunctionForm; } void JSSourceValue::setDefiningItem(Item *item) { Value::setDefiningItem(item); foreach (const JSSourceValue::Alternative &a, m_alternatives) a.value->setDefiningItem(item); } Item *JSSourceValue::exportScope() const { return m_exportScope; } void JSSourceValue::setExportScope(Item *extraScope) { m_exportScope = extraScope; } ItemValue::ItemValue(Item *item, bool createdByPropertiesBlock) : Value(ItemValueType, createdByPropertiesBlock) , m_item(item) { } ItemValuePtr ItemValue::create(Item *item, bool createdByPropertiesBlock) { return ItemValuePtr(new ItemValue(item, createdByPropertiesBlock)); } ItemValue::~ItemValue() { } ValuePtr ItemValue::clone() const { Item *clonedItem = m_item ? m_item->clone() : 0; return ItemValuePtr(new ItemValue(clonedItem, createdByPropertiesBlock())); } VariantValue::VariantValue(const QVariant &v) : Value(VariantValueType, false) , m_value(v) { } VariantValuePtr VariantValue::create(const QVariant &v) { return VariantValuePtr(new VariantValue(v)); } ValuePtr VariantValue::clone() const { return VariantValuePtr(new VariantValue(*this)); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/language/value.h000066400000000000000000000136171266132464200211350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_VALUE_H #define QBS_VALUE_H #include "forward_decls.h" #include #include namespace qbs { namespace Internal { class Item; class ValueHandler; class Value { public: enum Type { JSSourceValueType, ItemValueType, VariantValueType, BuiltinValueType }; Value(Type t, bool createdByPropertiesBlock); virtual ~Value(); Type type() const { return m_type; } virtual void apply(ValueHandler *) = 0; virtual ValuePtr clone() const = 0; virtual CodeLocation location() const { return CodeLocation(); } Item *definingItem() const; virtual void setDefiningItem(Item *item); ValuePtr next() const; void setNext(const ValuePtr &next); bool createdByPropertiesBlock() const { return m_createdByPropertiesBlock; } private: Type m_type; Item *m_definingItem; ValuePtr m_next; const bool m_createdByPropertiesBlock; }; class ValueHandler { public: virtual void handle(JSSourceValue *value) = 0; virtual void handle(ItemValue *value) = 0; virtual void handle(VariantValue *value) = 0; virtual void handle(BuiltinValue *value) = 0; }; class JSSourceValue : public Value { friend class ItemReaderASTVisitor; JSSourceValue(bool createdByPropertiesBlock); enum Flag { NoFlags = 0x00, SourceUsesBase = 0x01, SourceUsesOuter = 0x02, SourceUsesOriginal = 0x04, HasFunctionForm = 0x08 }; Q_DECLARE_FLAGS(Flags, Flag) public: static JSSourceValuePtr create(bool createdByPropertiesBlock = false); ~JSSourceValue(); void apply(ValueHandler *handler) { handler->handle(this); } ValuePtr clone() const; void setSourceCode(const QStringRef &sourceCode) { m_sourceCode = sourceCode; } const QStringRef &sourceCode() const { return m_sourceCode; } QString sourceCodeForEvaluation() const; void setLocation(int line, int column); int line() const { return m_line; } int column() const { return m_column; } CodeLocation location() const; void setFile(const FileContextPtr &file) { m_file = file; } const FileContextPtr &file() const { return m_file; } void setSourceUsesBaseFlag() { m_flags |= SourceUsesBase; } bool sourceUsesBase() const { return m_flags.testFlag(SourceUsesBase); } bool sourceUsesOuter() const { return m_flags.testFlag(SourceUsesOuter); } bool sourceUsesOriginal() const { return m_flags.testFlag(SourceUsesOriginal); } bool isInExportItem() const { return m_exportScope; } bool hasFunctionForm() const { return m_flags.testFlag(HasFunctionForm); } void setHasFunctionForm(bool b); const JSSourceValuePtr &baseValue() const { return m_baseValue; } void setBaseValue(const JSSourceValuePtr &v) { m_baseValue = v; } struct Alternative { QString condition; JSSourceValuePtr value; }; const QList &alternatives() const { return m_alternatives; } void setAlternatives(const QList &alternatives) { m_alternatives = alternatives; } void addAlternative(const Alternative &alternative) { m_alternatives.append(alternative); } void setDefiningItem(Item *item); Item *exportScope() const; void setExportScope(Item *exportScope); private: QStringRef m_sourceCode; int m_line; int m_column; FileContextPtr m_file; Flags m_flags; JSSourceValuePtr m_baseValue; QList m_alternatives; Item *m_exportScope; }; class ItemValue : public Value { ItemValue(Item *item, bool createdByPropertiesBlock); public: static ItemValuePtr create(Item *item = 0, bool createdByPropertiesBlock = false); ~ItemValue(); void apply(ValueHandler *handler) { handler->handle(this); } ValuePtr clone() const; Item *item() const; void setItem(Item *ptr); private: Item *m_item; }; inline Item *ItemValue::item() const { return m_item; } inline void ItemValue::setItem(Item *ptr) { m_item = ptr; } class VariantValue : public Value { VariantValue(const QVariant &v); public: static VariantValuePtr create(const QVariant &v = QVariant()); void apply(ValueHandler *handler) { handler->handle(this); } ValuePtr clone() const; void setValue(const QVariant &v) { m_value = v; } const QVariant &value() const { return m_value; } private: QVariant m_value; }; } // namespace Internal } // namespace qbs #endif // QBS_VALUE_H qbs-src-1.4.5/src/lib/corelib/logging/000077500000000000000000000000001266132464200175035ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/logging/ilogsink.cpp000066400000000000000000000063261266132464200220350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "ilogsink.h" #include #include #include namespace qbs { QString logLevelTag(LoggerLevel level) { if (level == LoggerInfo) return QString(); QString str = logLevelName(level).toUpper(); if (!str.isEmpty()) str.append(QLatin1String(": ")); return str; } QString logLevelName(LoggerLevel level) { switch (level) { case qbs::LoggerError: return QLatin1String("error"); case qbs::LoggerWarning: return QLatin1String("warning"); case qbs::LoggerInfo: return QLatin1String("info"); case qbs::LoggerDebug: return QLatin1String("debug"); case qbs::LoggerTrace: return QLatin1String("trace"); default: break; } return QString(); } class ILogSink::ILogSinkPrivate { public: LoggerLevel logLevel; QMutex mutex; }; ILogSink::ILogSink() : d(new ILogSinkPrivate) { d->logLevel = defaultLogLevel(); } ILogSink::~ILogSink() { delete d; } void ILogSink::setLogLevel(LoggerLevel level) { d->logLevel = level; } LoggerLevel ILogSink::logLevel() const { return d->logLevel; } void ILogSink::printWarning(const ErrorInfo &warning) { if (willPrint(LoggerWarning)) { d->mutex.lock(); doPrintWarning(warning); d->mutex.unlock(); } } void ILogSink::printMessage(LoggerLevel level, const QString &message, const QString &tag, bool force) { if (force || willPrint(level)) { d->mutex.lock(); doPrintMessage(level, message, tag); d->mutex.unlock(); } } void ILogSink::doPrintWarning(const ErrorInfo &warning) { doPrintMessage(LoggerWarning, warning.toString(), QString()); } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/logging/ilogsink.h000066400000000000000000000053101266132464200214720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_ILOGSINK_H #define QBS_ILOGSINK_H #include "../tools/qbs_export.h" #include namespace qbs { class ErrorInfo; enum LoggerLevel { LoggerMinLevel, LoggerError = LoggerMinLevel, LoggerWarning, LoggerInfo, LoggerDebug, LoggerTrace, LoggerMaxLevel = LoggerTrace }; inline LoggerLevel defaultLogLevel() { return LoggerInfo; } QBS_EXPORT QString logLevelTag(LoggerLevel level); QBS_EXPORT QString logLevelName(LoggerLevel level); class QBS_EXPORT ILogSink { Q_DISABLE_COPY(ILogSink) public: ILogSink(); virtual ~ILogSink(); void setLogLevel(LoggerLevel level); LoggerLevel logLevel() const; bool willPrint(LoggerLevel level) const { return level <= logLevel(); } void printWarning(const ErrorInfo &warning); void printMessage(LoggerLevel level, const QString &message, const QString &tag = QString(), bool force = false); private: virtual void doPrintWarning(const ErrorInfo &warning); virtual void doPrintMessage(LoggerLevel level, const QString &message, const QString &tag) = 0; class ILogSinkPrivate; ILogSinkPrivate * const d; }; } // namespace qbs #endif // Include guard qbs-src-1.4.5/src/lib/corelib/logging/logger.cpp000066400000000000000000000152661266132464200215000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #if defined(_MSC_VER) && _MSC_VER > 0 #define _CRT_SECURE_NO_WARNINGS #endif #include "logger.h" #include #include #include #include #include #include #include namespace qbs { namespace Internal { LogWriter::LogWriter(ILogSink *logSink, LoggerLevel level, bool force) : m_logSink(logSink), m_level(level), m_force(force) {} LogWriter::LogWriter(const LogWriter &other) : m_logSink(other.m_logSink) , m_level(other.m_level) , m_message(other.m_message) , m_tag(other.m_tag) , m_force(other.m_force) { other.m_message.clear(); } LogWriter::~LogWriter() { if (!m_message.isEmpty()) m_logSink->printMessage(m_level, m_message, m_tag, m_force); } const LogWriter &LogWriter::operator=(const LogWriter &other) { m_logSink = other.m_logSink; m_level = other.m_level; m_message = other.m_message; m_tag = other.m_tag; m_force = other.m_force; other.m_message.clear(); return *this; } void LogWriter::write(char c) { write(QLatin1Char(c)); } void LogWriter::write(const char *str) { write(QLatin1String(str)); } void LogWriter::write(const QChar &c) { if (m_force || m_logSink->logLevel() >= m_level) m_message.append(c); } void LogWriter::write(const QString &message) { if (m_force || m_logSink->logLevel() >= m_level) m_message += message; } void LogWriter::setMessageTag(const QString &tag) { m_tag = tag; } LogWriter operator<<(LogWriter w, const char *str) { w.write(str); return w; } LogWriter operator<<(LogWriter w, const QByteArray &byteArray) { w.write(byteArray.data()); return w; } LogWriter operator<<(LogWriter w, const QString &str) { w.write(str); return w; } LogWriter operator<<(LogWriter w, const QStringList &strList) { w.write('['); for (int i = 0; i < strList.size(); ++i) { w.write(strList.at(i)); if (i != strList.size() - 1) w.write(QLatin1String(", ")); } w.write(']'); return w; } LogWriter operator<<(LogWriter w, const QSet &strSet) { bool firstLoop = true; w.write('('); foreach (const QString &str, strSet) { if (firstLoop) firstLoop = false; else w.write(QLatin1String(", ")); w.write(str); } w.write(')'); return w; } LogWriter operator<<(LogWriter w, const QVariant &variant) { QString str = QLatin1String(variant.typeName()) + QLatin1Char('('); if (variant.type() == QVariant::List) { bool firstLoop = true; foreach (const QVariant &item, variant.toList()) { str += item.toString(); if (firstLoop) firstLoop = false; else str += QLatin1String(", "); } } else { str += variant.toString(); } str += QLatin1Char(')'); w.write(str); return w; } LogWriter operator<<(LogWriter w, int n) { return w << QString::number(n); } LogWriter operator<<(LogWriter w, qint64 n) { return w << QString::number(n); } LogWriter operator<<(LogWriter w, bool b) { return w << QString::fromLatin1(b ? "true" : "false"); } LogWriter operator<<(LogWriter w, const MessageTag &tag) { w.setMessageTag(tag.tag()); return w; } Logger::Logger(ILogSink *logger) : m_logSink(logger) { } bool Logger::debugEnabled() const { return m_logSink->willPrint(LoggerDebug); } bool Logger::traceEnabled() const { return m_logSink->willPrint(LoggerTrace); } LogWriter Logger::qbsLog(LoggerLevel level, bool force) const { return LogWriter(m_logSink, level, force); } class TimedActivityLogger::TimedActivityLoggerPrivate { public: Logger logger; QString prefix; QString activity; LoggerLevel logLevel; QElapsedTimer timer; bool alwaysLog; }; TimedActivityLogger::TimedActivityLogger(const Logger &logger, const QString &activity, const QString &prefix, LoggerLevel logLevel, bool alwaysLog) : d(0) { if (!alwaysLog && !logger.logSink()->willPrint(logLevel)) return; d = new TimedActivityLoggerPrivate; d->logger = logger; d->prefix = prefix; d->activity = activity; d->logLevel = logLevel; d->alwaysLog = alwaysLog; d->logger.qbsLog(logLevel, alwaysLog) << QString::fromLocal8Bit("%1Starting activity '%2'.") .arg(prefix, activity); d->timer.start(); } void TimedActivityLogger::finishActivity() { if (!d) return; qint64 ms = d->timer.elapsed(); qint64 s = ms/1000; ms -= s*1000; qint64 m = s/60; s -= m*60; const qint64 h = m/60; m -= h*60; QString timeString = QString::fromLocal8Bit("%1ms").arg(ms); if (h || m || s) timeString.prepend(QString::fromLocal8Bit("%1s, ").arg(s)); if (h || m) timeString.prepend(QString::fromLocal8Bit("%1m, ").arg(m)); if (h) timeString.prepend(QString::fromLocal8Bit("%1h, ").arg(h)); d->logger.qbsLog(d->logLevel, d->alwaysLog) << QString::fromLocal8Bit("%1Activity '%2' took %3.") .arg(d->prefix, d->activity, timeString); delete d; d = 0; } TimedActivityLogger::~TimedActivityLogger() { finishActivity(); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/logging/logger.h000066400000000000000000000106001266132464200211300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_LOGGER_H #define QBS_LOGGER_H #include "ilogsink.h" #include #include #include QT_BEGIN_NAMESPACE class QVariant; QT_END_NAMESPACE namespace qbs { namespace Internal { // Note that while these classes are not part of the API, we export some stuff for use by // our command line tools for the sake of a uniform logging approach. class QBS_EXPORT LogWriter { public: LogWriter(ILogSink *logSink, LoggerLevel level, bool force = false); // log writer has move semantics and the last instance of // a << chain prints the accumulated data LogWriter(const LogWriter &other); ~LogWriter(); const LogWriter &operator=(const LogWriter &other); void write(char c); void write(const char *str); void write(const QChar &c); void write(const QString &message); void setMessageTag(const QString &tag); private: ILogSink *m_logSink; LoggerLevel m_level; mutable QString m_message; QString m_tag; bool m_force; }; class QBS_EXPORT MessageTag { public: explicit MessageTag(const QString &tag) : m_tag(tag) {} const QString &tag() const { return m_tag; } private: QString m_tag; }; QBS_EXPORT LogWriter operator<<(LogWriter w, const char *str); QBS_EXPORT LogWriter operator<<(LogWriter w, const QByteArray &byteArray); QBS_EXPORT LogWriter operator<<(LogWriter w, const QString &str); QBS_EXPORT LogWriter operator<<(LogWriter w, const QStringList &strList); QBS_EXPORT LogWriter operator<<(LogWriter w, const QSet &strSet); QBS_EXPORT LogWriter operator<<(LogWriter w, const QVariant &variant); QBS_EXPORT LogWriter operator<<(LogWriter w, int n); QBS_EXPORT LogWriter operator<<(LogWriter w, qint64 n); QBS_EXPORT LogWriter operator<<(LogWriter w, bool b); QBS_EXPORT LogWriter operator<<(LogWriter w, const MessageTag &tag); class QBS_EXPORT Logger { public: Logger(ILogSink *logSink = 0); ILogSink *logSink() const { return m_logSink; } bool debugEnabled() const; bool traceEnabled() const; void printWarning(const ErrorInfo &warning) { logSink()->printWarning(warning); } LogWriter qbsLog(LoggerLevel level, bool force = false) const; LogWriter qbsWarning() const { return qbsLog(LoggerWarning); } LogWriter qbsInfo() const { return qbsLog(LoggerInfo); } LogWriter qbsDebug() const { return qbsLog(LoggerDebug); } LogWriter qbsTrace() const { return qbsLog(LoggerTrace); } private: ILogSink *m_logSink; }; class TimedActivityLogger { public: TimedActivityLogger(const Logger &logger, const QString &activity, const QString &prefix = QString(), LoggerLevel logLevel = LoggerDebug, bool alwaysLog = false); void finishActivity(); ~TimedActivityLogger(); private: class TimedActivityLoggerPrivate; TimedActivityLoggerPrivate *d; }; } // namespace Internal } // namespace qbs #endif // QBS_LOGGER_H qbs-src-1.4.5/src/lib/corelib/logging/logging.pri000066400000000000000000000005361266132464200216510ustar00rootroot00000000000000include(../../../install_prefix.pri) HEADERS += \ $$PWD/logger.h \ $$PWD/translator.h \ $$PWD/ilogsink.h SOURCES += \ $$PWD/logger.cpp \ $$PWD/ilogsink.cpp !qbs_no_dev_install { logging_headers.files = $$PWD/ilogsink.h logging_headers.path = $${QBS_INSTALL_PREFIX}/include/qbs/logging INSTALLS += logging_headers } qbs-src-1.4.5/src/lib/corelib/logging/translator.h000066400000000000000000000035211266132464200220460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_TRANSLATOR_H #define QBS_TRANSLATOR_H #include #include namespace qbs { namespace Internal { class QBS_EXPORT Tr // Name intended to be short. Exported for use by command line tools. { Q_DECLARE_TR_FUNCTIONS(Qbs) }; } // namespace Internal } // namespace qbs #endif // QBS_TRANSLATOR_H qbs-src-1.4.5/src/lib/corelib/parser/000077500000000000000000000000001266132464200173515ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/parser/parser.pri000066400000000000000000000010251266132464200213570ustar00rootroot00000000000000HEADERS += \ $$PWD/qmljsast_p.h \ $$PWD/qmljsastfwd_p.h \ $$PWD/qmljsastvisitor_p.h \ $$PWD/qmljsengine_p.h \ $$PWD/qmljsgrammar_p.h \ $$PWD/qmljslexer_p.h \ $$PWD/qmljsmemorypool_p.h \ $$PWD/qmljsparser_p.h \ $$PWD/qmljsglobal_p.h \ $$PWD/qmlerror.h \ $$PWD/qmljskeywords_p.h \ SOURCES += \ $$PWD/qmljsast.cpp \ $$PWD/qmljsastvisitor.cpp \ $$PWD/qmljsengine_p.cpp \ $$PWD/qmljsgrammar.cpp \ $$PWD/qmljslexer.cpp \ $$PWD/qmljsparser.cpp \ $$PWD/qmlerror.cpp \ qbs-src-1.4.5/src/lib/corelib/parser/qmlerror.cpp000066400000000000000000000153771266132464200217350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "qmlerror.h" #include #include #include namespace QbsQmlJS { /*! \class QmlError \since 5.0 \inmodule QtQml \brief The QmlError class encapsulates a QML error. QmlError includes a textual description of the error, as well as location information (the file, line, and column). The toString() method creates a single-line, human-readable string containing all of this information, for example: \code file:///home/user/test.qml:7:8: Invalid property assignment: double expected \endcode You can use qDebug() or qWarning() to output errors to the console. This method will attempt to open the file indicated by the error and include additional contextual information. \code file:///home/user/test.qml:7:8: Invalid property assignment: double expected y: "hello" ^ \endcode Note that the QtQuick 1 version is named QDeclarativeError \sa QQuickView::errors(), QmlComponent::errors() */ class QmlErrorPrivate { public: QmlErrorPrivate(); QUrl url; QString description; int line; int column; }; QmlErrorPrivate::QmlErrorPrivate() : line(-1), column(-1) { } /*! Creates an empty error object. */ QmlError::QmlError() : d(0) { } /*! Creates a copy of \a other. */ QmlError::QmlError(const QmlError &other) : d(0) { *this = other; } /*! Assigns \a other to this error object. */ QmlError &QmlError::operator=(const QmlError &other) { if (!other.d) { delete d; d = 0; } else { if (!d) d = new QmlErrorPrivate; d->url = other.d->url; d->description = other.d->description; d->line = other.d->line; d->column = other.d->column; } return *this; } /*! \internal */ QmlError::~QmlError() { delete d; d = 0; } /*! Returns true if this error is valid, otherwise false. */ bool QmlError::isValid() const { return d != 0; } /*! Returns the url for the file that caused this error. */ QUrl QmlError::url() const { if (d) return d->url; else return QUrl(); } /*! Sets the \a url for the file that caused this error. */ void QmlError::setUrl(const QUrl &url) { if (!d) d = new QmlErrorPrivate; d->url = url; } /*! Returns the error description. */ QString QmlError::description() const { if (d) return d->description; else return QString(); } /*! Sets the error \a description. */ void QmlError::setDescription(const QString &description) { if (!d) d = new QmlErrorPrivate; d->description = description; } /*! Returns the error line number. */ int QmlError::line() const { if (d) return d->line; else return -1; } /*! Sets the error \a line number. */ void QmlError::setLine(int line) { if (!d) d = new QmlErrorPrivate; d->line = line; } /*! Returns the error column number. */ int QmlError::column() const { if (d) return d->column; else return -1; } /*! Sets the error \a column number. */ void QmlError::setColumn(int column) { if (!d) d = new QmlErrorPrivate; d->column = column; } /*! Returns the error as a human readable string. */ QString QmlError::toString() const { QString rv; if (url().isEmpty()) { rv = QLatin1String(""); } else if (line() != -1) { rv = url().toString() + QLatin1Char(':') + QString::number(line()); if (column() != -1) rv += QLatin1Char(':') + QString::number(column()); } else { rv = url().toString(); } rv += QLatin1String(": ") + description(); return rv; } } // namespace QbsQmlJS QT_BEGIN_NAMESPACE using namespace QbsQmlJS; /*! \relates QmlError \fn QDebug operator<<(QDebug debug, const QmlError &error) Outputs a human readable version of \a error to \a debug. */ QDebug operator<<(QDebug debug, const QmlError &error) { debug << qPrintable(error.toString()); QUrl url = error.url(); if (error.line() > 0 && url.scheme() == QLatin1String("file")) { QString file = url.toLocalFile(); QFile f(file); if (f.open(QIODevice::ReadOnly)) { QByteArray data = f.readAll(); QTextStream stream(data, QIODevice::ReadOnly); #ifndef QT_NO_TEXTCODEC stream.setCodec("UTF-8"); #endif const QString code = stream.readAll(); const QStringList lines = code.split(QLatin1Char('\n')); if (lines.count() >= error.line()) { const QString &line = lines.at(error.line() - 1); debug << "\n " << qPrintable(line); if (error.column() > 0) { int column = qMax(0, error.column() - 1); column = qMin(column, line.length()); QByteArray ind; ind.reserve(column); for (int i = 0; i < column; ++i) { const QChar ch = line.at(i); if (ch.isSpace()) ind.append(ch.unicode()); else ind.append(' '); } ind.append('^'); debug << "\n " << ind.constData(); } } } } return debug; } QT_END_NAMESPACE qbs-src-1.4.5/src/lib/corelib/parser/qmlerror.h000066400000000000000000000045001266132464200213640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QQMLERROR_H #define QQMLERROR_H #include #include QT_BEGIN_NAMESPACE class QDebug; QT_END_NAMESPACE namespace QbsQmlJS { class QmlErrorPrivate; class QmlError { public: QmlError(); QmlError(const QmlError &); QmlError &operator=(const QmlError &); ~QmlError(); bool isValid() const; QUrl url() const; void setUrl(const QUrl &); QString description() const; void setDescription(const QString &); int line() const; void setLine(int); int column() const; void setColumn(int); QString toString() const; private: QmlErrorPrivate *d; }; } // namespace QbsQmlJS QT_BEGIN_NAMESPACE QDebug operator<<(QDebug debug, const QbsQmlJS::QmlError &error); Q_DECLARE_TYPEINFO(QbsQmlJS::QmlError, Q_MOVABLE_TYPE); QT_END_NAMESPACE #endif // QQMLERROR_H qbs-src-1.4.5/src/lib/corelib/parser/qmljs.g000066400000000000000000002413401266132464200206530ustar00rootroot00000000000000----------------------------------------------------------------------------- -- -- Copyright (C) 2015 The Qt Company Ltd. -- Contact: http://www.qt.io/licensing -- -- This file is part of the Qt Build Suite. -- -- Commercial License Usage -- Licensees holding valid commercial Qt licenses may use this file in -- accordance with the commercial license agreement provided with the -- Software or, alternatively, in accordance with the terms contained in -- a written agreement between you and The Qt Company. For licensing terms and -- conditions see http://www.qt.io/terms-conditions. For further information -- use the contact form at http://www.qt.io/contact-us. -- -- GNU Lesser General Public License Usage -- Alternatively, this file may be used under the terms of the GNU Lesser -- General Public License version 2.1 or version 3 as published by the Free -- Software Foundation and appearing in the file LICENSE.LGPLv21 and -- LICENSE.LGPLv3 included in the packaging of this file. Please review the -- following information to ensure the GNU Lesser General Public License -- requirements will be met: https://www.gnu.org/licenses/lgpl.html and -- http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -- -- In addition, as a special exception, The Qt Company gives you certain additional -- rights. These rights are described in The Qt Company LGPL Exception -- version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -- ----------------------------------------------------------------------------- %parser QmlJSGrammar %decl qmljsparser_p.h %impl qdeclarativejsparser.cpp %expect 2 %expect-rr 2 %token T_AND "&" T_AND_AND "&&" T_AND_EQ "&=" %token T_BREAK "break" T_CASE "case" T_CATCH "catch" %token T_COLON ":" T_COMMA "," T_CONTINUE "continue" %token T_DEFAULT "default" T_DELETE "delete" T_DIVIDE_ "/" %token T_DIVIDE_EQ "/=" T_DO "do" T_DOT "." %token T_ELSE "else" T_EQ "=" T_EQ_EQ "==" %token T_EQ_EQ_EQ "===" T_FINALLY "finally" T_FOR "for" %token T_FUNCTION "function" T_GE ">=" T_GT ">" %token T_GT_GT ">>" T_GT_GT_EQ ">>=" T_GT_GT_GT ">>>" %token T_GT_GT_GT_EQ ">>>=" T_IDENTIFIER "identifier" T_IF "if" %token T_IN "in" T_INSTANCEOF "instanceof" T_LBRACE "{" %token T_LBRACKET "[" T_LE "<=" T_LPAREN "(" %token T_LT "<" T_LT_LT "<<" T_LT_LT_EQ "<<=" %token T_MINUS "-" T_MINUS_EQ "-=" T_MINUS_MINUS "--" %token T_NEW "new" T_NOT "!" T_NOT_EQ "!=" %token T_NOT_EQ_EQ "!==" T_NUMERIC_LITERAL "numeric literal" T_OR "|" %token T_OR_EQ "|=" T_OR_OR "||" T_PLUS "+" %token T_PLUS_EQ "+=" T_PLUS_PLUS "++" T_QUESTION "?" %token T_RBRACE "}" T_RBRACKET "]" T_REMAINDER "%" %token T_REMAINDER_EQ "%=" T_RETURN "return" T_RPAREN ")" %token T_SEMICOLON ";" T_AUTOMATIC_SEMICOLON T_STAR "*" %token T_STAR_EQ "*=" T_STRING_LITERAL "string literal" %token T_PROPERTY "property" T_SIGNAL "signal" T_READONLY "readonly" %token T_SWITCH "switch" T_THIS "this" T_THROW "throw" %token T_TILDE "~" T_TRY "try" T_TYPEOF "typeof" %token T_VAR "var" T_VOID "void" T_WHILE "while" %token T_WITH "with" T_XOR "^" T_XOR_EQ "^=" %token T_NULL "null" T_TRUE "true" T_FALSE "false" %token T_CONST "const" %token T_DEBUGGER "debugger" %token T_RESERVED_WORD "reserved word" %token T_MULTILINE_STRING_LITERAL "multiline string literal" %token T_COMMENT "comment" --- context keywords. %token T_PUBLIC "public" %token T_IMPORT "import" %token T_AS "as" %token T_ON "on" %token T_ERROR --- feed tokens %token T_FEED_UI_PROGRAM %token T_FEED_UI_OBJECT_MEMBER %token T_FEED_JS_STATEMENT %token T_FEED_JS_EXPRESSION %token T_FEED_JS_SOURCE_ELEMENT %token T_FEED_JS_PROGRAM %nonassoc SHIFT_THERE %nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY T_READONLY %nonassoc REDUCE_HERE %start TopLevel /./**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #include #include #include "qmljsengine_p.h" #include "qmljslexer_p.h" #include "qmljsast_p.h" #include "qmljsmemorypool_p.h" ./ /:/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QMLJSPARSER_P_H #define QMLJSPARSER_P_H #include "qmljsglobal_p.h" #include "qmljsgrammar_p.h" #include "qmljsast_p.h" #include "qmljsengine_p.h" #include #include QT_QML_BEGIN_NAMESPACE namespace QmlJS { class Engine; class QML_PARSER_EXPORT Parser: protected $table { public: union Value { int ival; double dval; AST::ArgumentList *ArgumentList; AST::CaseBlock *CaseBlock; AST::CaseClause *CaseClause; AST::CaseClauses *CaseClauses; AST::Catch *Catch; AST::DefaultClause *DefaultClause; AST::ElementList *ElementList; AST::Elision *Elision; AST::ExpressionNode *Expression; AST::Finally *Finally; AST::FormalParameterList *FormalParameterList; AST::FunctionBody *FunctionBody; AST::FunctionDeclaration *FunctionDeclaration; AST::Node *Node; AST::PropertyName *PropertyName; AST::PropertyNameAndValueList *PropertyNameAndValueList; AST::SourceElement *SourceElement; AST::SourceElements *SourceElements; AST::Statement *Statement; AST::StatementList *StatementList; AST::Block *Block; AST::VariableDeclaration *VariableDeclaration; AST::VariableDeclarationList *VariableDeclarationList; AST::UiProgram *UiProgram; AST::UiImportList *UiImportList; AST::UiImport *UiImport; AST::UiParameterList *UiParameterList; AST::UiPublicMember *UiPublicMember; AST::UiObjectDefinition *UiObjectDefinition; AST::UiObjectInitializer *UiObjectInitializer; AST::UiObjectBinding *UiObjectBinding; AST::UiScriptBinding *UiScriptBinding; AST::UiArrayBinding *UiArrayBinding; AST::UiObjectMember *UiObjectMember; AST::UiObjectMemberList *UiObjectMemberList; AST::UiArrayMemberList *UiArrayMemberList; AST::UiQualifiedId *UiQualifiedId; }; public: Parser(Engine *engine); ~Parser(); // parse a UI program bool parse() { return parse(T_FEED_UI_PROGRAM); } bool parseStatement() { return parse(T_FEED_JS_STATEMENT); } bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); } bool parseSourceElement() { return parse(T_FEED_JS_SOURCE_ELEMENT); } bool parseUiObjectMember() { return parse(T_FEED_UI_OBJECT_MEMBER); } bool parseProgram() { return parse(T_FEED_JS_PROGRAM); } AST::UiProgram *ast() const { return AST::cast(program); } AST::Statement *statement() const { if (! program) return 0; return program->statementCast(); } AST::ExpressionNode *expression() const { if (! program) return 0; return program->expressionCast(); } AST::UiObjectMember *uiObjectMember() const { if (! program) return 0; return program->uiObjectMemberCast(); } AST::Node *rootNode() const { return program; } QList diagnosticMessages() const { return diagnostic_messages; } inline DiagnosticMessage diagnosticMessage() const { foreach (const DiagnosticMessage &d, diagnostic_messages) { if (d.kind != DiagnosticMessage::Warning) return d; } return DiagnosticMessage(); } inline QString errorMessage() const { return diagnosticMessage().message; } inline int errorLineNumber() const { return diagnosticMessage().loc.startLine; } inline int errorColumnNumber() const { return diagnosticMessage().loc.startColumn; } protected: bool parse(int startToken); void reallocateStack(); inline Value &sym(int index) { return sym_stack [tos + index - 1]; } inline QStringRef &stringRef(int index) { return string_stack [tos + index - 1]; } inline AST::SourceLocation &loc(int index) { return location_stack [tos + index - 1]; } AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr); protected: Engine *driver; MemoryPool *pool; int tos; int stack_size; Value *sym_stack; int *state_stack; AST::SourceLocation *location_stack; QStringRef *string_stack; AST::Node *program; // error recovery enum { TOKEN_BUFFER_SIZE = 3 }; struct SavedToken { int token; double dval; AST::SourceLocation loc; QStringRef spell; }; double yylval; QStringRef yytokenspell; AST::SourceLocation yylloc; AST::SourceLocation yyprevlloc; SavedToken token_buffer[TOKEN_BUFFER_SIZE]; SavedToken *first_token; SavedToken *last_token; QList diagnostic_messages; }; } // end of namespace QmlJS :/ /. #include "qmljsparser_p.h" #include // // This file is automatically generated from qmljs.g. // Changes will be lost. // using namespace QmlJS; QT_QML_BEGIN_NAMESPACE void Parser::reallocateStack() { if (! stack_size) stack_size = 128; else stack_size <<= 1; sym_stack = reinterpret_cast (realloc(sym_stack, stack_size * sizeof(Value))); state_stack = reinterpret_cast (realloc(state_stack, stack_size * sizeof(int))); location_stack = reinterpret_cast (realloc(location_stack, stack_size * sizeof(AST::SourceLocation))); string_stack = reinterpret_cast (realloc(string_stack, stack_size * sizeof(QStringRef))); } Parser::Parser(Engine *engine): driver(engine), pool(engine->pool()), tos(0), stack_size(0), sym_stack(0), state_stack(0), location_stack(0), string_stack(0), first_token(0), last_token(0) { } Parser::~Parser() { if (stack_size) { free(sym_stack); free(state_stack); free(location_stack); free(string_stack); } } static inline AST::SourceLocation location(Lexer *lexer) { AST::SourceLocation loc; loc.offset = lexer->tokenOffset(); loc.length = lexer->tokenLength(); loc.startLine = lexer->tokenStartLine(); loc.startColumn = lexer->tokenStartColumn(); return loc; } AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) { QVarLengthArray nameIds; QVarLengthArray locations; AST::ExpressionNode *it = expr; while (AST::FieldMemberExpression *m = AST::cast(it)) { nameIds.append(m->name); locations.append(m->identifierToken); it = m->base; } if (AST::IdentifierExpression *idExpr = AST::cast(it)) { AST::UiQualifiedId *q = new (pool) AST::UiQualifiedId(idExpr->name); q->identifierToken = idExpr->identifierToken; AST::UiQualifiedId *currentId = q; for (int i = nameIds.size() - 1; i != -1; --i) { currentId = new (pool) AST::UiQualifiedId(currentId, nameIds[i]); currentId->identifierToken = locations[i]; } return currentId->finish(); } return 0; } bool Parser::parse(int startToken) { Lexer *lexer = driver->lexer(); bool hadErrors = false; int yytoken = -1; int action = 0; token_buffer[0].token = startToken; first_token = &token_buffer[0]; last_token = &token_buffer[1]; tos = -1; program = 0; do { if (++tos == stack_size) reallocateStack(); state_stack[tos] = action; _Lcheck_token: if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) { yyprevlloc = yylloc; if (first_token == last_token) { yytoken = lexer->lex(); yylval = lexer->tokenValue(); yytokenspell = lexer->tokenSpell(); yylloc = location(lexer); } else { yytoken = first_token->token; yylval = first_token->dval; yytokenspell = first_token->spell; yylloc = first_token->loc; ++first_token; } } action = t_action(action, yytoken); if (action > 0) { if (action != ACCEPT_STATE) { yytoken = -1; sym(1).dval = yylval; stringRef(1) = yytokenspell; loc(1) = yylloc; } else { --tos; return ! hadErrors; } } else if (action < 0) { const int r = -action - 1; tos -= rhs[r]; switch (r) { ./ -------------------------------------------------------------------------------------------------------- -- Declarative UI -------------------------------------------------------------------------------------------------------- TopLevel: T_FEED_UI_PROGRAM UiProgram ; /. case $rule_number: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; ./ TopLevel: T_FEED_JS_STATEMENT Statement ; /. case $rule_number: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; ./ TopLevel: T_FEED_JS_EXPRESSION Expression ; /. case $rule_number: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; ./ TopLevel: T_FEED_JS_SOURCE_ELEMENT SourceElement ; /. case $rule_number: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; ./ TopLevel: T_FEED_UI_OBJECT_MEMBER UiObjectMember ; /. case $rule_number: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; ./ TopLevel: T_FEED_JS_PROGRAM Program ; /. case $rule_number: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; ./ UiProgram: UiImportListOpt UiRootMember ; /. case $rule_number: { sym(1).UiProgram = new (pool) AST::UiProgram(sym(1).UiImportList, sym(2).UiObjectMemberList->finish()); } break; ./ UiImportListOpt: Empty ; UiImportListOpt: UiImportList ; /. case $rule_number: { sym(1).Node = sym(1).UiImportList->finish(); } break; ./ UiImportList: UiImport ; /. case $rule_number: { sym(1).Node = new (pool) AST::UiImportList(sym(1).UiImport); } break; ./ UiImportList: UiImportList UiImport ; /. case $rule_number: { sym(1).Node = new (pool) AST::UiImportList(sym(1).UiImportList, sym(2).UiImport); } break; ./ ImportId: MemberExpression ; UiImport: UiImportHead T_AUTOMATIC_SEMICOLON ; UiImport: UiImportHead T_SEMICOLON ; /. case $rule_number: { sym(1).UiImport->semicolonToken = loc(2); } break; ./ UiImport: UiImportHead T_NUMERIC_LITERAL T_AUTOMATIC_SEMICOLON ; UiImport: UiImportHead T_NUMERIC_LITERAL T_SEMICOLON ; /. case $rule_number: { sym(1).UiImport->versionToken = loc(2); sym(1).UiImport->semicolonToken = loc(3); } break; ./ UiImport: UiImportHead T_NUMERIC_LITERAL T_AS JsIdentifier T_AUTOMATIC_SEMICOLON ; UiImport: UiImportHead T_NUMERIC_LITERAL T_AS JsIdentifier T_SEMICOLON ; /. case $rule_number: { sym(1).UiImport->versionToken = loc(2); sym(1).UiImport->asToken = loc(3); sym(1).UiImport->importIdToken = loc(4); sym(1).UiImport->importId = stringRef(4); sym(1).UiImport->semicolonToken = loc(5); } break; ./ UiImport: UiImportHead T_AS JsIdentifier T_AUTOMATIC_SEMICOLON ; UiImport: UiImportHead T_AS JsIdentifier T_SEMICOLON ; /. case $rule_number: { sym(1).UiImport->asToken = loc(2); sym(1).UiImport->importIdToken = loc(3); sym(1).UiImport->importId = stringRef(3); sym(1).UiImport->semicolonToken = loc(4); } break; ./ UiImportHead: T_IMPORT ImportId ; /. case $rule_number: { AST::UiImport *node = 0; if (AST::StringLiteral *importIdLiteral = AST::cast(sym(2).Expression)) { node = new (pool) AST::UiImport(importIdLiteral->value); node->fileNameToken = loc(2); } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) { node = new (pool) AST::UiImport(qualifiedId); node->fileNameToken = loc(2); } sym(1).Node = node; if (node) { node->importToken = loc(1); } else { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), QLatin1String("Expected a qualified name id or a string literal"))); return false; // ### remove me } } break; ./ Empty: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ UiRootMember: UiObjectDefinition ; /. case $rule_number: { sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember); } break; ./ UiObjectMemberList: UiObjectMember ; /. case $rule_number: { sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember); } break; ./ UiObjectMemberList: UiObjectMemberList UiObjectMember ; /. case $rule_number: { AST::UiObjectMemberList *node = new (pool) AST:: UiObjectMemberList( sym(1).UiObjectMemberList, sym(2).UiObjectMember); sym(1).Node = node; } break; ./ UiArrayMemberList: UiObjectDefinition ; /. case $rule_number: { sym(1).Node = new (pool) AST::UiArrayMemberList(sym(1).UiObjectMember); } break; ./ UiArrayMemberList: UiArrayMemberList T_COMMA UiObjectDefinition ; /. case $rule_number: { AST::UiArrayMemberList *node = new (pool) AST::UiArrayMemberList( sym(1).UiArrayMemberList, sym(3).UiObjectMember); node->commaToken = loc(2); sym(1).Node = node; } break; ./ UiObjectInitializer: T_LBRACE T_RBRACE ; /. case $rule_number: { AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer((AST::UiObjectMemberList*)0); node->lbraceToken = loc(1); node->rbraceToken = loc(2); sym(1).Node = node; } break; ./ UiObjectInitializer: T_LBRACE UiObjectMemberList T_RBRACE ; /. case $rule_number: { AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer(sym(2).UiObjectMemberList->finish()); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; ./ UiObjectDefinition: UiQualifiedId UiObjectInitializer ; /. case $rule_number: { AST::UiObjectDefinition *node = new (pool) AST::UiObjectDefinition(sym(1).UiQualifiedId, sym(2).UiObjectInitializer); sym(1).Node = node; } break; ./ UiObjectMember: UiObjectDefinition ; UiObjectMember: UiQualifiedId T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ; /. case $rule_number: { AST::UiArrayBinding *node = new (pool) AST::UiArrayBinding( sym(1).UiQualifiedId, sym(4).UiArrayMemberList->finish()); node->colonToken = loc(2); node->lbracketToken = loc(3); node->rbracketToken = loc(5); sym(1).Node = node; } break; ./ UiObjectMember: UiQualifiedId T_COLON UiQualifiedId UiObjectInitializer ; /. case $rule_number: { AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding( sym(1).UiQualifiedId, sym(3).UiQualifiedId, sym(4).UiObjectInitializer); node->colonToken = loc(2); sym(1).Node = node; } break; ./ UiObjectMember: UiQualifiedId T_ON UiQualifiedId UiObjectInitializer ; /. case $rule_number: { AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding( sym(3).UiQualifiedId, sym(1).UiQualifiedId, sym(4).UiObjectInitializer); node->colonToken = loc(2); node->hasOnToken = true; sym(1).Node = node; } break; ./ UiScriptStatement: Block ; UiScriptStatement: EmptyStatement ; UiScriptStatement: ExpressionStatement ; UiScriptStatement: IfStatement ; UiScriptStatement: WithStatement ; UiScriptStatement: SwitchStatement ; UiScriptStatement: TryStatement ; UiObjectMember: UiQualifiedId T_COLON UiScriptStatement ; /. case $rule_number: { AST::UiScriptBinding *node = new (pool) AST::UiScriptBinding( sym(1).UiQualifiedId, sym(3).Statement); node->colonToken = loc(2); sym(1).Node = node; } break; ./ UiPropertyType: T_VAR ; UiPropertyType: T_RESERVED_WORD ; UiPropertyType: T_IDENTIFIER ; UiParameterListOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ UiParameterListOpt: UiParameterList ; /. case $rule_number: { sym(1).Node = sym(1).UiParameterList->finish (); } break; ./ UiParameterList: UiPropertyType JsIdentifier ; /. case $rule_number: { AST::UiParameterList *node = new (pool) AST::UiParameterList(stringRef(1), stringRef(2)); node->propertyTypeToken = loc(1); node->identifierToken = loc(2); sym(1).Node = node; } break; ./ UiParameterList: UiParameterList T_COMMA UiPropertyType JsIdentifier ; /. case $rule_number: { AST::UiParameterList *node = new (pool) AST::UiParameterList(sym(1).UiParameterList, stringRef(3), stringRef(4)); node->commaToken = loc(2); node->identifierToken = loc(4); sym(1).Node = node; } break; ./ UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_AUTOMATIC_SEMICOLON ; UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_SEMICOLON ; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(QStringRef(), stringRef(2)); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(2); node->parameters = sym(4).UiParameterList; node->semicolonToken = loc(6); sym(1).Node = node; } break; ./ UiObjectMember: T_SIGNAL T_IDENTIFIER T_AUTOMATIC_SEMICOLON ; UiObjectMember: T_SIGNAL T_IDENTIFIER T_SEMICOLON ; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(QStringRef(), stringRef(2)); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(2); node->semicolonToken = loc(3); sym(1).Node = node; } break; ./ UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT JsIdentifier T_AUTOMATIC_SEMICOLON ; UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT JsIdentifier T_SEMICOLON ; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(4), stringRef(6)); node->typeModifier = stringRef(2); node->propertyToken = loc(1); node->typeModifierToken = loc(2); node->typeToken = loc(4); node->identifierToken = loc(6); node->semicolonToken = loc(7); sym(1).Node = node; } break; ./ UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_AUTOMATIC_SEMICOLON ; UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_SEMICOLON ; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3)); node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(3); node->semicolonToken = loc(4); sym(1).Node = node; } break; ./ UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType JsIdentifier T_AUTOMATIC_SEMICOLON ; UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType JsIdentifier T_SEMICOLON ; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4)); node->isDefaultMember = true; node->defaultToken = loc(1); node->propertyToken = loc(2); node->typeToken = loc(3); node->identifierToken = loc(4); node->semicolonToken = loc(5); sym(1).Node = node; } break; ./ UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_COLON UiScriptStatement ; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3), sym(5).Statement); node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(3); node->colonToken = loc(4); sym(1).Node = node; } break; ./ UiObjectMember: T_READONLY T_PROPERTY UiPropertyType JsIdentifier T_COLON UiScriptStatement ; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4), sym(6).Statement); node->isReadonlyMember = true; node->readonlyToken = loc(1); node->propertyToken = loc(2); node->typeToken = loc(3); node->identifierToken = loc(4); node->colonToken = loc(5); sym(1).Node = node; } break; ./ UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType JsIdentifier T_COLON UiScriptStatement ; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4), sym(6).Statement); node->isDefaultMember = true; node->defaultToken = loc(1); node->propertyToken = loc(2); node->typeToken = loc(3); node->identifierToken = loc(4); node->colonToken = loc(5); sym(1).Node = node; } break; ./ UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT JsIdentifier T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(4), stringRef(6)); node->typeModifier = stringRef(2); node->propertyToken = loc(1); node->typeModifierToken = loc(2); node->typeToken = loc(4); node->identifierToken = loc(6); node->semicolonToken = loc(7); // insert a fake ';' before ':' AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(6)); propertyName->identifierToken = loc(6); propertyName->next = 0; AST::UiArrayBinding *binding = new (pool) AST::UiArrayBinding( propertyName, sym(9).UiArrayMemberList->finish()); binding->colonToken = loc(7); binding->lbracketToken = loc(8); binding->rbracketToken = loc(10); node->binding = binding; sym(1).Node = node; } break; ./ UiObjectMember: T_PROPERTY UiPropertyType JsIdentifier T_COLON UiQualifiedId UiObjectInitializer ; /. case $rule_number: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3)); node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(3); node->semicolonToken = loc(4); // insert a fake ';' before ':' AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(3)); propertyName->identifierToken = loc(3); propertyName->next = 0; AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding( propertyName, sym(5).UiQualifiedId, sym(6).UiObjectInitializer); binding->colonToken = loc(4); node->binding = binding; sym(1).Node = node; } break; ./ UiObjectMember: FunctionDeclaration ; /. case $rule_number: { sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); } break; ./ UiObjectMember: VariableStatement ; /. case $rule_number: { sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); } break; ./ JsIdentifier: T_IDENTIFIER; JsIdentifier: T_PROPERTY ; JsIdentifier: T_SIGNAL ; JsIdentifier: T_READONLY ; JsIdentifier: T_ON ; -------------------------------------------------------------------------------------------------------- -- Expressions -------------------------------------------------------------------------------------------------------- PrimaryExpression: T_THIS ; /. case $rule_number: { AST::ThisExpression *node = new (pool) AST::ThisExpression(); node->thisToken = loc(1); sym(1).Node = node; } break; ./ PrimaryExpression: JsIdentifier ; /. case $rule_number: { AST::IdentifierExpression *node = new (pool) AST::IdentifierExpression(stringRef(1)); node->identifierToken = loc(1); sym(1).Node = node; } break; ./ PrimaryExpression: T_NULL ; /. case $rule_number: { AST::NullExpression *node = new (pool) AST::NullExpression(); node->nullToken = loc(1); sym(1).Node = node; } break; ./ PrimaryExpression: T_TRUE ; /. case $rule_number: { AST::TrueLiteral *node = new (pool) AST::TrueLiteral(); node->trueToken = loc(1); sym(1).Node = node; } break; ./ PrimaryExpression: T_FALSE ; /. case $rule_number: { AST::FalseLiteral *node = new (pool) AST::FalseLiteral(); node->falseToken = loc(1); sym(1).Node = node; } break; ./ PrimaryExpression: T_NUMERIC_LITERAL ; /. case $rule_number: { AST::NumericLiteral *node = new (pool) AST::NumericLiteral(sym(1).dval); node->literalToken = loc(1); sym(1).Node = node; } break; ./ PrimaryExpression: T_MULTILINE_STRING_LITERAL ; /.case $rule_number:./ PrimaryExpression: T_STRING_LITERAL ; /. case $rule_number: { AST::StringLiteral *node = new (pool) AST::StringLiteral(stringRef(1)); node->literalToken = loc(1); sym(1).Node = node; } break; ./ PrimaryExpression: T_DIVIDE_ ; /: #define J_SCRIPT_REGEXPLITERAL_RULE1 $rule_number :/ /. case $rule_number: { bool rx = lexer->scanRegExp(Lexer::NoPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); return false; // ### remove me } loc(1).length = lexer->tokenLength(); yylloc = loc(1); // adjust the location of the current token AST::RegExpLiteral *node = new (pool) AST::RegExpLiteral( driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags()); node->literalToken = loc(1); sym(1).Node = node; } break; ./ PrimaryExpression: T_DIVIDE_EQ ; /: #define J_SCRIPT_REGEXPLITERAL_RULE2 $rule_number :/ /. case $rule_number: { bool rx = lexer->scanRegExp(Lexer::EqualPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); return false; } loc(1).length = lexer->tokenLength(); yylloc = loc(1); // adjust the location of the current token AST::RegExpLiteral *node = new (pool) AST::RegExpLiteral( driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags()); node->literalToken = loc(1); sym(1).Node = node; } break; ./ PrimaryExpression: T_LBRACKET T_RBRACKET ; /. case $rule_number: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral((AST::Elision *) 0); node->lbracketToken = loc(1); node->rbracketToken = loc(2); sym(1).Node = node; } break; ./ PrimaryExpression: T_LBRACKET Elision T_RBRACKET ; /. case $rule_number: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).Elision->finish()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; ./ PrimaryExpression: T_LBRACKET ElementList T_RBRACKET ; /. case $rule_number: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish ()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; ./ PrimaryExpression: T_LBRACKET ElementList T_COMMA T_RBRACKET ; /. case $rule_number: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), (AST::Elision *) 0); node->lbracketToken = loc(1); node->commaToken = loc(3); node->rbracketToken = loc(4); sym(1).Node = node; } break; ./ PrimaryExpression: T_LBRACKET ElementList T_COMMA Elision T_RBRACKET ; /. case $rule_number: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), sym(4).Elision->finish()); node->lbracketToken = loc(1); node->commaToken = loc(3); node->rbracketToken = loc(5); sym(1).Node = node; } break; ./ -- PrimaryExpression: T_LBRACE T_RBRACE ; -- /. -- case $rule_number: { -- sym(1).Node = new (pool) AST::ObjectLiteral(); -- } break; -- ./ PrimaryExpression: T_LBRACE PropertyNameAndValueListOpt T_RBRACE ; /. case $rule_number: { AST::ObjectLiteral *node = 0; if (sym(2).Node) node = new (pool) AST::ObjectLiteral( sym(2).PropertyNameAndValueList->finish ()); else node = new (pool) AST::ObjectLiteral(); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; ./ PrimaryExpression: T_LBRACE PropertyNameAndValueList T_COMMA T_RBRACE ; /. case $rule_number: { AST::ObjectLiteral *node = new (pool) AST::ObjectLiteral( sym(2).PropertyNameAndValueList->finish ()); node->lbraceToken = loc(1); node->rbraceToken = loc(4); sym(1).Node = node; } break; ./ PrimaryExpression: T_LPAREN Expression T_RPAREN ; /. case $rule_number: { AST::NestedExpression *node = new (pool) AST::NestedExpression(sym(2).Expression); node->lparenToken = loc(1); node->rparenToken = loc(3); sym(1).Node = node; } break; ./ UiQualifiedId: MemberExpression ; /. case $rule_number: { if (AST::ArrayMemberExpression *mem = AST::cast(sym(1).Expression)) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken, QLatin1String("Ignored annotation"))); sym(1).Expression = mem->base; } if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) { sym(1).UiQualifiedId = qualifiedId; } else { sym(1).UiQualifiedId = 0; diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), QLatin1String("Expected a qualified name id"))); return false; // ### recover } } break; ./ ElementList: AssignmentExpression ; /. case $rule_number: { sym(1).Node = new (pool) AST::ElementList((AST::Elision *) 0, sym(1).Expression); } break; ./ ElementList: Elision AssignmentExpression ; /. case $rule_number: { sym(1).Node = new (pool) AST::ElementList(sym(1).Elision->finish(), sym(2).Expression); } break; ./ ElementList: ElementList T_COMMA AssignmentExpression ; /. case $rule_number: { AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, (AST::Elision *) 0, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; ./ ElementList: ElementList T_COMMA Elision AssignmentExpression ; /. case $rule_number: { AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, sym(3).Elision->finish(), sym(4).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; ./ Elision: T_COMMA ; /. case $rule_number: { AST::Elision *node = new (pool) AST::Elision(); node->commaToken = loc(1); sym(1).Node = node; } break; ./ Elision: Elision T_COMMA ; /. case $rule_number: { AST::Elision *node = new (pool) AST::Elision(sym(1).Elision); node->commaToken = loc(2); sym(1).Node = node; } break; ./ PropertyNameAndValueList: PropertyName T_COLON AssignmentExpression ; /. case $rule_number: { AST::PropertyNameAndValueList *node = new (pool) AST::PropertyNameAndValueList( sym(1).PropertyName, sym(3).Expression); node->colonToken = loc(2); sym(1).Node = node; } break; ./ PropertyNameAndValueList: PropertyNameAndValueList T_COMMA PropertyName T_COLON AssignmentExpression ; /. case $rule_number: { AST::PropertyNameAndValueList *node = new (pool) AST::PropertyNameAndValueList( sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression); node->commaToken = loc(2); node->colonToken = loc(4); sym(1).Node = node; } break; ./ PropertyName: T_IDENTIFIER %prec SHIFT_THERE ; /. case $rule_number: { AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; ./ PropertyName: T_SIGNAL ; /.case $rule_number:./ PropertyName: T_PROPERTY ; /. case $rule_number: { AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; ./ PropertyName: T_STRING_LITERAL ; /. case $rule_number: { AST::StringLiteralPropertyName *node = new (pool) AST::StringLiteralPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; ./ PropertyName: T_NUMERIC_LITERAL ; /. case $rule_number: { AST::NumericLiteralPropertyName *node = new (pool) AST::NumericLiteralPropertyName(sym(1).dval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; ./ PropertyName: ReservedIdentifier ; /. case $rule_number: { AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; ./ ReservedIdentifier: T_BREAK ; ReservedIdentifier: T_CASE ; ReservedIdentifier: T_CATCH ; ReservedIdentifier: T_CONTINUE ; ReservedIdentifier: T_DEFAULT ; ReservedIdentifier: T_DELETE ; ReservedIdentifier: T_DO ; ReservedIdentifier: T_ELSE ; ReservedIdentifier: T_FALSE ; ReservedIdentifier: T_FINALLY ; ReservedIdentifier: T_FOR ; ReservedIdentifier: T_FUNCTION ; ReservedIdentifier: T_IF ; ReservedIdentifier: T_IN ; ReservedIdentifier: T_INSTANCEOF ; ReservedIdentifier: T_NEW ; ReservedIdentifier: T_NULL ; ReservedIdentifier: T_RETURN ; ReservedIdentifier: T_SWITCH ; ReservedIdentifier: T_THIS ; ReservedIdentifier: T_THROW ; ReservedIdentifier: T_TRUE ; ReservedIdentifier: T_TRY ; ReservedIdentifier: T_TYPEOF ; ReservedIdentifier: T_VAR ; ReservedIdentifier: T_VOID ; ReservedIdentifier: T_WHILE ; ReservedIdentifier: T_CONST ; ReservedIdentifier: T_DEBUGGER ; ReservedIdentifier: T_RESERVED_WORD ; ReservedIdentifier: T_WITH ; PropertyIdentifier: JsIdentifier ; PropertyIdentifier: ReservedIdentifier ; MemberExpression: PrimaryExpression ; MemberExpression: FunctionExpression ; MemberExpression: MemberExpression T_LBRACKET Expression T_RBRACKET ; /. case $rule_number: { AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; ./ MemberExpression: MemberExpression T_DOT PropertyIdentifier ; /. case $rule_number: { AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; ./ MemberExpression: T_NEW MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ; /. case $rule_number: { AST::NewMemberExpression *node = new (pool) AST::NewMemberExpression(sym(2).Expression, sym(4).ArgumentList); node->newToken = loc(1); node->lparenToken = loc(3); node->rparenToken = loc(5); sym(1).Node = node; } break; ./ NewExpression: MemberExpression ; NewExpression: T_NEW NewExpression ; /. case $rule_number: { AST::NewExpression *node = new (pool) AST::NewExpression(sym(2).Expression); node->newToken = loc(1); sym(1).Node = node; } break; ./ CallExpression: MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ; /. case $rule_number: { AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; ./ CallExpression: CallExpression T_LPAREN ArgumentListOpt T_RPAREN ; /. case $rule_number: { AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; ./ CallExpression: CallExpression T_LBRACKET Expression T_RBRACKET ; /. case $rule_number: { AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; ./ CallExpression: CallExpression T_DOT PropertyIdentifier ; /. case $rule_number: { AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; ./ ArgumentListOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ ArgumentListOpt: ArgumentList ; /. case $rule_number: { sym(1).Node = sym(1).ArgumentList->finish(); } break; ./ ArgumentList: AssignmentExpression ; /. case $rule_number: { sym(1).Node = new (pool) AST::ArgumentList(sym(1).Expression); } break; ./ ArgumentList: ArgumentList T_COMMA AssignmentExpression ; /. case $rule_number: { AST::ArgumentList *node = new (pool) AST::ArgumentList(sym(1).ArgumentList, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; ./ LeftHandSideExpression: NewExpression ; LeftHandSideExpression: CallExpression ; PostfixExpression: LeftHandSideExpression ; PostfixExpression: LeftHandSideExpression T_PLUS_PLUS ; /. case $rule_number: { AST::PostIncrementExpression *node = new (pool) AST::PostIncrementExpression(sym(1).Expression); node->incrementToken = loc(2); sym(1).Node = node; } break; ./ PostfixExpression: LeftHandSideExpression T_MINUS_MINUS ; /. case $rule_number: { AST::PostDecrementExpression *node = new (pool) AST::PostDecrementExpression(sym(1).Expression); node->decrementToken = loc(2); sym(1).Node = node; } break; ./ UnaryExpression: PostfixExpression ; UnaryExpression: T_DELETE UnaryExpression ; /. case $rule_number: { AST::DeleteExpression *node = new (pool) AST::DeleteExpression(sym(2).Expression); node->deleteToken = loc(1); sym(1).Node = node; } break; ./ UnaryExpression: T_VOID UnaryExpression ; /. case $rule_number: { AST::VoidExpression *node = new (pool) AST::VoidExpression(sym(2).Expression); node->voidToken = loc(1); sym(1).Node = node; } break; ./ UnaryExpression: T_TYPEOF UnaryExpression ; /. case $rule_number: { AST::TypeOfExpression *node = new (pool) AST::TypeOfExpression(sym(2).Expression); node->typeofToken = loc(1); sym(1).Node = node; } break; ./ UnaryExpression: T_PLUS_PLUS UnaryExpression ; /. case $rule_number: { AST::PreIncrementExpression *node = new (pool) AST::PreIncrementExpression(sym(2).Expression); node->incrementToken = loc(1); sym(1).Node = node; } break; ./ UnaryExpression: T_MINUS_MINUS UnaryExpression ; /. case $rule_number: { AST::PreDecrementExpression *node = new (pool) AST::PreDecrementExpression(sym(2).Expression); node->decrementToken = loc(1); sym(1).Node = node; } break; ./ UnaryExpression: T_PLUS UnaryExpression ; /. case $rule_number: { AST::UnaryPlusExpression *node = new (pool) AST::UnaryPlusExpression(sym(2).Expression); node->plusToken = loc(1); sym(1).Node = node; } break; ./ UnaryExpression: T_MINUS UnaryExpression ; /. case $rule_number: { AST::UnaryMinusExpression *node = new (pool) AST::UnaryMinusExpression(sym(2).Expression); node->minusToken = loc(1); sym(1).Node = node; } break; ./ UnaryExpression: T_TILDE UnaryExpression ; /. case $rule_number: { AST::TildeExpression *node = new (pool) AST::TildeExpression(sym(2).Expression); node->tildeToken = loc(1); sym(1).Node = node; } break; ./ UnaryExpression: T_NOT UnaryExpression ; /. case $rule_number: { AST::NotExpression *node = new (pool) AST::NotExpression(sym(2).Expression); node->notToken = loc(1); sym(1).Node = node; } break; ./ MultiplicativeExpression: UnaryExpression ; MultiplicativeExpression: MultiplicativeExpression T_STAR UnaryExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Mul, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ MultiplicativeExpression: MultiplicativeExpression T_DIVIDE_ UnaryExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Div, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ MultiplicativeExpression: MultiplicativeExpression T_REMAINDER UnaryExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Mod, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ AdditiveExpression: MultiplicativeExpression ; AdditiveExpression: AdditiveExpression T_PLUS MultiplicativeExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Add, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ AdditiveExpression: AdditiveExpression T_MINUS MultiplicativeExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Sub, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ ShiftExpression: AdditiveExpression ; ShiftExpression: ShiftExpression T_LT_LT AdditiveExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::LShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ ShiftExpression: ShiftExpression T_GT_GT AdditiveExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::RShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ ShiftExpression: ShiftExpression T_GT_GT_GT AdditiveExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::URShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpression: ShiftExpression ; RelationalExpression: RelationalExpression T_LT ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpression: RelationalExpression T_GT ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpression: RelationalExpression T_LE ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpression: RelationalExpression T_GE ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpression: RelationalExpression T_INSTANCEOF ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpression: RelationalExpression T_IN ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::In, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpressionNotIn: ShiftExpression ; RelationalExpressionNotIn: RelationalExpressionNotIn T_LT ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpressionNotIn: RelationalExpressionNotIn T_GT ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpressionNotIn: RelationalExpressionNotIn T_LE ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpressionNotIn: RelationalExpressionNotIn T_GE ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ RelationalExpressionNotIn: RelationalExpressionNotIn T_INSTANCEOF ShiftExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ EqualityExpression: RelationalExpression ; EqualityExpression: EqualityExpression T_EQ_EQ RelationalExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ EqualityExpression: EqualityExpression T_NOT_EQ RelationalExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ EqualityExpression: EqualityExpression T_EQ_EQ_EQ RelationalExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ EqualityExpression: EqualityExpression T_NOT_EQ_EQ RelationalExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ EqualityExpressionNotIn: RelationalExpressionNotIn ; EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ RelationalExpressionNotIn ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ RelationalExpressionNotIn; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ_EQ RelationalExpressionNotIn ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ_EQ RelationalExpressionNotIn ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ BitwiseANDExpression: EqualityExpression ; BitwiseANDExpression: BitwiseANDExpression T_AND EqualityExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ BitwiseANDExpressionNotIn: EqualityExpressionNotIn ; BitwiseANDExpressionNotIn: BitwiseANDExpressionNotIn T_AND EqualityExpressionNotIn ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ BitwiseXORExpression: BitwiseANDExpression ; BitwiseXORExpression: BitwiseXORExpression T_XOR BitwiseANDExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ BitwiseXORExpressionNotIn: BitwiseANDExpressionNotIn ; BitwiseXORExpressionNotIn: BitwiseXORExpressionNotIn T_XOR BitwiseANDExpressionNotIn ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ BitwiseORExpression: BitwiseXORExpression ; BitwiseORExpression: BitwiseORExpression T_OR BitwiseXORExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ BitwiseORExpressionNotIn: BitwiseXORExpressionNotIn ; BitwiseORExpressionNotIn: BitwiseORExpressionNotIn T_OR BitwiseXORExpressionNotIn ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ LogicalANDExpression: BitwiseORExpression ; LogicalANDExpression: LogicalANDExpression T_AND_AND BitwiseORExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ LogicalANDExpressionNotIn: BitwiseORExpressionNotIn ; LogicalANDExpressionNotIn: LogicalANDExpressionNotIn T_AND_AND BitwiseORExpressionNotIn ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ LogicalORExpression: LogicalANDExpression ; LogicalORExpression: LogicalORExpression T_OR_OR LogicalANDExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Or, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ LogicalORExpressionNotIn: LogicalANDExpressionNotIn ; LogicalORExpressionNotIn: LogicalORExpressionNotIn T_OR_OR LogicalANDExpressionNotIn ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Or, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ ConditionalExpression: LogicalORExpression ; ConditionalExpression: LogicalORExpression T_QUESTION AssignmentExpression T_COLON AssignmentExpression ; /. case $rule_number: { AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); node->colonToken = loc(4); sym(1).Node = node; } break; ./ ConditionalExpressionNotIn: LogicalORExpressionNotIn ; ConditionalExpressionNotIn: LogicalORExpressionNotIn T_QUESTION AssignmentExpressionNotIn T_COLON AssignmentExpressionNotIn ; /. case $rule_number: { AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); node->colonToken = loc(4); sym(1).Node = node; } break; ./ AssignmentExpression: ConditionalExpression ; AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ AssignmentExpressionNotIn: ConditionalExpressionNotIn ; AssignmentExpressionNotIn: LeftHandSideExpression AssignmentOperator AssignmentExpressionNotIn ; /. case $rule_number: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; ./ AssignmentOperator: T_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::Assign; } break; ./ AssignmentOperator: T_STAR_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceMul; } break; ./ AssignmentOperator: T_DIVIDE_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceDiv; } break; ./ AssignmentOperator: T_REMAINDER_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceMod; } break; ./ AssignmentOperator: T_PLUS_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceAdd; } break; ./ AssignmentOperator: T_MINUS_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceSub; } break; ./ AssignmentOperator: T_LT_LT_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceLeftShift; } break; ./ AssignmentOperator: T_GT_GT_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceRightShift; } break; ./ AssignmentOperator: T_GT_GT_GT_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceURightShift; } break; ./ AssignmentOperator: T_AND_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceAnd; } break; ./ AssignmentOperator: T_XOR_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceXor; } break; ./ AssignmentOperator: T_OR_EQ ; /. case $rule_number: { sym(1).ival = QSOperator::InplaceOr; } break; ./ Expression: AssignmentExpression ; Expression: Expression T_COMMA AssignmentExpression ; /. case $rule_number: { AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; ./ ExpressionOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ ExpressionOpt: Expression ; ExpressionNotIn: AssignmentExpressionNotIn ; ExpressionNotIn: ExpressionNotIn T_COMMA AssignmentExpressionNotIn ; /. case $rule_number: { AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; ./ ExpressionNotInOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ ExpressionNotInOpt: ExpressionNotIn ; Statement: Block ; Statement: VariableStatement ; Statement: EmptyStatement ; Statement: ExpressionStatement ; Statement: IfStatement ; Statement: IterationStatement ; Statement: ContinueStatement ; Statement: BreakStatement ; Statement: ReturnStatement ; Statement: WithStatement ; Statement: LabelledStatement ; Statement: SwitchStatement ; Statement: ThrowStatement ; Statement: TryStatement ; Statement: DebuggerStatement ; Block: T_LBRACE StatementListOpt T_RBRACE ; /. case $rule_number: { AST::Block *node = new (pool) AST::Block(sym(2).StatementList); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; ./ StatementList: Statement ; /. case $rule_number: { sym(1).Node = new (pool) AST::StatementList(sym(1).Statement); } break; ./ StatementList: StatementList Statement ; /. case $rule_number: { sym(1).Node = new (pool) AST::StatementList(sym(1).StatementList, sym(2).Statement); } break; ./ StatementListOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ StatementListOpt: StatementList ; /. case $rule_number: { sym(1).Node = sym(1).StatementList->finish (); } break; ./ VariableStatement: VariableDeclarationKind VariableDeclarationList T_AUTOMATIC_SEMICOLON ; -- automatic semicolon VariableStatement: VariableDeclarationKind VariableDeclarationList T_SEMICOLON ; /. case $rule_number: { AST::VariableStatement *node = new (pool) AST::VariableStatement( sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST)); node->declarationKindToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; ./ VariableDeclarationKind: T_CONST ; /. case $rule_number: { sym(1).ival = T_CONST; } break; ./ VariableDeclarationKind: T_VAR ; /. case $rule_number: { sym(1).ival = T_VAR; } break; ./ VariableDeclarationList: VariableDeclaration ; /. case $rule_number: { sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); } break; ./ VariableDeclarationList: VariableDeclarationList T_COMMA VariableDeclaration ; /. case $rule_number: { AST::VariableDeclarationList *node = new (pool) AST::VariableDeclarationList( sym(1).VariableDeclarationList, sym(3).VariableDeclaration); node->commaToken = loc(2); sym(1).Node = node; } break; ./ VariableDeclarationListNotIn: VariableDeclarationNotIn ; /. case $rule_number: { sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); } break; ./ VariableDeclarationListNotIn: VariableDeclarationListNotIn T_COMMA VariableDeclarationNotIn ; /. case $rule_number: { sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclarationList, sym(3).VariableDeclaration); } break; ./ VariableDeclaration: JsIdentifier InitialiserOpt ; /. case $rule_number: { AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; ./ VariableDeclarationNotIn: JsIdentifier InitialiserNotInOpt ; /. case $rule_number: { AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; ./ Initialiser: T_EQ AssignmentExpression ; /. case $rule_number: { // ### TODO: AST for initializer sym(1) = sym(2); } break; ./ InitialiserOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ InitialiserOpt: Initialiser ; InitialiserNotIn: T_EQ AssignmentExpressionNotIn ; /. case $rule_number: { // ### TODO: AST for initializer sym(1) = sym(2); } break; ./ InitialiserNotInOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ InitialiserNotInOpt: InitialiserNotIn ; EmptyStatement: T_SEMICOLON ; /. case $rule_number: { AST::EmptyStatement *node = new (pool) AST::EmptyStatement(); node->semicolonToken = loc(1); sym(1).Node = node; } break; ./ ExpressionStatement: Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon ExpressionStatement: Expression T_SEMICOLON ; /. case $rule_number: { AST::ExpressionStatement *node = new (pool) AST::ExpressionStatement(sym(1).Expression); node->semicolonToken = loc(2); sym(1).Node = node; } break; ./ IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement T_ELSE Statement ; /. case $rule_number: { AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement, sym(7).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); node->elseToken = loc(6); sym(1).Node = node; } break; ./ IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement ; /. case $rule_number: { AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; ./ IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_AUTOMATIC_SEMICOLON ; -- automatic semicolon IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_SEMICOLON ; /. case $rule_number: { AST::DoWhileStatement *node = new (pool) AST::DoWhileStatement(sym(2).Statement, sym(5).Expression); node->doToken = loc(1); node->whileToken = loc(3); node->lparenToken = loc(4); node->rparenToken = loc(6); node->semicolonToken = loc(7); sym(1).Node = node; } break; ./ IterationStatement: T_WHILE T_LPAREN Expression T_RPAREN Statement ; /. case $rule_number: { AST::WhileStatement *node = new (pool) AST::WhileStatement(sym(3).Expression, sym(5).Statement); node->whileToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; ./ IterationStatement: T_FOR T_LPAREN ExpressionNotInOpt T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ; /. case $rule_number: { AST::ForStatement *node = new (pool) AST::ForStatement(sym(3).Expression, sym(5).Expression, sym(7).Expression, sym(9).Statement); node->forToken = loc(1); node->lparenToken = loc(2); node->firstSemicolonToken = loc(4); node->secondSemicolonToken = loc(6); node->rparenToken = loc(8); sym(1).Node = node; } break; ./ IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationListNotIn T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ; /. case $rule_number: { AST::LocalForStatement *node = new (pool) AST::LocalForStatement( sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression, sym(8).Expression, sym(10).Statement); node->forToken = loc(1); node->lparenToken = loc(2); node->varToken = loc(3); node->firstSemicolonToken = loc(5); node->secondSemicolonToken = loc(7); node->rparenToken = loc(9); sym(1).Node = node; } break; ./ IterationStatement: T_FOR T_LPAREN LeftHandSideExpression T_IN Expression T_RPAREN Statement ; /. case $rule_number: { AST:: ForEachStatement *node = new (pool) AST::ForEachStatement(sym(3).Expression, sym(5).Expression, sym(7).Statement); node->forToken = loc(1); node->lparenToken = loc(2); node->inToken = loc(4); node->rparenToken = loc(6); sym(1).Node = node; } break; ./ IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationNotIn T_IN Expression T_RPAREN Statement ; /. case $rule_number: { AST::LocalForEachStatement *node = new (pool) AST::LocalForEachStatement( sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); node->forToken = loc(1); node->lparenToken = loc(2); node->varToken = loc(3); node->inToken = loc(5); node->rparenToken = loc(7); sym(1).Node = node; } break; ./ ContinueStatement: T_CONTINUE T_AUTOMATIC_SEMICOLON ; -- automatic semicolon ContinueStatement: T_CONTINUE T_SEMICOLON ; /. case $rule_number: { AST::ContinueStatement *node = new (pool) AST::ContinueStatement(); node->continueToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; ./ ContinueStatement: T_CONTINUE JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon ContinueStatement: T_CONTINUE JsIdentifier T_SEMICOLON ; /. case $rule_number: { AST::ContinueStatement *node = new (pool) AST::ContinueStatement(stringRef(2)); node->continueToken = loc(1); node->identifierToken = loc(2); node->semicolonToken = loc(3); sym(1).Node = node; } break; ./ BreakStatement: T_BREAK T_AUTOMATIC_SEMICOLON ; -- automatic semicolon BreakStatement: T_BREAK T_SEMICOLON ; /. case $rule_number: { AST::BreakStatement *node = new (pool) AST::BreakStatement(QStringRef()); node->breakToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; ./ BreakStatement: T_BREAK JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon BreakStatement: T_BREAK JsIdentifier T_SEMICOLON ; /. case $rule_number: { AST::BreakStatement *node = new (pool) AST::BreakStatement(stringRef(2)); node->breakToken = loc(1); node->identifierToken = loc(2); node->semicolonToken = loc(3); sym(1).Node = node; } break; ./ ReturnStatement: T_RETURN ExpressionOpt T_AUTOMATIC_SEMICOLON ; -- automatic semicolon ReturnStatement: T_RETURN ExpressionOpt T_SEMICOLON ; /. case $rule_number: { AST::ReturnStatement *node = new (pool) AST::ReturnStatement(sym(2).Expression); node->returnToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; ./ WithStatement: T_WITH T_LPAREN Expression T_RPAREN Statement ; /. case $rule_number: { AST::WithStatement *node = new (pool) AST::WithStatement(sym(3).Expression, sym(5).Statement); node->withToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; ./ SwitchStatement: T_SWITCH T_LPAREN Expression T_RPAREN CaseBlock ; /. case $rule_number: { AST::SwitchStatement *node = new (pool) AST::SwitchStatement(sym(3).Expression, sym(5).CaseBlock); node->switchToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; ./ CaseBlock: T_LBRACE CaseClausesOpt T_RBRACE ; /. case $rule_number: { AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; ./ CaseBlock: T_LBRACE CaseClausesOpt DefaultClause CaseClausesOpt T_RBRACE ; /. case $rule_number: { AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(5); sym(1).Node = node; } break; ./ CaseClauses: CaseClause ; /. case $rule_number: { sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClause); } break; ./ CaseClauses: CaseClauses CaseClause ; /. case $rule_number: { sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClauses, sym(2).CaseClause); } break; ./ CaseClausesOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ CaseClausesOpt: CaseClauses ; /. case $rule_number: { sym(1).Node = sym(1).CaseClauses->finish (); } break; ./ CaseClause: T_CASE Expression T_COLON StatementListOpt ; /. case $rule_number: { AST::CaseClause *node = new (pool) AST::CaseClause(sym(2).Expression, sym(4).StatementList); node->caseToken = loc(1); node->colonToken = loc(3); sym(1).Node = node; } break; ./ DefaultClause: T_DEFAULT T_COLON StatementListOpt ; /. case $rule_number: { AST::DefaultClause *node = new (pool) AST::DefaultClause(sym(3).StatementList); node->defaultToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; ./ LabelledStatement: T_SIGNAL T_COLON Statement ; /.case $rule_number:./ LabelledStatement: T_PROPERTY T_COLON Statement ; /. case $rule_number: { AST::LabelledStatement *node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; ./ LabelledStatement: T_IDENTIFIER T_COLON Statement ; /. case $rule_number: { AST::LabelledStatement *node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; ./ ThrowStatement: T_THROW Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon ThrowStatement: T_THROW Expression T_SEMICOLON ; /. case $rule_number: { AST::ThrowStatement *node = new (pool) AST::ThrowStatement(sym(2).Expression); node->throwToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; ./ TryStatement: T_TRY Block Catch ; /. case $rule_number: { AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch); node->tryToken = loc(1); sym(1).Node = node; } break; ./ TryStatement: T_TRY Block Finally ; /. case $rule_number: { AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; ./ TryStatement: T_TRY Block Catch Finally ; /. case $rule_number: { AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch, sym(4).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; ./ Catch: T_CATCH T_LPAREN JsIdentifier T_RPAREN Block ; /. case $rule_number: { AST::Catch *node = new (pool) AST::Catch(stringRef(3), sym(5).Block); node->catchToken = loc(1); node->lparenToken = loc(2); node->identifierToken = loc(3); node->rparenToken = loc(4); sym(1).Node = node; } break; ./ Finally: T_FINALLY Block ; /. case $rule_number: { AST::Finally *node = new (pool) AST::Finally(sym(2).Block); node->finallyToken = loc(1); sym(1).Node = node; } break; ./ DebuggerStatement: T_DEBUGGER T_AUTOMATIC_SEMICOLON ; -- automatic semicolon DebuggerStatement: T_DEBUGGER T_SEMICOLON ; /. case $rule_number: { AST::DebuggerStatement *node = new (pool) AST::DebuggerStatement(); node->debuggerToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; ./ FunctionDeclaration: T_FUNCTION JsIdentifier T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ; /. case $rule_number: { AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); node->identifierToken = loc(2); node->lparenToken = loc(3); node->rparenToken = loc(5); node->lbraceToken = loc(6); node->rbraceToken = loc(8); sym(1).Node = node; } break; ./ FunctionExpression: T_FUNCTION IdentifierOpt T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ; /. case $rule_number: { AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); if (! stringRef(2).isNull()) node->identifierToken = loc(2); node->lparenToken = loc(3); node->rparenToken = loc(5); node->lbraceToken = loc(6); node->rbraceToken = loc(8); sym(1).Node = node; } break; ./ FormalParameterList: JsIdentifier ; /. case $rule_number: { AST::FormalParameterList *node = new (pool) AST::FormalParameterList(stringRef(1)); node->identifierToken = loc(1); sym(1).Node = node; } break; ./ FormalParameterList: FormalParameterList T_COMMA JsIdentifier ; /. case $rule_number: { AST::FormalParameterList *node = new (pool) AST::FormalParameterList(sym(1).FormalParameterList, stringRef(3)); node->commaToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; ./ FormalParameterListOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ FormalParameterListOpt: FormalParameterList ; /. case $rule_number: { sym(1).Node = sym(1).FormalParameterList->finish (); } break; ./ FunctionBodyOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ FunctionBodyOpt: FunctionBody ; FunctionBody: SourceElements ; /. case $rule_number: { sym(1).Node = new (pool) AST::FunctionBody(sym(1).SourceElements->finish ()); } break; ./ Program: Empty ; Program: SourceElements ; /. case $rule_number: { sym(1).Node = new (pool) AST::Program(sym(1).SourceElements->finish ()); } break; ./ SourceElements: SourceElement ; /. case $rule_number: { sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElement); } break; ./ SourceElements: SourceElements SourceElement ; /. case $rule_number: { sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElements, sym(2).SourceElement); } break; ./ SourceElement: Statement ; /. case $rule_number: { sym(1).Node = new (pool) AST::StatementSourceElement(sym(1).Statement); } break; ./ SourceElement: FunctionDeclaration ; /. case $rule_number: { sym(1).Node = new (pool) AST::FunctionSourceElement(sym(1).FunctionDeclaration); } break; ./ IdentifierOpt: ; /. case $rule_number: { stringRef(1) = QStringRef(); } break; ./ IdentifierOpt: JsIdentifier ; PropertyNameAndValueListOpt: ; /. case $rule_number: { sym(1).Node = 0; } break; ./ PropertyNameAndValueListOpt: PropertyNameAndValueList ; /. } // switch action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT); } // if } while (action != 0); if (first_token == last_token) { const int errorState = state_stack[tos]; // automatic insertion of `;' if (yytoken != -1 && t_action(errorState, T_AUTOMATIC_SEMICOLON) && lexer->canInsertAutomaticSemicolon(yytoken)) { SavedToken &tk = token_buffer[0]; tk.token = yytoken; tk.dval = yylval; tk.spell = yytokenspell; tk.loc = yylloc; yylloc = yyprevlloc; yylloc.offset += yylloc.length; yylloc.startColumn += yylloc.length; yylloc.length = 0; //const QString msg = qApp->translate("QmlParser", "Missing `;'"); //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg)); first_token = &token_buffer[0]; last_token = &token_buffer[1]; yytoken = T_SEMICOLON; yylval = 0; action = errorState; goto _Lcheck_token; } hadErrors = true; token_buffer[0].token = yytoken; token_buffer[0].dval = yylval; token_buffer[0].spell = yytokenspell; token_buffer[0].loc = yylloc; token_buffer[1].token = yytoken = lexer->lex(); token_buffer[1].dval = yylval = lexer->tokenValue(); token_buffer[1].spell = yytokenspell = lexer->tokenSpell(); token_buffer[1].loc = yylloc = location(lexer); if (t_action(errorState, yytoken)) { QString msg; int token = token_buffer[0].token; if (token < 0 || token >= TERMINAL_COUNT) msg = qApp->translate("QmlParser", "Syntax error"); else msg = qApp->translate("QmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); action = errorState; goto _Lcheck_token; } static int tokens[] = { T_PLUS, T_EQ, T_COMMA, T_COLON, T_SEMICOLON, T_RPAREN, T_RBRACKET, T_RBRACE, T_NUMERIC_LITERAL, T_IDENTIFIER, T_LPAREN, T_LBRACKET, T_LBRACE, EOF_SYMBOL }; for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) { int a = t_action(errorState, *tk); if (a > 0 && t_action(a, yytoken)) { const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[*tk])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); yytoken = *tk; yylval = 0; yylloc = token_buffer[0].loc; yylloc.length = 0; first_token = &token_buffer[0]; last_token = &token_buffer[2]; action = errorState; goto _Lcheck_token; } } for (int tk = 1; tk < TERMINAL_COUNT; ++tk) { if (tk == T_AUTOMATIC_SEMICOLON || tk == T_FEED_UI_PROGRAM || tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION || tk == T_FEED_JS_SOURCE_ELEMENT) continue; int a = t_action(errorState, tk); if (a > 0 && t_action(a, yytoken)) { const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[tk])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); yytoken = tk; yylval = 0; yylloc = token_buffer[0].loc; yylloc.length = 0; action = errorState; goto _Lcheck_token; } } const QString msg = qApp->translate("QmlParser", "Syntax error"); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); } return false; } QT_QML_END_NAMESPACE ./ /: QT_QML_END_NAMESPACE #endif // QMLJSPARSER_P_H :/ qbs-src-1.4.5/src/lib/corelib/parser/qmljsast.cpp000066400000000000000000000423641266132464200217240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "qmljsast_p.h" #include "qmljsastvisitor_p.h" namespace QbsQmlJS { namespace AST { void Node::accept(Visitor *visitor) { if (visitor->preVisit(this)) { accept0(visitor); } visitor->postVisit(this); } void Node::accept(Node *node, Visitor *visitor) { if (node) node->accept(visitor); } ExpressionNode *Node::expressionCast() { return 0; } BinaryExpression *Node::binaryExpressionCast() { return 0; } Statement *Node::statementCast() { return 0; } UiObjectMember *Node::uiObjectMemberCast() { return 0; } ExpressionNode *ExpressionNode::expressionCast() { return this; } BinaryExpression *BinaryExpression::binaryExpressionCast() { return this; } Statement *Statement::statementCast() { return this; } UiObjectMember *UiObjectMember::uiObjectMemberCast() { return this; } void NestedExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void ThisExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void IdentifierExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void NullExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void TrueLiteral::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void FalseLiteral::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void StringLiteral::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void NumericLiteral::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void RegExpLiteral::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void ArrayLiteral::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(elements, visitor); accept(elision, visitor); } visitor->endVisit(this); } void ObjectLiteral::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(properties, visitor); } visitor->endVisit(this); } void ElementList::accept0(Visitor *visitor) { if (visitor->visit(this)) { for (ElementList *it = this; it; it = it->next) { accept(it->elision, visitor); accept(it->expression, visitor); } } visitor->endVisit(this); } void Elision::accept0(Visitor *visitor) { if (visitor->visit(this)) { // ### } visitor->endVisit(this); } void PropertyNameAndValueList::accept0(Visitor *visitor) { if (visitor->visit(this)) { for (PropertyNameAndValueList *it = this; it; it = it->next) { accept(it->name, visitor); accept(it->value, visitor); } } visitor->endVisit(this); } void IdentifierPropertyName::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void StringLiteralPropertyName::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void NumericLiteralPropertyName::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void ArrayMemberExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); accept(expression, visitor); } visitor->endVisit(this); } void FieldMemberExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); } visitor->endVisit(this); } void NewMemberExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); accept(arguments, visitor); } visitor->endVisit(this); } void NewExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void CallExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); accept(arguments, visitor); } visitor->endVisit(this); } void ArgumentList::accept0(Visitor *visitor) { if (visitor->visit(this)) { for (ArgumentList *it = this; it; it = it->next) { accept(it->expression, visitor); } } visitor->endVisit(this); } void PostIncrementExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); } visitor->endVisit(this); } void PostDecrementExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(base, visitor); } visitor->endVisit(this); } void DeleteExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void VoidExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void TypeOfExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void PreIncrementExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void PreDecrementExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void UnaryPlusExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void UnaryMinusExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void TildeExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void NotExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void BinaryExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(left, visitor); accept(right, visitor); } visitor->endVisit(this); } void ConditionalExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); accept(ok, visitor); accept(ko, visitor); } visitor->endVisit(this); } void Expression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(left, visitor); accept(right, visitor); } visitor->endVisit(this); } void Block::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(statements, visitor); } visitor->endVisit(this); } void StatementList::accept0(Visitor *visitor) { if (visitor->visit(this)) { for (StatementList *it = this; it; it = it->next) { accept(it->statement, visitor); } } visitor->endVisit(this); } void VariableStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(declarations, visitor); } visitor->endVisit(this); } void VariableDeclarationList::accept0(Visitor *visitor) { if (visitor->visit(this)) { for (VariableDeclarationList *it = this; it; it = it->next) { accept(it->declaration, visitor); } } visitor->endVisit(this); } void VariableDeclaration::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void EmptyStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void ExpressionStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void IfStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); accept(ok, visitor); accept(ko, visitor); } visitor->endVisit(this); } void DoWhileStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); accept(expression, visitor); } visitor->endVisit(this); } void WhileStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); accept(statement, visitor); } visitor->endVisit(this); } void ForStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(initialiser, visitor); accept(condition, visitor); accept(expression, visitor); accept(statement, visitor); } visitor->endVisit(this); } void LocalForStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(declarations, visitor); accept(condition, visitor); accept(expression, visitor); accept(statement, visitor); } visitor->endVisit(this); } void ForEachStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(initialiser, visitor); accept(expression, visitor); accept(statement, visitor); } visitor->endVisit(this); } void LocalForEachStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(declaration, visitor); accept(expression, visitor); accept(statement, visitor); } visitor->endVisit(this); } void ContinueStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void BreakStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void ReturnStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void WithStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); accept(statement, visitor); } visitor->endVisit(this); } void SwitchStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); accept(block, visitor); } visitor->endVisit(this); } void CaseBlock::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(clauses, visitor); accept(defaultClause, visitor); accept(moreClauses, visitor); } visitor->endVisit(this); } void CaseClauses::accept0(Visitor *visitor) { if (visitor->visit(this)) { for (CaseClauses *it = this; it; it = it->next) { accept(it->clause, visitor); } } visitor->endVisit(this); } void CaseClause::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); accept(statements, visitor); } visitor->endVisit(this); } void DefaultClause::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(statements, visitor); } visitor->endVisit(this); } void LabelledStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); } visitor->endVisit(this); } void ThrowStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(expression, visitor); } visitor->endVisit(this); } void TryStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); accept(catchExpression, visitor); accept(finallyExpression, visitor); } visitor->endVisit(this); } void Catch::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); } visitor->endVisit(this); } void Finally::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); } visitor->endVisit(this); } void FunctionDeclaration::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(formals, visitor); accept(body, visitor); } visitor->endVisit(this); } void FunctionExpression::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(formals, visitor); accept(body, visitor); } visitor->endVisit(this); } void FormalParameterList::accept0(Visitor *visitor) { if (visitor->visit(this)) { // ### } visitor->endVisit(this); } void FunctionBody::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(elements, visitor); } visitor->endVisit(this); } void Program::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(elements, visitor); } visitor->endVisit(this); } void SourceElements::accept0(Visitor *visitor) { if (visitor->visit(this)) { for (SourceElements *it = this; it; it = it->next) { accept(it->element, visitor); } } visitor->endVisit(this); } void FunctionSourceElement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(declaration, visitor); } visitor->endVisit(this); } void StatementSourceElement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); } visitor->endVisit(this); } void DebuggerStatement::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void UiProgram::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(imports, visitor); accept(members, visitor); } visitor->endVisit(this); } void UiPublicMember::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(statement, visitor); accept(binding, visitor); } visitor->endVisit(this); } void UiObjectDefinition::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(qualifiedTypeNameId, visitor); accept(initializer, visitor); } visitor->endVisit(this); } void UiObjectInitializer::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(members, visitor); } visitor->endVisit(this); } void UiObjectBinding::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(qualifiedId, visitor); accept(qualifiedTypeNameId, visitor); accept(initializer, visitor); } visitor->endVisit(this); } void UiScriptBinding::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(qualifiedId, visitor); accept(statement, visitor); } visitor->endVisit(this); } void UiArrayBinding::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(qualifiedId, visitor); accept(members, visitor); } visitor->endVisit(this); } void UiObjectMemberList::accept0(Visitor *visitor) { if (visitor->visit(this)) { for (UiObjectMemberList *it = this; it; it = it->next) accept(it->member, visitor); } visitor->endVisit(this); } void UiArrayMemberList::accept0(Visitor *visitor) { if (visitor->visit(this)) { for (UiArrayMemberList *it = this; it; it = it->next) accept(it->member, visitor); } visitor->endVisit(this); } void UiQualifiedId::accept0(Visitor *visitor) { if (visitor->visit(this)) { } visitor->endVisit(this); } void UiImport::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(importUri, visitor); } visitor->endVisit(this); } void UiImportList::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(import, visitor); accept(next, visitor); } visitor->endVisit(this); } void UiSourceElement::accept0(Visitor *visitor) { if (visitor->visit(this)) { accept(sourceElement, visitor); } visitor->endVisit(this); } } // namespace AST } // namespace QbsQmlJS qbs-src-1.4.5/src/lib/corelib/parser/qmljsast_p.h000066400000000000000000001774371266132464200217220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QMLJSAST_P_H #define QMLJSAST_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include "qmljsastvisitor_p.h" #include "qmljsglobal_p.h" #include "qmljsmemorypool_p.h" #include namespace QbsQmlJS { #define QMLJS_DECLARE_AST_NODE(name) \ enum { K = Kind_##name }; namespace QSOperator // ### rename { enum Op { Add, And, InplaceAnd, Assign, BitAnd, BitOr, BitXor, InplaceSub, Div, InplaceDiv, Equal, Ge, Gt, In, InplaceAdd, InstanceOf, Le, LShift, InplaceLeftShift, Lt, Mod, InplaceMod, Mul, InplaceMul, NotEqual, Or, InplaceOr, RShift, InplaceRightShift, StrictEqual, StrictNotEqual, Sub, URShift, InplaceURightShift, InplaceXor }; } // namespace QSOperator namespace AST { template _T1 cast(_T2 *ast) { if (ast && ast->kind == static_cast<_T1>(0)->K) return static_cast<_T1>(ast); return 0; } class QML_PARSER_EXPORT Node: public Managed { public: enum Kind { Kind_Undefined, Kind_ArgumentList, Kind_ArrayLiteral, Kind_ArrayMemberExpression, Kind_BinaryExpression, Kind_Block, Kind_BreakStatement, Kind_CallExpression, Kind_CaseBlock, Kind_CaseClause, Kind_CaseClauses, Kind_Catch, Kind_ConditionalExpression, Kind_ContinueStatement, Kind_DebuggerStatement, Kind_DefaultClause, Kind_DeleteExpression, Kind_DoWhileStatement, Kind_ElementList, Kind_Elision, Kind_EmptyStatement, Kind_Expression, Kind_ExpressionStatement, Kind_FalseLiteral, Kind_FieldMemberExpression, Kind_Finally, Kind_ForEachStatement, Kind_ForStatement, Kind_FormalParameterList, Kind_FunctionBody, Kind_FunctionDeclaration, Kind_FunctionExpression, Kind_FunctionSourceElement, Kind_IdentifierExpression, Kind_IdentifierPropertyName, Kind_IfStatement, Kind_LabelledStatement, Kind_LocalForEachStatement, Kind_LocalForStatement, Kind_NewExpression, Kind_NewMemberExpression, Kind_NotExpression, Kind_NullExpression, Kind_NumericLiteral, Kind_NumericLiteralPropertyName, Kind_ObjectLiteral, Kind_PostDecrementExpression, Kind_PostIncrementExpression, Kind_PreDecrementExpression, Kind_PreIncrementExpression, Kind_Program, Kind_PropertyName, Kind_PropertyNameAndValueList, Kind_RegExpLiteral, Kind_ReturnStatement, Kind_SourceElement, Kind_SourceElements, Kind_StatementList, Kind_StatementSourceElement, Kind_StringLiteral, Kind_StringLiteralPropertyName, Kind_SwitchStatement, Kind_ThisExpression, Kind_ThrowStatement, Kind_TildeExpression, Kind_TrueLiteral, Kind_TryStatement, Kind_TypeOfExpression, Kind_UnaryMinusExpression, Kind_UnaryPlusExpression, Kind_VariableDeclaration, Kind_VariableDeclarationList, Kind_VariableStatement, Kind_VoidExpression, Kind_WhileStatement, Kind_WithStatement, Kind_NestedExpression, Kind_UiArrayBinding, Kind_UiImport, Kind_UiImportList, Kind_UiObjectBinding, Kind_UiObjectDefinition, Kind_UiObjectInitializer, Kind_UiObjectMemberList, Kind_UiArrayMemberList, Kind_UiProgram, Kind_UiParameterList, Kind_UiPublicMember, Kind_UiQualifiedId, Kind_UiScriptBinding, Kind_UiSourceElement }; inline Node() : kind(Kind_Undefined) {} // NOTE: node destructors are never called, // instead we block free the memory // (see the NodePool class) virtual ~Node() {} virtual ExpressionNode *expressionCast(); virtual BinaryExpression *binaryExpressionCast(); virtual Statement *statementCast(); virtual UiObjectMember *uiObjectMemberCast(); void accept(Visitor *visitor); static void accept(Node *node, Visitor *visitor); inline static void acceptChild(Node *node, Visitor *visitor) { return accept(node, visitor); } // ### remove virtual void accept0(Visitor *visitor) = 0; virtual SourceLocation firstSourceLocation() const = 0; virtual SourceLocation lastSourceLocation() const = 0; // attributes int kind; }; class QML_PARSER_EXPORT ExpressionNode: public Node { public: ExpressionNode() {} virtual ExpressionNode *expressionCast(); }; class QML_PARSER_EXPORT Statement: public Node { public: Statement() {} virtual Statement *statementCast(); }; class QML_PARSER_EXPORT NestedExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(NestedExpression) NestedExpression(ExpressionNode *expression) : expression(expression) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return lparenToken; } virtual SourceLocation lastSourceLocation() const { return rparenToken; } // attributes ExpressionNode *expression; SourceLocation lparenToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT ThisExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(ThisExpression) ThisExpression() { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return thisToken; } virtual SourceLocation lastSourceLocation() const { return thisToken; } // attributes SourceLocation thisToken; }; class QML_PARSER_EXPORT IdentifierExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(IdentifierExpression) IdentifierExpression(const QStringRef &n): name (n) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return identifierToken; } virtual SourceLocation lastSourceLocation() const { return identifierToken; } // attributes QStringRef name; SourceLocation identifierToken; }; class QML_PARSER_EXPORT NullExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(NullExpression) NullExpression() { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return nullToken; } virtual SourceLocation lastSourceLocation() const { return nullToken; } // attributes SourceLocation nullToken; }; class QML_PARSER_EXPORT TrueLiteral: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(TrueLiteral) TrueLiteral() { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return trueToken; } virtual SourceLocation lastSourceLocation() const { return trueToken; } // attributes SourceLocation trueToken; }; class QML_PARSER_EXPORT FalseLiteral: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(FalseLiteral) FalseLiteral() { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return falseToken; } virtual SourceLocation lastSourceLocation() const { return falseToken; } // attributes SourceLocation falseToken; }; class QML_PARSER_EXPORT NumericLiteral: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(NumericLiteral) NumericLiteral(double v): value(v) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return literalToken; } virtual SourceLocation lastSourceLocation() const { return literalToken; } // attributes: double value; SourceLocation literalToken; }; class QML_PARSER_EXPORT StringLiteral: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(StringLiteral) StringLiteral(const QStringRef &v): value (v) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return literalToken; } virtual SourceLocation lastSourceLocation() const { return literalToken; } // attributes: QStringRef value; SourceLocation literalToken; }; class QML_PARSER_EXPORT RegExpLiteral: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(RegExpLiteral) RegExpLiteral(const QStringRef &p, int f): pattern (p), flags (f) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return literalToken; } virtual SourceLocation lastSourceLocation() const { return literalToken; } // attributes: QStringRef pattern; int flags; SourceLocation literalToken; }; class QML_PARSER_EXPORT ArrayLiteral: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(ArrayLiteral) ArrayLiteral(Elision *e): elements (0), elision (e) { kind = K; } ArrayLiteral(ElementList *elts): elements (elts), elision (0) { kind = K; } ArrayLiteral(ElementList *elts, Elision *e): elements (elts), elision (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return lbracketToken; } virtual SourceLocation lastSourceLocation() const { return rbracketToken; } // attributes ElementList *elements; Elision *elision; SourceLocation lbracketToken; SourceLocation commaToken; SourceLocation rbracketToken; }; class QML_PARSER_EXPORT ObjectLiteral: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(ObjectLiteral) ObjectLiteral(): properties (0) { kind = K; } ObjectLiteral(PropertyNameAndValueList *plist): properties (plist) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return lbraceToken; } virtual SourceLocation lastSourceLocation() const { return rbraceToken; } // attributes PropertyNameAndValueList *properties; SourceLocation lbraceToken; SourceLocation rbraceToken; }; class QML_PARSER_EXPORT Elision: public Node { public: QMLJS_DECLARE_AST_NODE(Elision) Elision(): next (this) { kind = K; } Elision(Elision *previous) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return commaToken; } virtual SourceLocation lastSourceLocation() const { return next ? next->lastSourceLocation() : commaToken; } inline Elision *finish () { Elision *front = next; next = 0; return front; } // attributes Elision *next; SourceLocation commaToken; }; class QML_PARSER_EXPORT ElementList: public Node { public: QMLJS_DECLARE_AST_NODE(ElementList) ElementList(Elision *e, ExpressionNode *expr): elision (e), expression (expr), next (this) { kind = K; } ElementList(ElementList *previous, Elision *e, ExpressionNode *expr): elision (e), expression (expr) { kind = K; next = previous->next; previous->next = this; } inline ElementList *finish () { ElementList *front = next; next = 0; return front; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { if (elision) return elision->firstSourceLocation(); return expression->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { if (next) return next->lastSourceLocation(); return expression->lastSourceLocation(); } // attributes Elision *elision; ExpressionNode *expression; ElementList *next; SourceLocation commaToken; }; class QML_PARSER_EXPORT PropertyName: public Node { public: QMLJS_DECLARE_AST_NODE(PropertyName) PropertyName() { kind = K; } virtual SourceLocation firstSourceLocation() const { return propertyNameToken; } virtual SourceLocation lastSourceLocation() const { return propertyNameToken; } // attributes SourceLocation propertyNameToken; }; class QML_PARSER_EXPORT PropertyNameAndValueList: public Node { public: QMLJS_DECLARE_AST_NODE(PropertyNameAndValueList) PropertyNameAndValueList(PropertyName *n, ExpressionNode *v): name (n), value (v), next (this) { kind = K; } PropertyNameAndValueList(PropertyNameAndValueList *previous, PropertyName *n, ExpressionNode *v): name (n), value (v) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return name->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { if (next) return next->lastSourceLocation(); return value->lastSourceLocation(); } inline PropertyNameAndValueList *finish () { PropertyNameAndValueList *front = next; next = 0; return front; } // attributes PropertyName *name; ExpressionNode *value; PropertyNameAndValueList *next; SourceLocation colonToken; SourceLocation commaToken; }; class QML_PARSER_EXPORT IdentifierPropertyName: public PropertyName { public: QMLJS_DECLARE_AST_NODE(IdentifierPropertyName) IdentifierPropertyName(const QStringRef &n): id (n) { kind = K; } virtual void accept0(Visitor *visitor); // attributes QStringRef id; }; class QML_PARSER_EXPORT StringLiteralPropertyName: public PropertyName { public: QMLJS_DECLARE_AST_NODE(StringLiteralPropertyName) StringLiteralPropertyName(const QStringRef &n): id (n) { kind = K; } virtual void accept0(Visitor *visitor); // attributes QStringRef id; }; class QML_PARSER_EXPORT NumericLiteralPropertyName: public PropertyName { public: QMLJS_DECLARE_AST_NODE(NumericLiteralPropertyName) NumericLiteralPropertyName(double n): id (n) { kind = K; } virtual void accept0(Visitor *visitor); // attributes double id; }; class QML_PARSER_EXPORT ArrayMemberExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(ArrayMemberExpression) ArrayMemberExpression(ExpressionNode *b, ExpressionNode *e): base (b), expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return base->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return rbracketToken; } // attributes ExpressionNode *base; ExpressionNode *expression; SourceLocation lbracketToken; SourceLocation rbracketToken; }; class QML_PARSER_EXPORT FieldMemberExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(FieldMemberExpression) FieldMemberExpression(ExpressionNode *b, const QStringRef &n): base (b), name (n) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return base->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return identifierToken; } // attributes ExpressionNode *base; QStringRef name; SourceLocation dotToken; SourceLocation identifierToken; }; class QML_PARSER_EXPORT NewMemberExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(NewMemberExpression) NewMemberExpression(ExpressionNode *b, ArgumentList *a): base (b), arguments (a) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return newToken; } virtual SourceLocation lastSourceLocation() const { return rparenToken; } // attributes ExpressionNode *base; ArgumentList *arguments; SourceLocation newToken; SourceLocation lparenToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT NewExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(NewExpression) NewExpression(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return newToken; } virtual SourceLocation lastSourceLocation() const { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; SourceLocation newToken; }; class QML_PARSER_EXPORT CallExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(CallExpression) CallExpression(ExpressionNode *b, ArgumentList *a): base (b), arguments (a) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return base->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return rparenToken; } // attributes ExpressionNode *base; ArgumentList *arguments; SourceLocation lparenToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT ArgumentList: public Node { public: QMLJS_DECLARE_AST_NODE(ArgumentList) ArgumentList(ExpressionNode *e): expression (e), next (this) { kind = K; } ArgumentList(ArgumentList *previous, ExpressionNode *e): expression (e) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return expression->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { if (next) return next->lastSourceLocation(); return expression->lastSourceLocation(); } inline ArgumentList *finish () { ArgumentList *front = next; next = 0; return front; } // attributes ExpressionNode *expression; ArgumentList *next; SourceLocation commaToken; }; class QML_PARSER_EXPORT PostIncrementExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(PostIncrementExpression) PostIncrementExpression(ExpressionNode *b): base (b) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return base->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return incrementToken; } // attributes ExpressionNode *base; SourceLocation incrementToken; }; class QML_PARSER_EXPORT PostDecrementExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(PostDecrementExpression) PostDecrementExpression(ExpressionNode *b): base (b) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return base->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return decrementToken; } // attributes ExpressionNode *base; SourceLocation decrementToken; }; class QML_PARSER_EXPORT DeleteExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(DeleteExpression) DeleteExpression(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return deleteToken; } virtual SourceLocation lastSourceLocation() const { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; SourceLocation deleteToken; }; class QML_PARSER_EXPORT VoidExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(VoidExpression) VoidExpression(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return voidToken; } virtual SourceLocation lastSourceLocation() const { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; SourceLocation voidToken; }; class QML_PARSER_EXPORT TypeOfExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(TypeOfExpression) TypeOfExpression(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return typeofToken; } virtual SourceLocation lastSourceLocation() const { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; SourceLocation typeofToken; }; class QML_PARSER_EXPORT PreIncrementExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(PreIncrementExpression) PreIncrementExpression(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return incrementToken; } virtual SourceLocation lastSourceLocation() const { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; SourceLocation incrementToken; }; class QML_PARSER_EXPORT PreDecrementExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(PreDecrementExpression) PreDecrementExpression(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return decrementToken; } virtual SourceLocation lastSourceLocation() const { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; SourceLocation decrementToken; }; class QML_PARSER_EXPORT UnaryPlusExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(UnaryPlusExpression) UnaryPlusExpression(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return plusToken; } virtual SourceLocation lastSourceLocation() const { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; SourceLocation plusToken; }; class QML_PARSER_EXPORT UnaryMinusExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(UnaryMinusExpression) UnaryMinusExpression(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return minusToken; } virtual SourceLocation lastSourceLocation() const { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; SourceLocation minusToken; }; class QML_PARSER_EXPORT TildeExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(TildeExpression) TildeExpression(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return tildeToken; } virtual SourceLocation lastSourceLocation() const { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; SourceLocation tildeToken; }; class QML_PARSER_EXPORT NotExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(NotExpression) NotExpression(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return notToken; } virtual SourceLocation lastSourceLocation() const { return expression->lastSourceLocation(); } // attributes ExpressionNode *expression; SourceLocation notToken; }; class QML_PARSER_EXPORT BinaryExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(BinaryExpression) BinaryExpression(ExpressionNode *l, int o, ExpressionNode *r): left (l), op (o), right (r) { kind = K; } virtual BinaryExpression *binaryExpressionCast(); virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return left->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return right->lastSourceLocation(); } // attributes ExpressionNode *left; int op; ExpressionNode *right; SourceLocation operatorToken; }; class QML_PARSER_EXPORT ConditionalExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(ConditionalExpression) ConditionalExpression(ExpressionNode *e, ExpressionNode *t, ExpressionNode *f): expression (e), ok (t), ko (f) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return expression->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return ko->lastSourceLocation(); } // attributes ExpressionNode *expression; ExpressionNode *ok; ExpressionNode *ko; SourceLocation questionToken; SourceLocation colonToken; }; class QML_PARSER_EXPORT Expression: public ExpressionNode // ### rename { public: QMLJS_DECLARE_AST_NODE(Expression) Expression(ExpressionNode *l, ExpressionNode *r): left (l), right (r) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return left->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return right->lastSourceLocation(); } // attributes ExpressionNode *left; ExpressionNode *right; SourceLocation commaToken; }; class QML_PARSER_EXPORT Block: public Statement { public: QMLJS_DECLARE_AST_NODE(Block) Block(StatementList *slist): statements (slist) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return lbraceToken; } virtual SourceLocation lastSourceLocation() const { return rbraceToken; } // attributes StatementList *statements; SourceLocation lbraceToken; SourceLocation rbraceToken; }; class QML_PARSER_EXPORT StatementList: public Node { public: QMLJS_DECLARE_AST_NODE(StatementList) StatementList(Statement *stmt): statement (stmt), next (this) { kind = K; } StatementList(StatementList *previous, Statement *stmt): statement (stmt) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return statement->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return next ? next->lastSourceLocation() : statement->lastSourceLocation(); } inline StatementList *finish () { StatementList *front = next; next = 0; return front; } // attributes Statement *statement; StatementList *next; }; class QML_PARSER_EXPORT VariableStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(VariableStatement) VariableStatement(VariableDeclarationList *vlist): declarations (vlist) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return declarationKindToken; } virtual SourceLocation lastSourceLocation() const { return semicolonToken; } // attributes VariableDeclarationList *declarations; SourceLocation declarationKindToken; SourceLocation semicolonToken; }; class QML_PARSER_EXPORT VariableDeclaration: public Node { public: QMLJS_DECLARE_AST_NODE(VariableDeclaration) VariableDeclaration(const QStringRef &n, ExpressionNode *e): name (n), expression (e), readOnly(false) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return identifierToken; } virtual SourceLocation lastSourceLocation() const { return expression ? expression->lastSourceLocation() : identifierToken; } // attributes QStringRef name; ExpressionNode *expression; bool readOnly; SourceLocation identifierToken; }; class QML_PARSER_EXPORT VariableDeclarationList: public Node { public: QMLJS_DECLARE_AST_NODE(VariableDeclarationList) VariableDeclarationList(VariableDeclaration *decl): declaration (decl), next (this) { kind = K; } VariableDeclarationList(VariableDeclarationList *previous, VariableDeclaration *decl): declaration (decl) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return declaration->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { if (next) return next->lastSourceLocation(); return declaration->lastSourceLocation(); } inline VariableDeclarationList *finish (bool readOnly) { VariableDeclarationList *front = next; next = 0; if (readOnly) { VariableDeclarationList *vdl; for (vdl = front; vdl != 0; vdl = vdl->next) vdl->declaration->readOnly = true; } return front; } // attributes VariableDeclaration *declaration; VariableDeclarationList *next; SourceLocation commaToken; }; class QML_PARSER_EXPORT EmptyStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(EmptyStatement) EmptyStatement() { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return semicolonToken; } virtual SourceLocation lastSourceLocation() const { return semicolonToken; } // attributes SourceLocation semicolonToken; }; class QML_PARSER_EXPORT ExpressionStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(ExpressionStatement) ExpressionStatement(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return expression->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return semicolonToken; } // attributes ExpressionNode *expression; SourceLocation semicolonToken; }; class QML_PARSER_EXPORT IfStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(IfStatement) IfStatement(ExpressionNode *e, Statement *t, Statement *f = 0): expression (e), ok (t), ko (f) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return ifToken; } virtual SourceLocation lastSourceLocation() const { if (ko) return ko->lastSourceLocation(); return ok->lastSourceLocation(); } // attributes ExpressionNode *expression; Statement *ok; Statement *ko; SourceLocation ifToken; SourceLocation lparenToken; SourceLocation rparenToken; SourceLocation elseToken; }; class QML_PARSER_EXPORT DoWhileStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(DoWhileStatement) DoWhileStatement(Statement *stmt, ExpressionNode *e): statement (stmt), expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return doToken; } virtual SourceLocation lastSourceLocation() const { return semicolonToken; } // attributes Statement *statement; ExpressionNode *expression; SourceLocation doToken; SourceLocation whileToken; SourceLocation lparenToken; SourceLocation rparenToken; SourceLocation semicolonToken; }; class QML_PARSER_EXPORT WhileStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(WhileStatement) WhileStatement(ExpressionNode *e, Statement *stmt): expression (e), statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return whileToken; } virtual SourceLocation lastSourceLocation() const { return statement->lastSourceLocation(); } // attributes ExpressionNode *expression; Statement *statement; SourceLocation whileToken; SourceLocation lparenToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT ForStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(ForStatement) ForStatement(ExpressionNode *i, ExpressionNode *c, ExpressionNode *e, Statement *stmt): initialiser (i), condition (c), expression (e), statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return forToken; } virtual SourceLocation lastSourceLocation() const { return statement->lastSourceLocation(); } // attributes ExpressionNode *initialiser; ExpressionNode *condition; ExpressionNode *expression; Statement *statement; SourceLocation forToken; SourceLocation lparenToken; SourceLocation firstSemicolonToken; SourceLocation secondSemicolonToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT LocalForStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(LocalForStatement) LocalForStatement(VariableDeclarationList *vlist, ExpressionNode *c, ExpressionNode *e, Statement *stmt): declarations (vlist), condition (c), expression (e), statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return forToken; } virtual SourceLocation lastSourceLocation() const { return statement->lastSourceLocation(); } // attributes VariableDeclarationList *declarations; ExpressionNode *condition; ExpressionNode *expression; Statement *statement; SourceLocation forToken; SourceLocation lparenToken; SourceLocation varToken; SourceLocation firstSemicolonToken; SourceLocation secondSemicolonToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT ForEachStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(ForEachStatement) ForEachStatement(ExpressionNode *i, ExpressionNode *e, Statement *stmt): initialiser (i), expression (e), statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return forToken; } virtual SourceLocation lastSourceLocation() const { return statement->lastSourceLocation(); } // attributes ExpressionNode *initialiser; ExpressionNode *expression; Statement *statement; SourceLocation forToken; SourceLocation lparenToken; SourceLocation inToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT LocalForEachStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(LocalForEachStatement) LocalForEachStatement(VariableDeclaration *v, ExpressionNode *e, Statement *stmt): declaration (v), expression (e), statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return forToken; } virtual SourceLocation lastSourceLocation() const { return statement->lastSourceLocation(); } // attributes VariableDeclaration *declaration; ExpressionNode *expression; Statement *statement; SourceLocation forToken; SourceLocation lparenToken; SourceLocation varToken; SourceLocation inToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT ContinueStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(ContinueStatement) ContinueStatement(const QStringRef &l = QStringRef()): label (l) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return continueToken; } virtual SourceLocation lastSourceLocation() const { return semicolonToken; } // attributes QStringRef label; SourceLocation continueToken; SourceLocation identifierToken; SourceLocation semicolonToken; }; class QML_PARSER_EXPORT BreakStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(BreakStatement) BreakStatement(const QStringRef &l): label (l) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return breakToken; } virtual SourceLocation lastSourceLocation() const { return semicolonToken; } // attributes QStringRef label; SourceLocation breakToken; SourceLocation identifierToken; SourceLocation semicolonToken; }; class QML_PARSER_EXPORT ReturnStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(ReturnStatement) ReturnStatement(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return returnToken; } virtual SourceLocation lastSourceLocation() const { return semicolonToken; } // attributes ExpressionNode *expression; SourceLocation returnToken; SourceLocation semicolonToken; }; class QML_PARSER_EXPORT WithStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(WithStatement) WithStatement(ExpressionNode *e, Statement *stmt): expression (e), statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return withToken; } virtual SourceLocation lastSourceLocation() const { return statement->lastSourceLocation(); } // attributes ExpressionNode *expression; Statement *statement; SourceLocation withToken; SourceLocation lparenToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT CaseBlock: public Node { public: QMLJS_DECLARE_AST_NODE(CaseBlock) CaseBlock(CaseClauses *c, DefaultClause *d = 0, CaseClauses *r = 0): clauses (c), defaultClause (d), moreClauses (r) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return lbraceToken; } virtual SourceLocation lastSourceLocation() const { return rbraceToken; } // attributes CaseClauses *clauses; DefaultClause *defaultClause; CaseClauses *moreClauses; SourceLocation lbraceToken; SourceLocation rbraceToken; }; class QML_PARSER_EXPORT SwitchStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(SwitchStatement) SwitchStatement(ExpressionNode *e, CaseBlock *b): expression (e), block (b) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return switchToken; } virtual SourceLocation lastSourceLocation() const { return block->rbraceToken; } // attributes ExpressionNode *expression; CaseBlock *block; SourceLocation switchToken; SourceLocation lparenToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT CaseClause: public Node { public: QMLJS_DECLARE_AST_NODE(CaseClause) CaseClause(ExpressionNode *e, StatementList *slist): expression (e), statements (slist) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return caseToken; } virtual SourceLocation lastSourceLocation() const { return statements ? statements->lastSourceLocation() : colonToken; } // attributes ExpressionNode *expression; StatementList *statements; SourceLocation caseToken; SourceLocation colonToken; }; class QML_PARSER_EXPORT CaseClauses: public Node { public: QMLJS_DECLARE_AST_NODE(CaseClauses) CaseClauses(CaseClause *c): clause (c), next (this) { kind = K; } CaseClauses(CaseClauses *previous, CaseClause *c): clause (c) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return clause->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return next ? next->lastSourceLocation() : clause->lastSourceLocation(); } inline CaseClauses *finish () { CaseClauses *front = next; next = 0; return front; } //attributes CaseClause *clause; CaseClauses *next; }; class QML_PARSER_EXPORT DefaultClause: public Node { public: QMLJS_DECLARE_AST_NODE(DefaultClause) DefaultClause(StatementList *slist): statements (slist) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return defaultToken; } virtual SourceLocation lastSourceLocation() const { return statements ? statements->lastSourceLocation() : colonToken; } // attributes StatementList *statements; SourceLocation defaultToken; SourceLocation colonToken; }; class QML_PARSER_EXPORT LabelledStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(LabelledStatement) LabelledStatement(const QStringRef &l, Statement *stmt): label (l), statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return identifierToken; } virtual SourceLocation lastSourceLocation() const { return statement->lastSourceLocation(); } // attributes QStringRef label; Statement *statement; SourceLocation identifierToken; SourceLocation colonToken; }; class QML_PARSER_EXPORT ThrowStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(ThrowStatement) ThrowStatement(ExpressionNode *e): expression (e) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return throwToken; } virtual SourceLocation lastSourceLocation() const { return semicolonToken; } // attributes ExpressionNode *expression; SourceLocation throwToken; SourceLocation semicolonToken; }; class QML_PARSER_EXPORT Catch: public Node { public: QMLJS_DECLARE_AST_NODE(Catch) Catch(const QStringRef &n, Block *stmt): name (n), statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return catchToken; } virtual SourceLocation lastSourceLocation() const { return statement->lastSourceLocation(); } // attributes QStringRef name; Block *statement; SourceLocation catchToken; SourceLocation lparenToken; SourceLocation identifierToken; SourceLocation rparenToken; }; class QML_PARSER_EXPORT Finally: public Node { public: QMLJS_DECLARE_AST_NODE(Finally) Finally(Block *stmt): statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return finallyToken; } virtual SourceLocation lastSourceLocation() const { return statement ? statement->lastSourceLocation() : finallyToken; } // attributes Block *statement; SourceLocation finallyToken; }; class QML_PARSER_EXPORT TryStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(TryStatement) TryStatement(Statement *stmt, Catch *c, Finally *f): statement (stmt), catchExpression (c), finallyExpression (f) { kind = K; } TryStatement(Statement *stmt, Finally *f): statement (stmt), catchExpression (0), finallyExpression (f) { kind = K; } TryStatement(Statement *stmt, Catch *c): statement (stmt), catchExpression (c), finallyExpression (0) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return tryToken; } virtual SourceLocation lastSourceLocation() const { if (finallyExpression) return finallyExpression->statement->rbraceToken; else if (catchExpression) return catchExpression->statement->rbraceToken; return statement->lastSourceLocation(); } // attributes Statement *statement; Catch *catchExpression; Finally *finallyExpression; SourceLocation tryToken; }; class QML_PARSER_EXPORT FunctionExpression: public ExpressionNode { public: QMLJS_DECLARE_AST_NODE(FunctionExpression) FunctionExpression(const QStringRef &n, FormalParameterList *f, FunctionBody *b): name (n), formals (f), body (b) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return functionToken; } virtual SourceLocation lastSourceLocation() const { return rbraceToken; } // attributes QStringRef name; FormalParameterList *formals; FunctionBody *body; SourceLocation functionToken; SourceLocation identifierToken; SourceLocation lparenToken; SourceLocation rparenToken; SourceLocation lbraceToken; SourceLocation rbraceToken; }; class QML_PARSER_EXPORT FunctionDeclaration: public FunctionExpression { public: QMLJS_DECLARE_AST_NODE(FunctionDeclaration) FunctionDeclaration(const QStringRef &n, FormalParameterList *f, FunctionBody *b): FunctionExpression(n, f, b) { kind = K; } virtual void accept0(Visitor *visitor); }; class QML_PARSER_EXPORT FormalParameterList: public Node { public: QMLJS_DECLARE_AST_NODE(FormalParameterList) FormalParameterList(const QStringRef &n): name (n), next (this) { kind = K; } FormalParameterList(FormalParameterList *previous, const QStringRef &n): name (n) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return identifierToken; } virtual SourceLocation lastSourceLocation() const { return next ? next->lastSourceLocation() : identifierToken; } inline FormalParameterList *finish () { FormalParameterList *front = next; next = 0; return front; } // attributes QStringRef name; FormalParameterList *next; SourceLocation commaToken; SourceLocation identifierToken; }; class QML_PARSER_EXPORT SourceElement: public Node { public: QMLJS_DECLARE_AST_NODE(SourceElement) inline SourceElement() { kind = K; } }; class QML_PARSER_EXPORT SourceElements: public Node { public: QMLJS_DECLARE_AST_NODE(SourceElements) SourceElements(SourceElement *elt): element (elt), next (this) { kind = K; } SourceElements(SourceElements *previous, SourceElement *elt): element (elt) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return element->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return next ? next->lastSourceLocation() : element->lastSourceLocation(); } inline SourceElements *finish () { SourceElements *front = next; next = 0; return front; } // attributes SourceElement *element; SourceElements *next; }; class QML_PARSER_EXPORT FunctionBody: public Node { public: QMLJS_DECLARE_AST_NODE(FunctionBody) FunctionBody(SourceElements *elts): elements (elts) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return elements ? elements->firstSourceLocation() : SourceLocation(); } virtual SourceLocation lastSourceLocation() const { return elements ? elements->lastSourceLocation() : SourceLocation(); } // attributes SourceElements *elements; }; class QML_PARSER_EXPORT Program: public Node { public: QMLJS_DECLARE_AST_NODE(Program) Program(SourceElements *elts): elements (elts) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return elements ? elements->firstSourceLocation() : SourceLocation(); } virtual SourceLocation lastSourceLocation() const { return elements ? elements->lastSourceLocation() : SourceLocation(); } // attributes SourceElements *elements; }; class QML_PARSER_EXPORT FunctionSourceElement: public SourceElement { public: QMLJS_DECLARE_AST_NODE(FunctionSourceElement) FunctionSourceElement(FunctionDeclaration *f): declaration (f) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return declaration->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return declaration->lastSourceLocation(); } // attributes FunctionDeclaration *declaration; }; class QML_PARSER_EXPORT StatementSourceElement: public SourceElement { public: QMLJS_DECLARE_AST_NODE(StatementSourceElement) StatementSourceElement(Statement *stmt): statement (stmt) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return statement->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return statement->lastSourceLocation(); } // attributes Statement *statement; }; class QML_PARSER_EXPORT DebuggerStatement: public Statement { public: QMLJS_DECLARE_AST_NODE(DebuggerStatement) DebuggerStatement() { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return debuggerToken; } virtual SourceLocation lastSourceLocation() const { return semicolonToken; } // attributes SourceLocation debuggerToken; SourceLocation semicolonToken; }; class QML_PARSER_EXPORT UiQualifiedId: public Node { public: QMLJS_DECLARE_AST_NODE(UiQualifiedId) UiQualifiedId(const QStringRef &name) : next(this), name(name) { kind = K; } UiQualifiedId(UiQualifiedId *previous, const QStringRef &name) : name(name) { kind = K; next = previous->next; previous->next = this; } UiQualifiedId *finish() { UiQualifiedId *head = next; next = 0; return head; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return identifierToken; } virtual SourceLocation lastSourceLocation() const { return next ? next->lastSourceLocation() : identifierToken; } // attributes UiQualifiedId *next; QStringRef name; SourceLocation identifierToken; }; class QML_PARSER_EXPORT UiImport: public Node { public: QMLJS_DECLARE_AST_NODE(UiImport) UiImport(const QStringRef &fileName) : fileName(fileName), importUri(0) { kind = K; } UiImport(UiQualifiedId *uri) : importUri(uri) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return importToken; } virtual SourceLocation lastSourceLocation() const { return semicolonToken; } // attributes QStringRef fileName; UiQualifiedId *importUri; QStringRef importId; SourceLocation importToken; SourceLocation fileNameToken; SourceLocation versionToken; SourceLocation asToken; SourceLocation importIdToken; SourceLocation semicolonToken; }; class QML_PARSER_EXPORT UiImportList: public Node { public: QMLJS_DECLARE_AST_NODE(UiImportList) UiImportList(UiImport *import) : import(import), next(this) { kind = K; } UiImportList(UiImportList *previous, UiImport *import) : import(import) { kind = K; next = previous->next; previous->next = this; } UiImportList *finish() { UiImportList *head = next; next = 0; return head; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return import->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return next ? next->lastSourceLocation() : import->lastSourceLocation(); } // attributes UiImport *import; UiImportList *next; }; class QML_PARSER_EXPORT UiObjectMember: public Node { public: virtual SourceLocation firstSourceLocation() const = 0; virtual SourceLocation lastSourceLocation() const = 0; virtual UiObjectMember *uiObjectMemberCast(); }; class QML_PARSER_EXPORT UiObjectMemberList: public Node { public: QMLJS_DECLARE_AST_NODE(UiObjectMemberList) UiObjectMemberList(UiObjectMember *member) : next(this), member(member) { kind = K; } UiObjectMemberList(UiObjectMemberList *previous, UiObjectMember *member) : member(member) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return member->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return next ? next->lastSourceLocation() : member->lastSourceLocation(); } UiObjectMemberList *finish() { UiObjectMemberList *head = next; next = 0; return head; } // attributes UiObjectMemberList *next; UiObjectMember *member; }; class QML_PARSER_EXPORT UiProgram: public Node { public: QMLJS_DECLARE_AST_NODE(UiProgram) UiProgram(UiImportList *imports, UiObjectMemberList *members) : imports(imports), members(members) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { if (imports) return imports->firstSourceLocation(); else if (members) return members->firstSourceLocation(); return SourceLocation(); } virtual SourceLocation lastSourceLocation() const { if (members) return members->lastSourceLocation(); else if (imports) return imports->lastSourceLocation(); return SourceLocation(); } // attributes UiImportList *imports; UiObjectMemberList *members; }; class QML_PARSER_EXPORT UiArrayMemberList: public Node { public: QMLJS_DECLARE_AST_NODE(UiArrayMemberList) UiArrayMemberList(UiObjectMember *member) : next(this), member(member) { kind = K; } UiArrayMemberList(UiArrayMemberList *previous, UiObjectMember *member) : member(member) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return member->firstSourceLocation(); } virtual SourceLocation lastSourceLocation() const { return next ? next->lastSourceLocation() : member->lastSourceLocation(); } UiArrayMemberList *finish() { UiArrayMemberList *head = next; next = 0; return head; } // attributes UiArrayMemberList *next; UiObjectMember *member; SourceLocation commaToken; }; class QML_PARSER_EXPORT UiObjectInitializer: public Node { public: QMLJS_DECLARE_AST_NODE(UiObjectInitializer) UiObjectInitializer(UiObjectMemberList *members) : members(members) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return lbraceToken; } virtual SourceLocation lastSourceLocation() const { return rbraceToken; } // attributes SourceLocation lbraceToken; UiObjectMemberList *members; SourceLocation rbraceToken; }; class QML_PARSER_EXPORT UiParameterList: public Node { public: QMLJS_DECLARE_AST_NODE(UiParameterList) UiParameterList(const QStringRef &t, const QStringRef &n): type (t), name (n), next (this) { kind = K; } UiParameterList(UiParameterList *previous, const QStringRef &t, const QStringRef &n): type (t), name (n) { kind = K; next = previous->next; previous->next = this; } virtual void accept0(Visitor *) {} virtual SourceLocation firstSourceLocation() const { return propertyTypeToken; } virtual SourceLocation lastSourceLocation() const { return next ? next->lastSourceLocation() : identifierToken; } inline UiParameterList *finish () { UiParameterList *front = next; next = 0; return front; } // attributes QStringRef type; QStringRef name; UiParameterList *next; SourceLocation commaToken; SourceLocation propertyTypeToken; SourceLocation identifierToken; }; class QML_PARSER_EXPORT UiPublicMember: public UiObjectMember { public: QMLJS_DECLARE_AST_NODE(UiPublicMember) UiPublicMember(const QStringRef &memberType, const QStringRef &name) : type(Property), memberType(memberType), name(name), statement(0), binding(0), isDefaultMember(false), isReadonlyMember(false), parameters(0) { kind = K; } UiPublicMember(const QStringRef &memberType, const QStringRef &name, Statement *statement) : type(Property), memberType(memberType), name(name), statement(statement), binding(0), isDefaultMember(false), isReadonlyMember(false), parameters(0) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { if (defaultToken.isValid()) return defaultToken; else if (readonlyToken.isValid()) return readonlyToken; return propertyToken; } virtual SourceLocation lastSourceLocation() const { if (binding) return binding->lastSourceLocation(); if (statement) return statement->lastSourceLocation(); return semicolonToken; } // attributes enum { Signal, Property } type; QStringRef typeModifier; QStringRef memberType; QStringRef name; Statement *statement; // initialized with a JS expression UiObjectMember *binding; // initialized with a QML object or array. bool isDefaultMember; bool isReadonlyMember; UiParameterList *parameters; SourceLocation defaultToken; SourceLocation readonlyToken; SourceLocation propertyToken; SourceLocation typeModifierToken; SourceLocation typeToken; SourceLocation identifierToken; SourceLocation colonToken; SourceLocation semicolonToken; }; class QML_PARSER_EXPORT UiObjectDefinition: public UiObjectMember { public: QMLJS_DECLARE_AST_NODE(UiObjectDefinition) UiObjectDefinition(UiQualifiedId *qualifiedTypeNameId, UiObjectInitializer *initializer) : qualifiedTypeNameId(qualifiedTypeNameId), initializer(initializer) { kind = K; } virtual void accept0(Visitor *visitor); virtual SourceLocation firstSourceLocation() const { return qualifiedTypeNameId->identifierToken; } virtual SourceLocation lastSourceLocation() const { return initializer->rbraceToken; } // attributes UiQualifiedId *qualifiedTypeNameId; UiObjectInitializer *initializer; }; class QML_PARSER_EXPORT UiSourceElement: public UiObjectMember { public: QMLJS_DECLARE_AST_NODE(UiSourceElement) UiSourceElement(Node *sourceElement) : sourceElement(sourceElement) { kind = K; } virtual SourceLocation firstSourceLocation() const { if (FunctionDeclaration *funDecl = cast(sourceElement)) return funDecl->firstSourceLocation(); else if (VariableStatement *varStmt = cast(sourceElement)) return varStmt->firstSourceLocation(); return SourceLocation(); } virtual SourceLocation lastSourceLocation() const { if (FunctionDeclaration *funDecl = cast(sourceElement)) return funDecl->lastSourceLocation(); else if (VariableStatement *varStmt = cast(sourceElement)) return varStmt->lastSourceLocation(); return SourceLocation(); } virtual void accept0(Visitor *visitor); // attributes Node *sourceElement; }; class QML_PARSER_EXPORT UiObjectBinding: public UiObjectMember { public: QMLJS_DECLARE_AST_NODE(UiObjectBinding) UiObjectBinding(UiQualifiedId *qualifiedId, UiQualifiedId *qualifiedTypeNameId, UiObjectInitializer *initializer) : qualifiedId(qualifiedId), qualifiedTypeNameId(qualifiedTypeNameId), initializer(initializer), hasOnToken(false) { kind = K; } virtual SourceLocation firstSourceLocation() const { if (hasOnToken && qualifiedTypeNameId) return qualifiedTypeNameId->identifierToken; return qualifiedId->identifierToken; } virtual SourceLocation lastSourceLocation() const { return initializer->rbraceToken; } virtual void accept0(Visitor *visitor); // attributes UiQualifiedId *qualifiedId; UiQualifiedId *qualifiedTypeNameId; UiObjectInitializer *initializer; SourceLocation colonToken; bool hasOnToken; }; class QML_PARSER_EXPORT UiScriptBinding: public UiObjectMember { public: QMLJS_DECLARE_AST_NODE(UiScriptBinding) UiScriptBinding(UiQualifiedId *qualifiedId, Statement *statement) : qualifiedId(qualifiedId), statement(statement) { kind = K; } virtual SourceLocation firstSourceLocation() const { return qualifiedId->identifierToken; } virtual SourceLocation lastSourceLocation() const { return statement->lastSourceLocation(); } virtual void accept0(Visitor *visitor); // attributes UiQualifiedId *qualifiedId; Statement *statement; SourceLocation colonToken; }; class QML_PARSER_EXPORT UiArrayBinding: public UiObjectMember { public: QMLJS_DECLARE_AST_NODE(UiArrayBinding) UiArrayBinding(UiQualifiedId *qualifiedId, UiArrayMemberList *members) : qualifiedId(qualifiedId), members(members) { kind = K; } virtual SourceLocation firstSourceLocation() const { return qualifiedId->identifierToken; } virtual SourceLocation lastSourceLocation() const { return rbracketToken; } virtual void accept0(Visitor *visitor); // attributes UiQualifiedId *qualifiedId; UiArrayMemberList *members; SourceLocation colonToken; SourceLocation lbracketToken; SourceLocation rbracketToken; }; } // namespace AST } // namespace QbsQmlJS #endif qbs-src-1.4.5/src/lib/corelib/parser/qmljsastfwd_p.h000066400000000000000000000110611266132464200223770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QMLJSAST_FWD_P_H #define QMLJSAST_FWD_P_H #include "qmljsglobal_p.h" #include // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // namespace QbsQmlJS { namespace AST { class SourceLocation { public: SourceLocation(quint32 offset = 0, quint32 length = 0, quint32 line = 0, quint32 column = 0) : offset(offset), length(length), startLine(line), startColumn(column) { } bool isValid() const { return length != 0; } quint32 begin() const { return offset; } quint32 end() const { return offset + length; } // attributes // ### encode quint32 offset; quint32 length; quint32 startLine; quint32 startColumn; }; class Visitor; class Node; class ExpressionNode; class Statement; class ThisExpression; class IdentifierExpression; class NullExpression; class TrueLiteral; class FalseLiteral; class NumericLiteral; class StringLiteral; class RegExpLiteral; class ArrayLiteral; class ObjectLiteral; class ElementList; class Elision; class PropertyNameAndValueList; class PropertyName; class IdentifierPropertyName; class StringLiteralPropertyName; class NumericLiteralPropertyName; class ArrayMemberExpression; class FieldMemberExpression; class NewMemberExpression; class NewExpression; class CallExpression; class ArgumentList; class PostIncrementExpression; class PostDecrementExpression; class DeleteExpression; class VoidExpression; class TypeOfExpression; class PreIncrementExpression; class PreDecrementExpression; class UnaryPlusExpression; class UnaryMinusExpression; class TildeExpression; class NotExpression; class BinaryExpression; class ConditionalExpression; class Expression; // ### rename class Block; class StatementList; class VariableStatement; class VariableDeclarationList; class VariableDeclaration; class EmptyStatement; class ExpressionStatement; class IfStatement; class DoWhileStatement; class WhileStatement; class ForStatement; class LocalForStatement; class ForEachStatement; class LocalForEachStatement; class ContinueStatement; class BreakStatement; class ReturnStatement; class WithStatement; class SwitchStatement; class CaseBlock; class CaseClauses; class CaseClause; class DefaultClause; class LabelledStatement; class ThrowStatement; class TryStatement; class Catch; class Finally; class FunctionDeclaration; class FunctionExpression; class FormalParameterList; class FunctionBody; class Program; class SourceElements; class SourceElement; class FunctionSourceElement; class StatementSourceElement; class DebuggerStatement; class NestedExpression; // ui elements class UiProgram; class UiImportList; class UiImport; class UiPublicMember; class UiObjectDefinition; class UiObjectInitializer; class UiObjectBinding; class UiScriptBinding; class UiSourceElement; class UiArrayBinding; class UiObjectMember; class UiObjectMemberList; class UiArrayMemberList; class UiQualifiedId; } // namespace AST } // namespace QbsQmlJS #endif qbs-src-1.4.5/src/lib/corelib/parser/qmljsastvisitor.cpp000066400000000000000000000032201266132464200233300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "qmljsastvisitor_p.h" namespace QbsQmlJS { namespace AST { Visitor::Visitor() { } Visitor::~Visitor() { } } // namespace AST } // namespace QbsQmlJS qbs-src-1.4.5/src/lib/corelib/parser/qmljsastvisitor_p.h000066400000000000000000000266001266132464200233230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QMLJSASTVISITOR_P_H #define QMLJSASTVISITOR_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include "qmljsastfwd_p.h" #include "qmljsglobal_p.h" namespace QbsQmlJS { namespace AST { class QML_PARSER_EXPORT Visitor { public: Visitor(); virtual ~Visitor(); virtual bool preVisit(Node *) { return true; } virtual void postVisit(Node *) {} // Ui virtual bool visit(UiProgram *) { return true; } virtual bool visit(UiImportList *) { return true; } virtual bool visit(UiImport *) { return true; } virtual bool visit(UiPublicMember *) { return true; } virtual bool visit(UiSourceElement *) { return true; } virtual bool visit(UiObjectDefinition *) { return true; } virtual bool visit(UiObjectInitializer *) { return true; } virtual bool visit(UiObjectBinding *) { return true; } virtual bool visit(UiScriptBinding *) { return true; } virtual bool visit(UiArrayBinding *) { return true; } virtual bool visit(UiObjectMemberList *) { return true; } virtual bool visit(UiArrayMemberList *) { return true; } virtual bool visit(UiQualifiedId *) { return true; } virtual void endVisit(UiProgram *) {} virtual void endVisit(UiImportList *) {} virtual void endVisit(UiImport *) {} virtual void endVisit(UiPublicMember *) {} virtual void endVisit(UiSourceElement *) {} virtual void endVisit(UiObjectDefinition *) {} virtual void endVisit(UiObjectInitializer *) {} virtual void endVisit(UiObjectBinding *) {} virtual void endVisit(UiScriptBinding *) {} virtual void endVisit(UiArrayBinding *) {} virtual void endVisit(UiObjectMemberList *) {} virtual void endVisit(UiArrayMemberList *) {} virtual void endVisit(UiQualifiedId *) {} // QbsQmlJS virtual bool visit(ThisExpression *) { return true; } virtual void endVisit(ThisExpression *) {} virtual bool visit(IdentifierExpression *) { return true; } virtual void endVisit(IdentifierExpression *) {} virtual bool visit(NullExpression *) { return true; } virtual void endVisit(NullExpression *) {} virtual bool visit(TrueLiteral *) { return true; } virtual void endVisit(TrueLiteral *) {} virtual bool visit(FalseLiteral *) { return true; } virtual void endVisit(FalseLiteral *) {} virtual bool visit(StringLiteral *) { return true; } virtual void endVisit(StringLiteral *) {} virtual bool visit(NumericLiteral *) { return true; } virtual void endVisit(NumericLiteral *) {} virtual bool visit(RegExpLiteral *) { return true; } virtual void endVisit(RegExpLiteral *) {} virtual bool visit(ArrayLiteral *) { return true; } virtual void endVisit(ArrayLiteral *) {} virtual bool visit(ObjectLiteral *) { return true; } virtual void endVisit(ObjectLiteral *) {} virtual bool visit(ElementList *) { return true; } virtual void endVisit(ElementList *) {} virtual bool visit(Elision *) { return true; } virtual void endVisit(Elision *) {} virtual bool visit(PropertyNameAndValueList *) { return true; } virtual void endVisit(PropertyNameAndValueList *) {} virtual bool visit(NestedExpression *) { return true; } virtual void endVisit(NestedExpression *) {} virtual bool visit(IdentifierPropertyName *) { return true; } virtual void endVisit(IdentifierPropertyName *) {} virtual bool visit(StringLiteralPropertyName *) { return true; } virtual void endVisit(StringLiteralPropertyName *) {} virtual bool visit(NumericLiteralPropertyName *) { return true; } virtual void endVisit(NumericLiteralPropertyName *) {} virtual bool visit(ArrayMemberExpression *) { return true; } virtual void endVisit(ArrayMemberExpression *) {} virtual bool visit(FieldMemberExpression *) { return true; } virtual void endVisit(FieldMemberExpression *) {} virtual bool visit(NewMemberExpression *) { return true; } virtual void endVisit(NewMemberExpression *) {} virtual bool visit(NewExpression *) { return true; } virtual void endVisit(NewExpression *) {} virtual bool visit(CallExpression *) { return true; } virtual void endVisit(CallExpression *) {} virtual bool visit(ArgumentList *) { return true; } virtual void endVisit(ArgumentList *) {} virtual bool visit(PostIncrementExpression *) { return true; } virtual void endVisit(PostIncrementExpression *) {} virtual bool visit(PostDecrementExpression *) { return true; } virtual void endVisit(PostDecrementExpression *) {} virtual bool visit(DeleteExpression *) { return true; } virtual void endVisit(DeleteExpression *) {} virtual bool visit(VoidExpression *) { return true; } virtual void endVisit(VoidExpression *) {} virtual bool visit(TypeOfExpression *) { return true; } virtual void endVisit(TypeOfExpression *) {} virtual bool visit(PreIncrementExpression *) { return true; } virtual void endVisit(PreIncrementExpression *) {} virtual bool visit(PreDecrementExpression *) { return true; } virtual void endVisit(PreDecrementExpression *) {} virtual bool visit(UnaryPlusExpression *) { return true; } virtual void endVisit(UnaryPlusExpression *) {} virtual bool visit(UnaryMinusExpression *) { return true; } virtual void endVisit(UnaryMinusExpression *) {} virtual bool visit(TildeExpression *) { return true; } virtual void endVisit(TildeExpression *) {} virtual bool visit(NotExpression *) { return true; } virtual void endVisit(NotExpression *) {} virtual bool visit(BinaryExpression *) { return true; } virtual void endVisit(BinaryExpression *) {} virtual bool visit(ConditionalExpression *) { return true; } virtual void endVisit(ConditionalExpression *) {} virtual bool visit(Expression *) { return true; } virtual void endVisit(Expression *) {} virtual bool visit(Block *) { return true; } virtual void endVisit(Block *) {} virtual bool visit(StatementList *) { return true; } virtual void endVisit(StatementList *) {} virtual bool visit(VariableStatement *) { return true; } virtual void endVisit(VariableStatement *) {} virtual bool visit(VariableDeclarationList *) { return true; } virtual void endVisit(VariableDeclarationList *) {} virtual bool visit(VariableDeclaration *) { return true; } virtual void endVisit(VariableDeclaration *) {} virtual bool visit(EmptyStatement *) { return true; } virtual void endVisit(EmptyStatement *) {} virtual bool visit(ExpressionStatement *) { return true; } virtual void endVisit(ExpressionStatement *) {} virtual bool visit(IfStatement *) { return true; } virtual void endVisit(IfStatement *) {} virtual bool visit(DoWhileStatement *) { return true; } virtual void endVisit(DoWhileStatement *) {} virtual bool visit(WhileStatement *) { return true; } virtual void endVisit(WhileStatement *) {} virtual bool visit(ForStatement *) { return true; } virtual void endVisit(ForStatement *) {} virtual bool visit(LocalForStatement *) { return true; } virtual void endVisit(LocalForStatement *) {} virtual bool visit(ForEachStatement *) { return true; } virtual void endVisit(ForEachStatement *) {} virtual bool visit(LocalForEachStatement *) { return true; } virtual void endVisit(LocalForEachStatement *) {} virtual bool visit(ContinueStatement *) { return true; } virtual void endVisit(ContinueStatement *) {} virtual bool visit(BreakStatement *) { return true; } virtual void endVisit(BreakStatement *) {} virtual bool visit(ReturnStatement *) { return true; } virtual void endVisit(ReturnStatement *) {} virtual bool visit(WithStatement *) { return true; } virtual void endVisit(WithStatement *) {} virtual bool visit(SwitchStatement *) { return true; } virtual void endVisit(SwitchStatement *) {} virtual bool visit(CaseBlock *) { return true; } virtual void endVisit(CaseBlock *) {} virtual bool visit(CaseClauses *) { return true; } virtual void endVisit(CaseClauses *) {} virtual bool visit(CaseClause *) { return true; } virtual void endVisit(CaseClause *) {} virtual bool visit(DefaultClause *) { return true; } virtual void endVisit(DefaultClause *) {} virtual bool visit(LabelledStatement *) { return true; } virtual void endVisit(LabelledStatement *) {} virtual bool visit(ThrowStatement *) { return true; } virtual void endVisit(ThrowStatement *) {} virtual bool visit(TryStatement *) { return true; } virtual void endVisit(TryStatement *) {} virtual bool visit(Catch *) { return true; } virtual void endVisit(Catch *) {} virtual bool visit(Finally *) { return true; } virtual void endVisit(Finally *) {} virtual bool visit(FunctionDeclaration *) { return true; } virtual void endVisit(FunctionDeclaration *) {} virtual bool visit(FunctionExpression *) { return true; } virtual void endVisit(FunctionExpression *) {} virtual bool visit(FormalParameterList *) { return true; } virtual void endVisit(FormalParameterList *) {} virtual bool visit(FunctionBody *) { return true; } virtual void endVisit(FunctionBody *) {} virtual bool visit(Program *) { return true; } virtual void endVisit(Program *) {} virtual bool visit(SourceElements *) { return true; } virtual void endVisit(SourceElements *) {} virtual bool visit(FunctionSourceElement *) { return true; } virtual void endVisit(FunctionSourceElement *) {} virtual bool visit(StatementSourceElement *) { return true; } virtual void endVisit(StatementSourceElement *) {} virtual bool visit(DebuggerStatement *) { return true; } virtual void endVisit(DebuggerStatement *) {} }; } // namespace AST } // namespace QbsQmlJS #endif // QMLJSASTVISITOR_P_H qbs-src-1.4.5/src/lib/corelib/parser/qmljsengine_p.cpp000066400000000000000000000102151266132464200227070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "qmljsengine_p.h" #include "qmljsglobal_p.h" #include #include #include namespace QbsQmlJS { static int toDigit(char c) { if ((c >= '0') && (c <= '9')) return c - '0'; else if ((c >= 'a') && (c <= 'z')) return 10 + c - 'a'; else if ((c >= 'A') && (c <= 'Z')) return 10 + c - 'A'; return -1; } double integerFromString(const char *buf, int size, int radix) { if (size == 0) return qSNaN(); double sign = 1.0; int i = 0; if (buf[0] == '+') { ++i; } else if (buf[0] == '-') { sign = -1.0; ++i; } if (((size-i) >= 2) && (buf[i] == '0')) { if (((buf[i+1] == 'x') || (buf[i+1] == 'X')) && (radix < 34)) { if ((radix != 0) && (radix != 16)) return 0; radix = 16; i += 2; } else { if (radix == 0) { radix = 8; ++i; } } } else if (radix == 0) { radix = 10; } int j = i; for ( ; i < size; ++i) { int d = toDigit(buf[i]); if ((d == -1) || (d >= radix)) break; } double result; if (j == i) { if (!qstrcmp(buf, "Infinity")) result = qInf(); else result = qSNaN(); } else { result = 0; double multiplier = 1; for (--i ; i >= j; --i, multiplier *= radix) result += toDigit(buf[i]) * multiplier; } result *= sign; return result; } double integerFromString(const QString &str, int radix) { QByteArray ba = str.trimmed().toLatin1(); return integerFromString(ba.constData(), ba.size(), radix); } Engine::Engine() : _lexer(0), _directives(0) { } Engine::~Engine() { } void Engine::setCode(const QString &code) { _code = code; } void Engine::addComment(int pos, int len, int line, int col) { if (len > 0) _comments.append(QbsQmlJS::AST::SourceLocation(pos, len, line, col)); } QList Engine::comments() const { return _comments; } Lexer *Engine::lexer() const { return _lexer; } void Engine::setLexer(Lexer *lexer) { _lexer = lexer; } void Engine::setDirectives(Directives *directives) { _directives = directives; } Directives *Engine::directives() const { return _directives; } MemoryPool *Engine::pool() { return &_pool; } QStringRef Engine::newStringRef(const QString &text) { const int pos = _extraCode.length(); _extraCode += text; return _extraCode.midRef(pos, text.length()); } QStringRef Engine::newStringRef(const QChar *chars, int size) { return newStringRef(QString(chars, size)); } } // end of namespace QbsQmlJS qbs-src-1.4.5/src/lib/corelib/parser/qmljsengine_p.h000066400000000000000000000064201266132464200223570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QMLJSENGINE_P_H #define QMLJSENGINE_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include "qmljsglobal_p.h" #include "qmljsastfwd_p.h" #include "qmljsmemorypool_p.h" #include #include namespace QbsQmlJS { class Lexer; class Directives; class MemoryPool; class QML_PARSER_EXPORT DiagnosticMessage { public: enum Kind { Warning, Error }; DiagnosticMessage() : kind(Error) {} DiagnosticMessage(Kind kind, const AST::SourceLocation &loc, const QString &message) : kind(kind), loc(loc), message(message) {} bool isWarning() const { return kind == Warning; } bool isError() const { return kind == Error; } Kind kind; AST::SourceLocation loc; QString message; }; class QML_PARSER_EXPORT Engine { Lexer *_lexer; Directives *_directives; MemoryPool _pool; QList _comments; QString _extraCode; QString _code; public: Engine(); ~Engine(); void setCode(const QString &code); void addComment(int pos, int len, int line, int col); QList comments() const; Lexer *lexer() const; void setLexer(Lexer *lexer); void setDirectives(Directives *directives); Directives *directives() const; MemoryPool *pool(); inline QStringRef midRef(int position, int size) { return _code.midRef(position, size); } QStringRef newStringRef(const QString &s); QStringRef newStringRef(const QChar *chars, int size); }; double integerFromString(const char *buf, int size, int radix); } // end of namespace QbsQmlJS #endif // QMLJSENGINE_P_H qbs-src-1.4.5/src/lib/corelib/parser/qmljsglobal_p.h000066400000000000000000000040611266132464200223510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QMLJSGLOBAL_P_H #define QMLJSGLOBAL_P_H #include #ifdef QT_CREATOR # ifdef QMLJS_BUILD_DIR # define QML_PARSER_EXPORT Q_DECL_EXPORT # elif QML_BUILD_STATIC_LIB # define QML_PARSER_EXPORT # else # define QML_PARSER_EXPORT Q_DECL_IMPORT # endif // QMLJS_BUILD_DIR #else // !QT_CREATOR # if defined(QT_BUILD_QMLDEVTOOLS_LIB) || defined(QT_QMLDEVTOOLS_LIB) // QmlDevTools is a static library # define QML_PARSER_EXPORT # else # define QML_PARSER_EXPORT Q_AUTOTEST_EXPORT # endif #endif // QT_CREATOR #endif // QMLJSGLOBAL_P_H qbs-src-1.4.5/src/lib/corelib/parser/qmljsgrammar.cpp000066400000000000000000001257771266132464200225750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ // This file was generated by qlalr - DO NOT EDIT! #include "qmljsgrammar_p.h" namespace QbsQmlJS { const char *const QmlJSGrammar::spell [] = { "end of file", "&", "&&", "&=", "break", "case", "catch", ":", ",", "continue", "default", "delete", "/", "/=", "do", ".", "else", "=", "==", "===", "finally", "for", "function", ">=", ">", ">>", ">>=", ">>>", ">>>=", "identifier", "if", "in", "instanceof", "{", "[", "<=", "(", "<", "<<", "<<=", "-", "-=", "--", "new", "!", "!=", "!==", "numeric literal", "|", "|=", "||", "+", "+=", "++", "?", "}", "]", "%", "%=", "return", ")", ";", 0, "*", "*=", "string literal", "property", "signal", "readonly", "switch", "this", "throw", "~", "try", "typeof", "var", "void", "while", "with", "^", "^=", "null", "true", "false", "const", "debugger", "reserved word", "multiline string literal", "comment", "public", "import", "as", "on", 0, 0, 0, 0, 0, 0, 0, 0, 0}; const short QmlJSGrammar::lhs [] = { 102, 102, 102, 102, 102, 102, 103, 109, 109, 112, 112, 114, 113, 113, 113, 113, 113, 113, 113, 113, 116, 111, 110, 119, 119, 120, 120, 121, 121, 118, 107, 107, 107, 107, 123, 123, 123, 123, 123, 123, 123, 107, 131, 131, 131, 132, 132, 133, 133, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 117, 117, 117, 117, 117, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 122, 138, 138, 138, 138, 137, 137, 140, 140, 142, 142, 142, 142, 142, 142, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 144, 144, 115, 115, 115, 115, 115, 147, 147, 148, 148, 148, 148, 146, 146, 149, 149, 150, 150, 151, 151, 151, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 153, 153, 153, 153, 154, 154, 154, 155, 155, 155, 155, 156, 156, 156, 156, 156, 156, 156, 157, 157, 157, 157, 157, 157, 158, 158, 158, 158, 158, 159, 159, 159, 159, 159, 160, 160, 161, 161, 162, 162, 163, 163, 164, 164, 165, 165, 166, 166, 167, 167, 168, 168, 169, 169, 170, 170, 171, 171, 141, 141, 172, 172, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 105, 105, 174, 174, 175, 175, 176, 176, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 124, 185, 185, 184, 184, 135, 135, 186, 186, 187, 187, 189, 189, 188, 190, 193, 191, 191, 194, 192, 192, 125, 126, 126, 127, 127, 177, 177, 177, 177, 177, 177, 177, 178, 178, 178, 178, 179, 179, 179, 179, 180, 180, 128, 129, 195, 195, 198, 198, 196, 196, 199, 197, 181, 181, 181, 182, 182, 130, 130, 130, 200, 201, 183, 183, 134, 145, 205, 205, 202, 202, 203, 203, 206, 108, 108, 207, 207, 106, 106, 204, 204, 139, 139, 208}; const short QmlJSGrammar::rhs [] = { 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 2, 2, 3, 3, 5, 5, 4, 4, 2, 0, 1, 1, 2, 1, 3, 2, 3, 2, 1, 5, 4, 4, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 0, 1, 2, 4, 6, 6, 3, 3, 7, 7, 4, 4, 5, 5, 5, 6, 6, 10, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 5, 3, 4, 3, 1, 1, 2, 3, 4, 1, 2, 3, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 3, 5, 1, 2, 4, 4, 4, 3, 0, 1, 1, 3, 1, 1, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 3, 3, 1, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 1, 3, 3, 3, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 5, 1, 5, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, 0, 1, 3, 3, 1, 1, 1, 3, 1, 3, 2, 2, 2, 0, 1, 2, 0, 1, 1, 2, 2, 7, 5, 7, 7, 5, 9, 10, 7, 8, 2, 2, 3, 3, 2, 2, 3, 3, 3, 3, 5, 5, 3, 5, 1, 2, 0, 1, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, 2, 2, 2, 8, 8, 1, 3, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 1, 0, 1, 0, 1, 2}; const short QmlJSGrammar::action_default [] = { 0, 0, 22, 0, 0, 0, 22, 0, 175, 242, 206, 214, 210, 154, 226, 202, 3, 139, 73, 155, 218, 222, 143, 172, 153, 158, 138, 192, 179, 0, 80, 81, 76, 345, 67, 347, 0, 0, 0, 0, 78, 0, 0, 74, 77, 71, 0, 0, 68, 70, 69, 79, 72, 0, 75, 0, 0, 168, 0, 0, 155, 174, 157, 156, 0, 0, 0, 170, 171, 169, 173, 0, 203, 0, 0, 0, 0, 193, 0, 0, 0, 0, 0, 0, 183, 0, 0, 0, 177, 178, 176, 181, 185, 184, 182, 180, 195, 194, 196, 0, 211, 0, 207, 0, 0, 149, 136, 148, 137, 105, 106, 107, 132, 108, 133, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 134, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 135, 0, 0, 147, 243, 150, 0, 151, 0, 152, 146, 0, 239, 232, 230, 237, 238, 236, 235, 241, 234, 233, 231, 240, 227, 0, 215, 0, 0, 219, 0, 0, 223, 0, 0, 149, 141, 0, 140, 0, 145, 159, 0, 346, 334, 335, 0, 332, 0, 333, 0, 336, 250, 257, 256, 264, 252, 0, 253, 337, 0, 344, 254, 255, 260, 258, 341, 338, 343, 261, 0, 272, 0, 0, 0, 0, 345, 67, 0, 347, 68, 244, 286, 69, 0, 0, 0, 273, 0, 0, 262, 263, 0, 251, 259, 287, 288, 331, 342, 0, 302, 303, 304, 305, 0, 298, 299, 300, 301, 328, 329, 0, 0, 0, 0, 0, 291, 292, 248, 246, 208, 216, 212, 228, 204, 249, 0, 155, 220, 224, 197, 186, 0, 0, 205, 0, 0, 0, 0, 198, 0, 0, 0, 0, 0, 190, 188, 191, 189, 187, 200, 199, 201, 0, 213, 0, 209, 0, 247, 155, 0, 229, 244, 245, 0, 244, 0, 0, 294, 0, 0, 0, 296, 0, 217, 0, 0, 221, 0, 0, 225, 284, 0, 276, 285, 279, 0, 283, 0, 244, 277, 0, 244, 0, 0, 295, 0, 0, 0, 297, 346, 334, 0, 0, 336, 0, 330, 0, 320, 0, 0, 0, 290, 0, 289, 0, 348, 0, 104, 266, 269, 0, 105, 272, 108, 133, 110, 111, 76, 115, 116, 67, 117, 120, 74, 77, 68, 244, 69, 79, 123, 72, 125, 75, 127, 128, 273, 130, 131, 135, 0, 97, 0, 0, 99, 103, 101, 88, 100, 102, 0, 98, 87, 267, 265, 143, 144, 149, 0, 142, 0, 319, 0, 306, 307, 0, 318, 0, 0, 0, 309, 314, 312, 315, 0, 0, 313, 314, 0, 310, 0, 311, 268, 317, 0, 268, 316, 0, 321, 322, 0, 268, 323, 324, 0, 0, 325, 0, 0, 0, 326, 327, 161, 160, 0, 0, 0, 293, 0, 0, 0, 308, 281, 274, 0, 282, 278, 0, 280, 270, 0, 271, 275, 91, 0, 0, 95, 82, 0, 84, 93, 0, 85, 94, 96, 86, 92, 83, 0, 89, 165, 163, 167, 164, 162, 166, 339, 6, 340, 4, 2, 65, 90, 0, 0, 68, 70, 69, 31, 5, 0, 66, 0, 45, 44, 43, 0, 0, 58, 0, 59, 35, 36, 37, 38, 40, 41, 62, 39, 0, 45, 0, 0, 0, 0, 0, 54, 0, 55, 0, 0, 26, 0, 0, 63, 27, 0, 30, 28, 24, 0, 29, 25, 0, 56, 0, 57, 143, 0, 60, 64, 0, 0, 0, 0, 61, 0, 52, 46, 53, 47, 0, 0, 0, 0, 49, 0, 50, 51, 48, 0, 0, 143, 268, 0, 0, 42, 105, 272, 108, 133, 110, 111, 76, 115, 116, 67, 117, 120, 74, 77, 68, 244, 69, 79, 123, 72, 125, 75, 127, 128, 273, 130, 131, 135, 0, 32, 33, 0, 34, 8, 0, 10, 0, 9, 0, 1, 21, 12, 0, 13, 0, 14, 0, 19, 20, 0, 15, 16, 0, 17, 18, 11, 23, 7, 349}; const short QmlJSGrammar::goto_default [] = { 7, 625, 207, 196, 205, 508, 496, 624, 643, 495, 623, 621, 626, 22, 622, 18, 507, 549, 539, 546, 541, 526, 191, 195, 197, 201, 233, 208, 230, 530, 570, 569, 200, 232, 26, 474, 473, 356, 355, 9, 354, 357, 107, 17, 145, 24, 13, 144, 19, 25, 57, 23, 8, 28, 27, 269, 15, 263, 10, 259, 12, 261, 11, 260, 20, 267, 21, 268, 14, 262, 258, 299, 411, 264, 265, 202, 193, 192, 204, 203, 229, 194, 360, 359, 231, 463, 462, 321, 322, 465, 324, 464, 323, 419, 423, 426, 422, 421, 441, 442, 185, 199, 181, 184, 198, 206, 0}; const short QmlJSGrammar::action_index [] = { 404, 1275, 2411, 2411, 2509, 1000, 68, 92, 90, -102, 88, 62, 60, 256, -102, 298, 86, -102, -102, 638, 83, 134, 172, 219, -102, -102, -102, 454, 194, 1275, -102, -102, -102, 381, -102, 2215, 1555, 1275, 1275, 1275, -102, 790, 1275, -102, -102, -102, 1275, 1275, -102, -102, -102, -102, -102, 1275, -102, 1275, 1275, -102, 1275, 1275, 102, 217, -102, -102, 1275, 1275, 1275, -102, -102, -102, 204, 1275, 304, 1275, 1275, 1275, 1275, 539, 1275, 1275, 1275, 1275, 1275, 1275, 308, 1275, 1275, 1275, 103, 131, 135, 308, 210, 225, 216, 308, 444, 390, 434, 1275, 82, 1275, 100, 2117, 1275, 1275, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, 139, 1275, -102, -102, 91, 10, -102, 1275, -102, -102, 1275, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, 1275, 26, 1275, 1275, 69, 66, 1275, -102, 2117, 1275, 1275, -102, 97, -102, 44, -102, -102, 67, -102, 297, 78, 24, -102, 291, -102, 36, 2411, -102, -102, -102, -102, -102, 234, -102, -102, 12, -102, -102, -102, -102, -102, -102, 2411, -102, -102, 464, -102, 461, 115, 2509, 42, 381, 58, 46, 2705, 70, 1275, -102, 74, 57, 1275, 65, -102, 59, 61, -102, -102, 367, -102, -102, -102, -102, -102, -102, 106, -102, -102, -102, -102, 87, -102, -102, -102, -102, -102, -102, 56, 55, 1275, 99, 84, -102, -102, 1461, -102, 75, 48, 52, -102, 306, 72, 53, 579, 77, 110, 370, 230, 381, 1275, 286, 1275, 1275, 1275, 1275, 380, 1275, 1275, 1275, 1275, 1275, 184, 169, 166, 190, 198, 460, 363, 353, 1275, 50, 1275, 63, 1275, -102, 638, 1275, -102, 1275, 64, 39, 1275, 30, 2509, -102, 1275, 173, 2509, -102, 1275, 79, 1275, 1275, 81, 80, 1275, -102, 71, 149, 32, -102, -102, 1275, -102, 381, 1275, -102, 73, 1275, 76, 2509, -102, 1275, 142, 2509, -102, -16, 381, -42, -12, 2411, -39, -102, 2509, -102, 1275, 154, 2509, 14, 2509, -102, 20, 16, -32, -102, -102, 2509, -51, 519, -4, 511, 136, 1275, 2509, -2, -35, 395, -1, -27, 908, 4, 6, -102, 1370, -102, 0, -36, 27, 1275, 47, 22, 1275, 45, 1275, 21, 17, 1275, -102, 2313, 144, -102, -102, -102, -102, -102, -102, 1275, -102, -102, -102, -102, 274, -102, 1275, -21, -102, 2509, -102, 138, -102, -102, 2509, -102, 1275, 132, 5, -102, 40, -102, 41, 101, 1275, -102, 38, 34, -102, -38, -102, 2509, -102, 105, 2509, -102, 245, -102, -102, 96, 2509, 11, -102, -7, -11, -102, 352, 8, 18, -102, -102, -102, -102, 1275, 129, 2509, -102, 1275, 130, 2509, -102, 49, -102, 226, -102, -102, 1275, -102, -102, 362, -102, -102, -102, 107, 1837, -102, -102, 1649, -102, -102, 1743, -102, -102, -102, -102, -102, -102, 114, -102, -102, -102, -102, -102, -102, -102, -102, -102, 2411, -102, -102, -102, 94, 9, 818, 189, -10, 31, -102, -102, 223, -102, 191, -102, -102, -102, 300, 178, -102, 1928, -102, -102, -102, -102, -102, -102, -102, -102, -102, 257, -25, 381, 195, -22, 305, 240, -102, -6, -102, 818, 127, -102, -18, 818, -102, -102, 1184, -102, -102, -102, 1092, -102, -102, 237, -102, 1928, -102, 294, -8, -102, -102, 176, 381, 19, 1928, -102, 165, -102, 174, -102, 2, -52, 381, 183, 381, -102, 117, -102, -102, -102, 2019, 880, 285, 2607, 1555, 3, -102, 522, 35, 453, 108, 1275, 2509, 51, 23, 475, 54, -17, 700, 7, 43, -102, 1370, -102, 28, -3, 33, 1275, 37, 15, 1275, 25, 1275, 1, 13, 124, -102, -102, 29, -102, -102, 728, -102, 250, -43, 627, -102, -102, 231, 372, -102, 222, -102, 111, -102, -102, 381, -102, -102, 104, -102, -102, -102, -102, -102, -102, -107, 9, -103, 2, 5, 266, 1, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -39, -107, -107, -107, -107, -107, -107, -107, -107, -107, 86, -107, -107, -107, 8, -107, -107, -22, 19, 71, 174, -107, 186, 171, -107, -107, -107, 184, 178, -107, -107, -107, -107, -107, 144, -107, 124, 150, -107, 165, 161, -107, -107, -107, -107, 156, 160, 157, -107, -107, -107, -107, 147, -107, 142, 135, 179, 166, -107, 177, 170, 117, 72, 134, 92, -107, 75, 94, 66, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, 181, -107, 106, -107, 143, 78, 55, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -5, -107, -107, -107, -107, -107, 54, -107, -107, 51, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, 114, -107, 113, 38, -107, -107, 41, -107, 231, 63, 112, -107, -107, -107, -107, -107, -107, -107, -107, 30, -107, -107, -107, 52, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, 36, -107, -107, 45, -107, 42, -107, 40, -107, 80, -107, -107, 77, -107, 88, -107, -107, -107, 83, 74, -107, -107, -107, -107, -107, -10, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, 23, -107, -107, -107, -107, 100, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, 4, 223, -107, 230, 236, 222, 205, -107, 127, 125, 115, 96, 102, -107, -107, -107, -107, -107, -107, -107, -107, 234, -107, 215, -107, 199, -107, -107, 197, -107, 190, -107, -107, 163, -107, 90, -107, 0, -107, -1, -107, 203, -107, 189, 211, -107, -107, 195, -107, -107, -107, -107, -107, -107, 191, -107, 98, 119, -107, -107, 95, -107, 81, -107, 79, -107, 82, -107, -107, 101, -107, -107, -16, -107, -107, 53, -107, 46, -107, 57, -107, 59, -107, -107, -107, -107, -107, -107, 35, -107, 33, -107, 39, -107, 89, 67, -107, -107, 58, -107, -107, 84, -107, -107, -107, 73, -107, -107, -107, -107, 65, -107, 43, 93, -107, 109, -107, -107, 49, -107, 47, -107, -107, -107, -107, -107, -107, -107, 50, -107, -107, -107, -107, -107, -107, 108, -107, -107, 61, -107, -107, -107, -107, 62, -107, 68, -107, -107, -107, -107, -107, -23, -107, 69, -107, -19, -107, -107, -107, -107, 97, -107, -107, 99, -107, -107, -107, -107, -107, 60, -61, -107, -107, 34, -107, 37, -107, 29, -107, -107, -107, -107, 32, -107, 76, -107, 44, -107, 56, -107, -107, -107, -107, -107, -107, 31, -107, -107, 116, -107, -107, -107, -107, -6, -107, -107, 70, -107, -107, 64, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, 193, -107, -107, -107, -107, -107, 7, -107, -107, -107, -107, -107, -107, -107, -20, -107, -107, -107, -7, -107, -107, 290, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -107, -2, -25, -107, -15, -107, -107, -107, -107, 172, -107, -107, -107, 287, -107, -107, 288, -107, -107, -107, 291, -107, -107, -107, -107, 336, -107, -107, 20, -107, -107, 15, 3, -107, 304, -107, -107, -107, 24, -107, -107, -107, 28, 21, 26, -107, -107, -107, -107, -107, 320, 104, -107, 13, 381, -3, -107, 6, -107, 10, -107, 167, 22, -107, -107, 12, -107, -107, 87, -107, -107, -107, 25, -107, -107, -107, -107, 11, -107, 14, 85, -107, 121, -107, -107, -107, -107, -107, 27, -107, -107, 17, -107, -107, 18, 91, -107, -107, -107, 16, -107, -107, -107, -107, -107, -107, -4, -107, -107, -107, -107, -107, -107, -107, -107, -107}; const short QmlJSGrammar::action_info [] = { 416, 257, 533, -132, 403, -113, 346, -102, 575, 348, 572, -121, 531, -103, -121, 545, 345, 430, 342, 348, 340, 343, 440, 401, 391, 545, 563, 389, 538, 446, 352, 444, -129, 416, -124, -102, 545, 453, 420, 408, -124, 431, -132, 424, -126, 424, 424, 620, 440, 457, -103, 440, -129, 457, -126, 440, 560, 453, -113, 257, 565, 346, 545, 335, 272, 346, 466, 236, 448, 190, 149, 164, 141, 170, 99, 511, 272, 409, 257, 312, 296, 414, 348, 312, 189, 164, 187, 318, 325, 71, 306, 252, 644, 416, 141, 453, 292, 457, 440, 147, 304, 71, 443, 183, 179, 141, 0, 141, 0, 172, 99, 427, 434, 141, 301, 477, 444, 0, 0, 0, 0, 0, 141, 0, 0, 0, 0, 292, 173, 294, 58, 294, 542, 251, 331, 542, 333, 141, 141, 101, 141, 59, 0, 58, 62, 256, 255, 141, 247, 246, 141, 399, 0, 177, 59, 63, 428, 327, 620, 254, 314, 101, 141, 478, 315, 640, 639, 242, 241, 249, 248, 58, 634, 633, 488, 58, 249, 248, 577, 576, 615, 141, 59, 543, 166, 518, 59, 172, 167, 455, 459, 85, 418, 86, 85, 142, 86, 249, 248, 413, 412, 567, 337, 512, 87, 512, 173, 87, 174, 85, 328, 86, 512, 0, 350, 85, 64, 86, 529, 85, 512, 86, 87, 85, 512, 86, 568, 566, 87, 64, 579, 64, 87, 310, 469, 85, 87, 86, 0, 519, 517, 85, 141, 86, 554, 0, 172, 536, 87, 514, 85, 514, 86, 141, 87, 85, 545, 86, 514, 0, 513, 65, 513, 87, 514, 173, 514, 66, 87, 513, 514, 103, 172, 0, 65, 513, 65, 513, 0, 0, 66, 513, 66, 637, 636, 0, 0, 470, 468, 172, 104, 173, 105, 406, 0, 235, 234, 630, 555, 553, 172, 537, 535, 0, 274, 275, 438, 437, 173, 172, 406, 631, 629, 635, 0, 580, 73, 74, -90, 173, 34, 174, 73, 74, 274, 275, 34, -90, 173, 34, 174, 276, 277, 85, 34, 86, 0, 0, 0, 0, 0, 628, 0, 75, 76, 0, 87, 0, 0, 75, 76, 276, 277, 0, 0, 0, 0, 48, 50, 49, 0, 0, 0, 48, 50, 49, 48, 50, 49, 0, 0, 48, 50, 49, 0, 0, 279, 280, 0, 0, 0, 34, 0, 45, 0, 281, 279, 280, 282, 45, 283, 34, 45, 279, 280, 281, 34, 45, 282, 0, 283, 34, 281, 279, 280, 282, 0, 283, 0, 0, 34, 0, 281, 78, 79, 282, 0, 283, 48, 50, 49, 80, 81, 0, 34, 82, 0, 83, 48, 50, 49, -345, 0, 48, 50, 49, 0, 0, 48, 50, 49, 0, 0, 0, 45, 0, 0, 48, 50, 49, 0, 0, 0, 0, 45, 0, 0, 78, 79, 45, 0, 48, 50, 49, 45, 80, 81, 78, 79, 82, 0, 83, 0, 45, 0, 80, 81, 78, 79, 82, 0, 83, 34, 279, 280, 80, 81, 45, 0, 82, 34, 83, 281, 34, 0, 282, 0, 283, 6, 5, 4, 1, 3, 2, 34, 0, 0, 0, 0, 0, 0, -345, 0, 0, 245, 244, 0, 0, 0, 48, 50, 49, 245, 244, 0, 240, 239, 48, 50, 49, 48, 50, 49, 0, 0, 0, 0, 0, 0, 0, 34, 48, 50, 49, 0, 45, 0, 0, 34, 0, 0, 34, 0, 45, 0, 0, 45, 0, 0, 0, 0, 0, 78, 79, 0, 0, 0, 45, 0, 0, 80, 81, 245, 244, 82, 0, 83, 48, 50, 49, 240, 239, 151, 240, 239, 48, 50, 49, 48, 50, 49, 0, 152, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 45, 0, 154, 0, 155, 0, 0, 308, 45, 0, 0, 45, 0, 0, 0, 156, 0, 157, 62, 0, 0, 0, 0, 0, 0, 158, 0, 0, 159, 63, 0, 0, 0, 0, 160, 0, 30, 31, 151, 0, 161, 0, 0, 0, 0, 0, 33, 0, 152, 0, 0, 0, 153, 34, 0, 0, 162, 35, 36, 0, 37, 154, 0, 155, 0, 0, 0, 503, 0, 0, 0, 44, 0, 0, 156, 0, 157, 62, 0, 0, 0, 0, 0, 0, 158, 0, 0, 159, 63, 51, 48, 50, 49, 160, 52, 0, 0, 0, 0, 161, 0, 0, 0, 0, 0, 43, 54, 32, 0, 30, 31, 40, 0, 0, 0, 162, 45, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 30, 31, 0, 41, 0, 0, 0, 44, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 51, 48, 50, 49, 0, 52, 503, 0, 0, 0, 44, 0, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 51, 48, 50, 49, 0, 52, 0, 0, 0, 30, 31, 0, 0, 0, 0, 0, 43, 54, 32, 33, 0, 0, 40, 0, 0, 0, 34, 45, 0, 0, 35, 36, 0, 37, 0, 0, 0, 30, 31, 0, 41, 0, 0, 0, 44, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 51, 48, 50, 49, 0, 52, 503, 0, 0, 0, 44, 0, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 51, 48, 50, 49, 0, 52, 0, 0, 0, 30, 31, 0, 0, 0, 0, 0, 43, 54, 32, 33, 0, 0, 40, 0, 0, 0, 34, 45, 0, 0, 35, 36, 0, 37, 0, 0, 0, 30, 31, 0, 503, 0, 0, 0, 44, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 51, 48, 50, 49, 0, 52, 41, 0, 0, 0, 44, 0, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 51, 48, 50, 49, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 502, 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 215, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 0, 0, 0, 503, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 504, 506, 505, 0, 52, 0, 0, 0, 0, 226, 0, 0, 0, 0, 0, 43, 54, 32, 210, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 502, 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 215, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 0, 0, 0, 503, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 550, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 504, 506, 505, 0, 52, 0, 0, 0, 0, 226, 0, 0, 0, 0, 0, 43, 54, 32, 210, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 502, 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 215, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 0, 0, 0, 503, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 547, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 504, 506, 505, 0, 52, 0, 0, 0, 0, 226, 0, 0, 0, 0, 0, 43, 54, 32, 210, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, -122, 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, 271, 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 475, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 476, 0, 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 475, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 481, 0, 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 483, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 484, 0, 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 483, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 35, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 486, 0, 0, 0, 0, 0, 0, 0, 0, 51, 48, 50, 49, 0, 52, 0, 53, 0, 55, 0, 56, 0, 0, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 217, 0, 0, 218, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, 0, 0, 0, 221, 0, 0, 0, 51, 48, 50, 49, 223, 52, 0, 53, 225, 55, 0, 56, 0, 228, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 217, 0, 0, 582, 583, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, 0, 0, 0, 221, 0, 0, 0, 51, 48, 50, 49, 223, 52, 0, 53, 225, 55, 0, 56, 0, 228, 0, 0, 43, 54, 32, 0, 0, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 110, 111, 0, 0, 113, 115, 116, 0, 0, 117, 0, 118, 0, 0, 0, 120, 121, 122, 0, 0, 0, 0, 0, 0, 34, 123, 124, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 0, 0, 0, 0, 0, 0, 48, 50, 49, 130, 131, 132, 0, 134, 135, 136, 137, 138, 139, 0, 0, 127, 133, 119, 112, 114, 128, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 110, 111, 0, 0, 113, 115, 116, 0, 0, 117, 0, 118, 0, 0, 0, 120, 121, 122, 0, 0, 0, 0, 0, 0, 393, 123, 124, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 0, 0, 0, 0, 0, 398, 395, 397, 0, 130, 131, 132, 0, 134, 135, 136, 137, 138, 139, 0, 0, 127, 133, 119, 112, 114, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 110, 111, 0, 0, 113, 115, 116, 0, 0, 117, 0, 118, 0, 0, 0, 120, 121, 122, 0, 0, 0, 0, 0, 0, 393, 123, 124, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 394, 0, 0, 0, 0, 0, 0, 0, 396, 0, 0, 0, 129, 0, 0, 0, 0, 0, 398, 395, 397, 0, 130, 131, 132, 0, 134, 135, 136, 137, 138, 139, 0, 0, 127, 133, 119, 112, 114, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 0, 0, 0, 0, 211, 0, 29, 30, 31, 213, 0, 0, 0, 0, 0, 0, 214, 215, 0, 0, 0, 0, 0, 0, 216, 217, 0, 0, 218, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, 0, 220, 0, 221, 0, 0, 0, 51, 219, 222, 49, 223, 52, 224, 53, 225, 55, 226, 56, 227, 228, 0, 0, 43, 54, 32, 210, 212, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 209, 0, 0, 0, 0, 211, 0, 29, 30, 31, 213, 0, 0, 0, 0, 0, 0, 214, 33, 0, 0, 0, 0, 0, 0, 216, 217, 0, 0, 218, 36, 0, 37, 0, 0, 0, 38, 0, 39, 41, 42, 0, 0, 44, 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, 0, 220, 0, 221, 0, 0, 0, 51, 219, 222, 49, 223, 52, 224, 53, 225, 55, 226, 56, 227, 228, 0, 0, 43, 54, 32, 210, 212, 0, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 586, 110, 111, 0, 0, 588, 115, 590, 30, 31, 591, 0, 118, 0, 0, 0, 120, 593, 594, 0, 0, 0, 0, 0, 0, 595, 596, 124, 125, 218, 36, 0, 37, 0, 0, 0, 38, 0, 39, 597, 42, 0, 0, 599, 0, 0, 0, 46, 0, 47, 0, 0, 0, 0, 0, 601, 0, 221, 0, 0, 0, 603, 600, 602, 49, 604, 605, 606, 53, 608, 609, 610, 611, 612, 613, 0, 0, 598, 607, 592, 587, 589, 128, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 361, 110, 111, 0, 0, 363, 115, 365, 30, 31, 366, 0, 118, 0, 0, 0, 120, 368, 369, 0, 0, 0, 0, 0, 0, 370, 371, 124, 125, 218, 36, 0, 37, 0, 0, 0, 38, 0, 39, 372, 42, 0, 0, 374, 0, 0, 0, 46, 0, 47, 0, -268, 0, 0, 0, 376, 0, 221, 0, 0, 0, 378, 375, 377, 49, 379, 380, 381, 53, 383, 384, 385, 386, 387, 388, 0, 0, 373, 382, 367, 362, 364, 128, 40, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 534, 311, 497, 309, 532, 461, 498, 499, 516, 515, 619, 638, 16, 552, 436, 358, 616, 472, 562, 320, 528, 238, 487, 182, 250, 243, 253, 182, 302, 641, 627, 632, 150, 485, 143, 454, 439, 402, 445, 559, 237, 574, 250, 578, 561, 186, 618, 458, 238, 349, 573, 449, 447, 571, 243, 347, 450, 243, 460, 351, 238, 353, 358, 410, 415, 439, 176, 188, 436, 250, 467, 417, 433, 182, 425, 429, 302, 169, 456, 358, 171, 140, 336, 334, 338, 344, 436, 392, 390, 400, 163, 302, 307, 148, 146, 339, 439, 404, 302, 358, 404, 358, 0, 482, 501, 480, 0, 642, 0, 479, 0, 0, 0, 320, 60, 0, 186, 501, 90, 60, 60, 489, 302, 60, 617, 93, 0, 88, 0, 405, 0, 461, 405, 60, 60, 451, 180, 60, 0, 180, 60, 60, 60, 451, 60, 95, 89, 146, 266, 287, 60, 146, 407, 270, 60, 288, 178, 60, 106, 452, 0, 60, 60, 60, 102, 60, 302, 332, 286, 60, 92, 452, 60, 60, 451, 60, 165, 168, 285, 432, 284, 435, 60, 60, 108, 501, 329, 94, 540, 96, 60, 330, 60, 302, 494, 60, 77, 237, 60, 404, 452, 341, 471, 72, 60, 60, 67, 69, 60, 60, 68, 0, 70, 60, 60, 60, 61, 180, 60, 60, 98, 491, 60, 91, 490, 60, 60, 60, 493, 60, 84, 405, 60, 97, 492, 305, 0, 60, 0, 298, 0, 100, 270, 298, 270, 298, 106, 298, 270, 0, 270, 60, 270, 60, 316, 0, 270, 0, 270, 298, 291, 326, 303, 60, 270, 319, 313, 300, 270, 297, 60, 60, 108, 175, 295, 270, 270, 290, 60, 501, 273, 317, 60, 270, 60, 278, 509, 270, 0, 270, 0, 289, 0, 548, 0, 293, 551, 0, 500, 510, 501, 501, 0, 544, 501, 0, 0, 0, 509, 0, 0, 509, 520, 521, 522, 523, 527, 524, 525, 0, 500, 510, 0, 500, 510, 564, 520, 521, 522, 523, 527, 524, 525, 581, 0, 0, 0, 0, 0, 0, 584, 585, 520, 521, 522, 523, 527, 524, 525, 556, 0, 0, 0, 0, 0, 0, 557, 558, 520, 521, 522, 523, 527, 524, 525, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 556, 0, 0, 540, 0, 614, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 472, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; const short QmlJSGrammar::action_check [] = { 36, 36, 24, 7, 55, 7, 7, 7, 60, 36, 8, 7, 37, 7, 7, 33, 55, 55, 60, 36, 36, 33, 33, 55, 8, 33, 7, 7, 34, 36, 16, 20, 7, 36, 7, 7, 33, 36, 33, 60, 7, 7, 7, 5, 7, 5, 5, 90, 33, 36, 7, 33, 7, 36, 7, 33, 66, 36, 7, 36, 29, 7, 33, 31, 1, 7, 17, 55, 60, 33, 60, 2, 8, 7, 48, 66, 1, 7, 36, 2, 8, 7, 36, 2, 60, 2, 8, 7, 17, 1, 60, 36, 0, 36, 8, 36, 48, 36, 33, 8, 61, 1, 6, 36, 60, 8, -1, 8, -1, 15, 48, 10, 7, 8, 61, 8, 20, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, 48, 34, 79, 40, 79, 8, 77, 61, 8, 60, 8, 8, 79, 8, 51, -1, 40, 42, 61, 62, 8, 61, 62, 8, 7, -1, 56, 51, 53, 55, 8, 90, 60, 50, 79, 8, 56, 54, 61, 62, 61, 62, 61, 62, 40, 61, 62, 60, 40, 61, 62, 61, 62, 56, 8, 51, 56, 50, 7, 51, 15, 54, 60, 60, 25, 60, 27, 25, 56, 27, 61, 62, 61, 62, 36, 60, 29, 38, 29, 34, 38, 36, 25, 61, 27, 29, -1, 60, 25, 12, 27, 29, 25, 29, 27, 38, 25, 29, 27, 61, 62, 38, 12, 7, 12, 38, 60, 8, 25, 38, 27, -1, 61, 62, 25, 8, 27, 7, -1, 15, 7, 38, 75, 25, 75, 27, 8, 38, 25, 33, 27, 75, -1, 86, 57, 86, 38, 75, 34, 75, 63, 38, 86, 75, 15, 15, -1, 57, 86, 57, 86, -1, -1, 63, 86, 63, 61, 62, -1, -1, 61, 62, 15, 34, 34, 36, 36, -1, 61, 62, 47, 61, 62, 15, 61, 62, -1, 18, 19, 61, 62, 34, 15, 36, 61, 62, 91, -1, 92, 18, 19, 33, 34, 29, 36, 18, 19, 18, 19, 29, 33, 34, 29, 36, 45, 46, 25, 29, 27, -1, -1, -1, -1, -1, 91, -1, 45, 46, -1, 38, -1, -1, 45, 46, 45, 46, -1, -1, -1, -1, 66, 67, 68, -1, -1, -1, 66, 67, 68, 66, 67, 68, -1, -1, 66, 67, 68, -1, -1, 23, 24, -1, -1, -1, 29, -1, 92, -1, 32, 23, 24, 35, 92, 37, 29, 92, 23, 24, 32, 29, 92, 35, -1, 37, 29, 32, 23, 24, 35, -1, 37, -1, -1, 29, -1, 32, 23, 24, 35, -1, 37, 66, 67, 68, 31, 32, -1, 29, 35, -1, 37, 66, 67, 68, 36, -1, 66, 67, 68, -1, -1, 66, 67, 68, -1, -1, -1, 92, -1, -1, 66, 67, 68, -1, -1, -1, -1, 92, -1, -1, 23, 24, 92, -1, 66, 67, 68, 92, 31, 32, 23, 24, 35, -1, 37, -1, 92, -1, 31, 32, 23, 24, 35, -1, 37, 29, 23, 24, 31, 32, 92, -1, 35, 29, 37, 32, 29, -1, 35, -1, 37, 94, 95, 96, 97, 98, 99, 29, -1, -1, -1, -1, -1, -1, 36, -1, -1, 61, 62, -1, -1, -1, 66, 67, 68, 61, 62, -1, 61, 62, 66, 67, 68, 66, 67, 68, -1, -1, -1, -1, -1, -1, -1, 29, 66, 67, 68, -1, 92, -1, -1, 29, -1, -1, 29, -1, 92, -1, -1, 92, -1, -1, -1, -1, -1, 23, 24, -1, -1, -1, 92, -1, -1, 31, 32, 61, 62, 35, -1, 37, 66, 67, 68, 61, 62, 3, 61, 62, 66, 67, 68, 66, 67, 68, -1, 13, -1, -1, -1, 17, -1, -1, -1, -1, -1, -1, 92, -1, 26, -1, 28, -1, -1, 31, 92, -1, -1, 92, -1, -1, -1, 39, -1, 41, 42, -1, -1, -1, -1, -1, -1, 49, -1, -1, 52, 53, -1, -1, -1, -1, 58, -1, 12, 13, 3, -1, 64, -1, -1, -1, -1, -1, 22, -1, 13, -1, -1, -1, 17, 29, -1, -1, 80, 33, 34, -1, 36, 26, -1, 28, -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, 39, -1, 41, 42, -1, -1, -1, -1, -1, -1, 49, -1, -1, 52, 53, 65, 66, 67, 68, 58, 70, -1, -1, -1, -1, 64, -1, -1, -1, -1, -1, 81, 82, 83, -1, 12, 13, 87, -1, -1, -1, 80, 92, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 12, 13, -1, 43, -1, -1, -1, 47, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, 65, 66, 67, 68, -1, 70, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, 65, 66, 67, 68, -1, 70, -1, -1, -1, 12, 13, -1, -1, -1, -1, -1, 81, 82, 83, 22, -1, -1, 87, -1, -1, -1, 29, 92, -1, -1, 33, 34, -1, 36, -1, -1, -1, 12, 13, -1, 43, -1, -1, -1, 47, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, 65, 66, 67, 68, -1, 70, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, 65, 66, 67, 68, -1, 70, -1, -1, -1, 12, 13, -1, -1, -1, -1, -1, 81, 82, 83, 22, -1, -1, 87, -1, -1, -1, 29, 92, -1, -1, 33, 34, -1, 36, -1, -1, -1, 12, 13, -1, 43, -1, -1, -1, 47, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, 65, 66, 67, 68, -1, 70, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, 65, 66, 67, 68, -1, 70, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, -1, -1, -1, 75, -1, -1, -1, -1, -1, 81, 82, 83, 84, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, 55, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, -1, -1, -1, 75, -1, -1, -1, -1, -1, 81, 82, 83, 84, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, 55, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, -1, -1, -1, 75, -1, -1, -1, -1, -1, 81, 82, 83, 84, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, 75, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, -1, 72, 73, 74, -1, 76, -1, 78, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, -1, -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, -1, 72, 73, 74, -1, 76, -1, 78, -1, -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 59, -1, -1, -1, -1, -1, -1, 66, 67, 68, 69, 70, 71, -1, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, -1, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 59, -1, -1, -1, -1, -1, 65, 66, 67, -1, 69, 70, 71, -1, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, -1, 55, -1, -1, -1, 59, -1, -1, -1, -1, -1, 65, 66, 67, -1, 69, 70, 71, -1, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, 9, -1, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, 9, -1, 11, 12, 13, 14, -1, -1, -1, -1, -1, -1, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, -1, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, 12, 13, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, 10, 11, 12, 13, 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, 30, 31, 32, 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, 55, -1, -1, -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, 86, 87, -1, -1, -1, -1, 92, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, 2, 105, 3, 29, 15, 4, 2, 15, 29, 9, 15, 3, 15, 3, 2, 19, 39, 15, 15, 13, 15, 3, 15, 2, 15, 3, 15, 3, 11, 13, 15, 71, 39, 39, 3, 22, 2, 99, 19, 4, 15, 2, 15, 29, 15, 19, 3, 15, 3, 29, 22, 15, 29, 15, 2, 22, 15, 2, 2, 15, 2, 2, 2, 2, 22, 3, 15, 3, 2, 39, 3, 3, 15, 97, 94, 3, 39, 2, 2, 39, 3, 3, 2, 2, 101, 3, 40, 39, 39, 39, 3, 2, 39, 39, 15, 22, 13, 3, 2, 13, 2, -1, 39, 13, 35, -1, 16, -1, 39, -1, -1, -1, 15, 48, -1, 15, 13, 52, 48, 48, 50, 3, 48, 20, 53, -1, 52, -1, 45, -1, 15, 45, 48, 48, 50, 50, 48, -1, 50, 48, 48, 48, 50, 48, 53, 52, 39, 48, 53, 48, 39, 44, 53, 48, 53, 44, 48, 15, 50, -1, 48, 48, 48, 58, 48, 3, 72, 53, 48, 53, 50, 48, 48, 50, 48, 62, 64, 53, 82, 53, 82, 48, 48, 41, 13, 88, 53, 16, 54, 48, 72, 48, 3, 50, 48, 54, 4, 48, 13, 50, 100, 86, 56, 48, 48, 50, 50, 48, 48, 50, -1, 51, 48, 48, 48, 51, 50, 48, 48, 54, 50, 48, 53, 50, 48, 48, 48, 50, 48, 53, 45, 48, 54, 50, 72, -1, 48, -1, 48, -1, 60, 53, 48, 53, 48, 15, 48, 53, -1, 53, 48, 53, 48, 65, -1, 53, -1, 53, 48, 55, 70, 72, 48, 53, 70, 63, 70, 53, 70, 48, 48, 41, 42, 59, 53, 53, 55, 48, 13, 57, 70, 48, 53, 48, 55, 20, 53, -1, 53, -1, 55, -1, 5, -1, 61, 5, -1, 32, 33, 13, 13, -1, 16, 13, -1, -1, -1, 20, -1, -1, 20, 22, 23, 24, 25, 26, 27, 28, -1, 32, 33, -1, 32, 33, 21, 22, 23, 24, 25, 26, 27, 28, 13, -1, -1, -1, -1, -1, -1, 20, 21, 22, 23, 24, 25, 26, 27, 28, 13, -1, -1, -1, -1, -1, -1, 20, 21, 22, 23, 24, 25, 26, 27, 28, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, 16, -1, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; } // namespace QbsQmlJS qbs-src-1.4.5/src/lib/corelib/parser/qmljsgrammar_p.h000066400000000000000000000120561266132464200225420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists for the convenience // of other Qt classes. This header file may change from version to // version without notice, or even be removed. // // We mean it. // // This file was generated by qlalr - DO NOT EDIT! #ifndef QMLJSGRAMMAR_P_H #define QMLJSGRAMMAR_P_H #include "qmljsglobal_p.h" #include namespace QbsQmlJS { class QML_PARSER_EXPORT QmlJSGrammar { public: enum VariousConstants { EOF_SYMBOL = 0, REDUCE_HERE = 101, SHIFT_THERE = 100, T_AND = 1, T_AND_AND = 2, T_AND_EQ = 3, T_AS = 91, T_AUTOMATIC_SEMICOLON = 62, T_BREAK = 4, T_CASE = 5, T_CATCH = 6, T_COLON = 7, T_COMMA = 8, T_COMMENT = 88, T_CONST = 84, T_CONTINUE = 9, T_DEBUGGER = 85, T_DEFAULT = 10, T_DELETE = 11, T_DIVIDE_ = 12, T_DIVIDE_EQ = 13, T_DO = 14, T_DOT = 15, T_ELSE = 16, T_EQ = 17, T_EQ_EQ = 18, T_EQ_EQ_EQ = 19, T_ERROR = 93, T_FALSE = 83, T_FEED_JS_EXPRESSION = 97, T_FEED_JS_PROGRAM = 99, T_FEED_JS_SOURCE_ELEMENT = 98, T_FEED_JS_STATEMENT = 96, T_FEED_UI_OBJECT_MEMBER = 95, T_FEED_UI_PROGRAM = 94, T_FINALLY = 20, T_FOR = 21, T_FUNCTION = 22, T_GE = 23, T_GT = 24, T_GT_GT = 25, T_GT_GT_EQ = 26, T_GT_GT_GT = 27, T_GT_GT_GT_EQ = 28, T_IDENTIFIER = 29, T_IF = 30, T_IMPORT = 90, T_IN = 31, T_INSTANCEOF = 32, T_LBRACE = 33, T_LBRACKET = 34, T_LE = 35, T_LPAREN = 36, T_LT = 37, T_LT_LT = 38, T_LT_LT_EQ = 39, T_MINUS = 40, T_MINUS_EQ = 41, T_MINUS_MINUS = 42, T_MULTILINE_STRING_LITERAL = 87, T_NEW = 43, T_NOT = 44, T_NOT_EQ = 45, T_NOT_EQ_EQ = 46, T_NULL = 81, T_NUMERIC_LITERAL = 47, T_ON = 92, T_OR = 48, T_OR_EQ = 49, T_OR_OR = 50, T_PLUS = 51, T_PLUS_EQ = 52, T_PLUS_PLUS = 53, T_PROPERTY = 66, T_PUBLIC = 89, T_QUESTION = 54, T_RBRACE = 55, T_RBRACKET = 56, T_READONLY = 68, T_REMAINDER = 57, T_REMAINDER_EQ = 58, T_RESERVED_WORD = 86, T_RETURN = 59, T_RPAREN = 60, T_SEMICOLON = 61, T_SIGNAL = 67, T_STAR = 63, T_STAR_EQ = 64, T_STRING_LITERAL = 65, T_SWITCH = 69, T_THIS = 70, T_THROW = 71, T_TILDE = 72, T_TRUE = 82, T_TRY = 73, T_TYPEOF = 74, T_VAR = 75, T_VOID = 76, T_WHILE = 77, T_WITH = 78, T_XOR = 79, T_XOR_EQ = 80, ACCEPT_STATE = 644, RULE_COUNT = 349, STATE_COUNT = 645, TERMINAL_COUNT = 102, NON_TERMINAL_COUNT = 107, GOTO_INDEX_OFFSET = 645, GOTO_INFO_OFFSET = 2807, GOTO_CHECK_OFFSET = 2807 }; static const char *const spell []; static const short lhs []; static const short rhs []; static const short goto_default []; static const short action_default []; static const short action_index []; static const short action_info []; static const short action_check []; static inline int nt_action (int state, int nt) { const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt; if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt) return goto_default [nt]; return action_info [GOTO_INFO_OFFSET + yyn]; } static inline int t_action (int state, int token) { const int yyn = action_index [state] + token; if (yyn < 0 || action_check [yyn] != token) return - action_default [state]; return action_info [yyn]; } }; } // namespace QbsQmlJS #endif // QMLJSGRAMMAR_P_H qbs-src-1.4.5/src/lib/corelib/parser/qmljskeywords_p.h000066400000000000000000000530061266132464200227630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QMLJSKEYWORDS_P_H #define QMLJSKEYWORDS_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // namespace QbsQmlJS { static inline int classify2(const QChar *s, bool qmlMode) { if (s[0].unicode() == 'a') { if (s[1].unicode() == 's') { return qmlMode ? Lexer::T_AS : Lexer::T_RESERVED_WORD; } } else if (s[0].unicode() == 'd') { if (s[1].unicode() == 'o') { return Lexer::T_DO; } } else if (s[0].unicode() == 'i') { if (s[1].unicode() == 'f') { return Lexer::T_IF; } else if (s[1].unicode() == 'n') { return Lexer::T_IN; } } else if (qmlMode && s[0].unicode() == 'o') { if (s[1].unicode() == 'n') { return Lexer::T_ON; } } return Lexer::T_IDENTIFIER; } static inline int classify3(const QChar *s, bool /*qmlMode*/) { if (s[0].unicode() == 'f') { if (s[1].unicode() == 'o') { if (s[2].unicode() == 'r') { return Lexer::T_FOR; } } } else if (s[0].unicode() == 'i') { if (s[1].unicode() == 'n') { if (s[2].unicode() == 't') { return Lexer::T_INT; } } } else if (s[0].unicode() == 'n') { if (s[1].unicode() == 'e') { if (s[2].unicode() == 'w') { return Lexer::T_NEW; } } } else if (s[0].unicode() == 't') { if (s[1].unicode() == 'r') { if (s[2].unicode() == 'y') { return Lexer::T_TRY; } } } else if (s[0].unicode() == 'v') { if (s[1].unicode() == 'a') { if (s[2].unicode() == 'r') { return Lexer::T_VAR; } } } return Lexer::T_IDENTIFIER; } static inline int classify4(const QChar *s, bool /*qmlMode*/) { if (s[0].unicode() == 'b') { if (s[1].unicode() == 'y') { if (s[2].unicode() == 't') { if (s[3].unicode() == 'e') { return Lexer::T_BYTE; } } } } else if (s[0].unicode() == 'c') { if (s[1].unicode() == 'a') { if (s[2].unicode() == 's') { if (s[3].unicode() == 'e') { return Lexer::T_CASE; } } } else if (s[1].unicode() == 'h') { if (s[2].unicode() == 'a') { if (s[3].unicode() == 'r') { return Lexer::T_CHAR; } } } } else if (s[0].unicode() == 'e') { if (s[1].unicode() == 'l') { if (s[2].unicode() == 's') { if (s[3].unicode() == 'e') { return Lexer::T_ELSE; } } } else if (s[1].unicode() == 'n') { if (s[2].unicode() == 'u') { if (s[3].unicode() == 'm') { return Lexer::T_ENUM; } } } } else if (s[0].unicode() == 'g') { if (s[1].unicode() == 'o') { if (s[2].unicode() == 't') { if (s[3].unicode() == 'o') { return Lexer::T_GOTO; } } } } else if (s[0].unicode() == 'l') { if (s[1].unicode() == 'o') { if (s[2].unicode() == 'n') { if (s[3].unicode() == 'g') { return Lexer::T_LONG; } } } } else if (s[0].unicode() == 'n') { if (s[1].unicode() == 'u') { if (s[2].unicode() == 'l') { if (s[3].unicode() == 'l') { return Lexer::T_NULL; } } } } else if (s[0].unicode() == 't') { if (s[1].unicode() == 'h') { if (s[2].unicode() == 'i') { if (s[3].unicode() == 's') { return Lexer::T_THIS; } } } else if (s[1].unicode() == 'r') { if (s[2].unicode() == 'u') { if (s[3].unicode() == 'e') { return Lexer::T_TRUE; } } } } else if (s[0].unicode() == 'v') { if (s[1].unicode() == 'o') { if (s[2].unicode() == 'i') { if (s[3].unicode() == 'd') { return Lexer::T_VOID; } } } } else if (s[0].unicode() == 'w') { if (s[1].unicode() == 'i') { if (s[2].unicode() == 't') { if (s[3].unicode() == 'h') { return Lexer::T_WITH; } } } } return Lexer::T_IDENTIFIER; } static inline int classify5(const QChar *s, bool /*qmlMode*/) { if (s[0].unicode() == 'b') { if (s[1].unicode() == 'r') { if (s[2].unicode() == 'e') { if (s[3].unicode() == 'a') { if (s[4].unicode() == 'k') { return Lexer::T_BREAK; } } } } } else if (s[0].unicode() == 'c') { if (s[1].unicode() == 'a') { if (s[2].unicode() == 't') { if (s[3].unicode() == 'c') { if (s[4].unicode() == 'h') { return Lexer::T_CATCH; } } } } else if (s[1].unicode() == 'l') { if (s[2].unicode() == 'a') { if (s[3].unicode() == 's') { if (s[4].unicode() == 's') { return Lexer::T_CLASS; } } } } else if (s[1].unicode() == 'o') { if (s[2].unicode() == 'n') { if (s[3].unicode() == 's') { if (s[4].unicode() == 't') { return Lexer::T_CONST; } } } } } else if (s[0].unicode() == 'f') { if (s[1].unicode() == 'a') { if (s[2].unicode() == 'l') { if (s[3].unicode() == 's') { if (s[4].unicode() == 'e') { return Lexer::T_FALSE; } } } } else if (s[1].unicode() == 'i') { if (s[2].unicode() == 'n') { if (s[3].unicode() == 'a') { if (s[4].unicode() == 'l') { return Lexer::T_FINAL; } } } } else if (s[1].unicode() == 'l') { if (s[2].unicode() == 'o') { if (s[3].unicode() == 'a') { if (s[4].unicode() == 't') { return Lexer::T_FLOAT; } } } } } else if (s[0].unicode() == 's') { if (s[1].unicode() == 'h') { if (s[2].unicode() == 'o') { if (s[3].unicode() == 'r') { if (s[4].unicode() == 't') { return Lexer::T_SHORT; } } } } else if (s[1].unicode() == 'u') { if (s[2].unicode() == 'p') { if (s[3].unicode() == 'e') { if (s[4].unicode() == 'r') { return Lexer::T_SUPER; } } } } } else if (s[0].unicode() == 't') { if (s[1].unicode() == 'h') { if (s[2].unicode() == 'r') { if (s[3].unicode() == 'o') { if (s[4].unicode() == 'w') { return Lexer::T_THROW; } } } } } else if (s[0].unicode() == 'w') { if (s[1].unicode() == 'h') { if (s[2].unicode() == 'i') { if (s[3].unicode() == 'l') { if (s[4].unicode() == 'e') { return Lexer::T_WHILE; } } } } } return Lexer::T_IDENTIFIER; } static inline int classify6(const QChar *s, bool qmlMode) { if (s[0].unicode() == 'd') { if (s[1].unicode() == 'e') { if (s[2].unicode() == 'l') { if (s[3].unicode() == 'e') { if (s[4].unicode() == 't') { if (s[5].unicode() == 'e') { return Lexer::T_DELETE; } } } } } else if (s[1].unicode() == 'o') { if (s[2].unicode() == 'u') { if (s[3].unicode() == 'b') { if (s[4].unicode() == 'l') { if (s[5].unicode() == 'e') { return Lexer::T_DOUBLE; } } } } } } else if (s[0].unicode() == 'e') { if (s[1].unicode() == 'x') { if (s[2].unicode() == 'p') { if (s[3].unicode() == 'o') { if (s[4].unicode() == 'r') { if (s[5].unicode() == 't') { return Lexer::T_EXPORT; } } } } } } else if (s[0].unicode() == 'i') { if (s[1].unicode() == 'm') { if (s[2].unicode() == 'p') { if (s[3].unicode() == 'o') { if (s[4].unicode() == 'r') { if (s[5].unicode() == 't') { return qmlMode ? Lexer::T_IMPORT : Lexer::T_RESERVED_WORD; } } } } } } else if (s[0].unicode() == 'n') { if (s[1].unicode() == 'a') { if (s[2].unicode() == 't') { if (s[3].unicode() == 'i') { if (s[4].unicode() == 'v') { if (s[5].unicode() == 'e') { return Lexer::T_NATIVE; } } } } } } else if (s[0].unicode() == 'p') { if (s[1].unicode() == 'u') { if (s[2].unicode() == 'b') { if (s[3].unicode() == 'l') { if (s[4].unicode() == 'i') { if (s[5].unicode() == 'c') { return qmlMode ? Lexer::T_PUBLIC : Lexer::T_RESERVED_WORD; } } } } } } else if (s[0].unicode() == 'r') { if (s[1].unicode() == 'e') { if (s[2].unicode() == 't') { if (s[3].unicode() == 'u') { if (s[4].unicode() == 'r') { if (s[5].unicode() == 'n') { return Lexer::T_RETURN; } } } } } } else if (s[0].unicode() == 's') { if (qmlMode && s[1].unicode() == 'i') { if (s[2].unicode() == 'g') { if (s[3].unicode() == 'n') { if (s[4].unicode() == 'a') { if (s[5].unicode() == 'l') { return Lexer::T_SIGNAL; } } } } } else if (s[1].unicode() == 't') { if (s[2].unicode() == 'a') { if (s[3].unicode() == 't') { if (s[4].unicode() == 'i') { if (s[5].unicode() == 'c') { return Lexer::T_STATIC; } } } } } else if (s[1].unicode() == 'w') { if (s[2].unicode() == 'i') { if (s[3].unicode() == 't') { if (s[4].unicode() == 'c') { if (s[5].unicode() == 'h') { return Lexer::T_SWITCH; } } } } } } else if (s[0].unicode() == 't') { if (s[1].unicode() == 'h') { if (s[2].unicode() == 'r') { if (s[3].unicode() == 'o') { if (s[4].unicode() == 'w') { if (s[5].unicode() == 's') { return Lexer::T_THROWS; } } } } } else if (s[1].unicode() == 'y') { if (s[2].unicode() == 'p') { if (s[3].unicode() == 'e') { if (s[4].unicode() == 'o') { if (s[5].unicode() == 'f') { return Lexer::T_TYPEOF; } } } } } } return Lexer::T_IDENTIFIER; } static inline int classify7(const QChar *s, bool /*qmlMode*/) { if (s[0].unicode() == 'b') { if (s[1].unicode() == 'o') { if (s[2].unicode() == 'o') { if (s[3].unicode() == 'l') { if (s[4].unicode() == 'e') { if (s[5].unicode() == 'a') { if (s[6].unicode() == 'n') { return Lexer::T_BOOLEAN; } } } } } } } else if (s[0].unicode() == 'd') { if (s[1].unicode() == 'e') { if (s[2].unicode() == 'f') { if (s[3].unicode() == 'a') { if (s[4].unicode() == 'u') { if (s[5].unicode() == 'l') { if (s[6].unicode() == 't') { return Lexer::T_DEFAULT; } } } } } } } else if (s[0].unicode() == 'e') { if (s[1].unicode() == 'x') { if (s[2].unicode() == 't') { if (s[3].unicode() == 'e') { if (s[4].unicode() == 'n') { if (s[5].unicode() == 'd') { if (s[6].unicode() == 's') { return Lexer::T_EXTENDS; } } } } } } } else if (s[0].unicode() == 'f') { if (s[1].unicode() == 'i') { if (s[2].unicode() == 'n') { if (s[3].unicode() == 'a') { if (s[4].unicode() == 'l') { if (s[5].unicode() == 'l') { if (s[6].unicode() == 'y') { return Lexer::T_FINALLY; } } } } } } } else if (s[0].unicode() == 'p') { if (s[1].unicode() == 'a') { if (s[2].unicode() == 'c') { if (s[3].unicode() == 'k') { if (s[4].unicode() == 'a') { if (s[5].unicode() == 'g') { if (s[6].unicode() == 'e') { return Lexer::T_PACKAGE; } } } } } } else if (s[1].unicode() == 'r') { if (s[2].unicode() == 'i') { if (s[3].unicode() == 'v') { if (s[4].unicode() == 'a') { if (s[5].unicode() == 't') { if (s[6].unicode() == 'e') { return Lexer::T_PRIVATE; } } } } } } } return Lexer::T_IDENTIFIER; } static inline int classify8(const QChar *s, bool qmlMode) { if (s[0].unicode() == 'a') { if (s[1].unicode() == 'b') { if (s[2].unicode() == 's') { if (s[3].unicode() == 't') { if (s[4].unicode() == 'r') { if (s[5].unicode() == 'a') { if (s[6].unicode() == 'c') { if (s[7].unicode() == 't') { return Lexer::T_ABSTRACT; } } } } } } } } else if (s[0].unicode() == 'c') { if (s[1].unicode() == 'o') { if (s[2].unicode() == 'n') { if (s[3].unicode() == 't') { if (s[4].unicode() == 'i') { if (s[5].unicode() == 'n') { if (s[6].unicode() == 'u') { if (s[7].unicode() == 'e') { return Lexer::T_CONTINUE; } } } } } } } } else if (s[0].unicode() == 'd') { if (s[1].unicode() == 'e') { if (s[2].unicode() == 'b') { if (s[3].unicode() == 'u') { if (s[4].unicode() == 'g') { if (s[5].unicode() == 'g') { if (s[6].unicode() == 'e') { if (s[7].unicode() == 'r') { return Lexer::T_DEBUGGER; } } } } } } } } else if (s[0].unicode() == 'f') { if (s[1].unicode() == 'u') { if (s[2].unicode() == 'n') { if (s[3].unicode() == 'c') { if (s[4].unicode() == 't') { if (s[5].unicode() == 'i') { if (s[6].unicode() == 'o') { if (s[7].unicode() == 'n') { return Lexer::T_FUNCTION; } } } } } } } } else if (qmlMode && s[0].unicode() == 'p') { if (s[1].unicode() == 'r') { if (s[2].unicode() == 'o') { if (s[3].unicode() == 'p') { if (s[4].unicode() == 'e') { if (s[5].unicode() == 'r') { if (s[6].unicode() == 't') { if (s[7].unicode() == 'y') { return Lexer::T_PROPERTY; } } } } } } } } else if (qmlMode && s[0].unicode() == 'r') { if (s[1].unicode() == 'e') { if (s[2].unicode() == 'a') { if (s[3].unicode() == 'd') { if (s[4].unicode() == 'o') { if (s[5].unicode() == 'n') { if (s[6].unicode() == 'l') { if (s[7].unicode() == 'y') { return Lexer::T_READONLY; } } } } } } } } else if (s[0].unicode() == 'v') { if (s[1].unicode() == 'o') { if (s[2].unicode() == 'l') { if (s[3].unicode() == 'a') { if (s[4].unicode() == 't') { if (s[5].unicode() == 'i') { if (s[6].unicode() == 'l') { if (s[7].unicode() == 'e') { return Lexer::T_VOLATILE; } } } } } } } } return Lexer::T_IDENTIFIER; } static inline int classify9(const QChar *s, bool /*qmlMode*/) { if (s[0].unicode() == 'i') { if (s[1].unicode() == 'n') { if (s[2].unicode() == 't') { if (s[3].unicode() == 'e') { if (s[4].unicode() == 'r') { if (s[5].unicode() == 'f') { if (s[6].unicode() == 'a') { if (s[7].unicode() == 'c') { if (s[8].unicode() == 'e') { return Lexer::T_INTERFACE; } } } } } } } } } else if (s[0].unicode() == 'p') { if (s[1].unicode() == 'r') { if (s[2].unicode() == 'o') { if (s[3].unicode() == 't') { if (s[4].unicode() == 'e') { if (s[5].unicode() == 'c') { if (s[6].unicode() == 't') { if (s[7].unicode() == 'e') { if (s[8].unicode() == 'd') { return Lexer::T_PROTECTED; } } } } } } } } } else if (s[0].unicode() == 't') { if (s[1].unicode() == 'r') { if (s[2].unicode() == 'a') { if (s[3].unicode() == 'n') { if (s[4].unicode() == 's') { if (s[5].unicode() == 'i') { if (s[6].unicode() == 'e') { if (s[7].unicode() == 'n') { if (s[8].unicode() == 't') { return Lexer::T_TRANSIENT; } } } } } } } } } return Lexer::T_IDENTIFIER; } static inline int classify10(const QChar *s, bool /*qmlMode*/) { if (s[0].unicode() == 'i') { if (s[1].unicode() == 'm') { if (s[2].unicode() == 'p') { if (s[3].unicode() == 'l') { if (s[4].unicode() == 'e') { if (s[5].unicode() == 'm') { if (s[6].unicode() == 'e') { if (s[7].unicode() == 'n') { if (s[8].unicode() == 't') { if (s[9].unicode() == 's') { return Lexer::T_IMPLEMENTS; } } } } } } } } } else if (s[1].unicode() == 'n') { if (s[2].unicode() == 's') { if (s[3].unicode() == 't') { if (s[4].unicode() == 'a') { if (s[5].unicode() == 'n') { if (s[6].unicode() == 'c') { if (s[7].unicode() == 'e') { if (s[8].unicode() == 'o') { if (s[9].unicode() == 'f') { return Lexer::T_INSTANCEOF; } } } } } } } } } } return Lexer::T_IDENTIFIER; } static inline int classify12(const QChar *s, bool /*qmlMode*/) { if (s[0].unicode() == 's') { if (s[1].unicode() == 'y') { if (s[2].unicode() == 'n') { if (s[3].unicode() == 'c') { if (s[4].unicode() == 'h') { if (s[5].unicode() == 'r') { if (s[6].unicode() == 'o') { if (s[7].unicode() == 'n') { if (s[8].unicode() == 'i') { if (s[9].unicode() == 'z') { if (s[10].unicode() == 'e') { if (s[11].unicode() == 'd') { return Lexer::T_SYNCHRONIZED; } } } } } } } } } } } } return Lexer::T_IDENTIFIER; } int Lexer::classify(const QChar *s, int n, bool qmlMode) { switch (n) { case 2: return classify2(s, qmlMode); case 3: return classify3(s, qmlMode); case 4: return classify4(s, qmlMode); case 5: return classify5(s, qmlMode); case 6: return classify6(s, qmlMode); case 7: return classify7(s, qmlMode); case 8: return classify8(s, qmlMode); case 9: return classify9(s, qmlMode); case 10: return classify10(s, qmlMode); case 12: return classify12(s, qmlMode); default: return Lexer::T_IDENTIFIER; } // switch } } // namespace QbsQmlJS #endif // QMLJSKEYWORDS_P_H qbs-src-1.4.5/src/lib/corelib/parser/qmljslexer.cpp000066400000000000000000000774471266132464200222660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "qmljslexer_p.h" #include "qmljsengine_p.h" #include "qmljsmemorypool_p.h" #include #include #include QT_BEGIN_NAMESPACE Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok); QT_END_NAMESPACE namespace QbsQmlJS { static int regExpFlagFromChar(const QChar &ch) { switch (ch.unicode()) { case 'g': return Lexer::RegExp_Global; case 'i': return Lexer::RegExp_IgnoreCase; case 'm': return Lexer::RegExp_Multiline; } return 0; } static unsigned char convertHex(ushort c) { if (c >= '0' && c <= '9') return (c - '0'); else if (c >= 'a' && c <= 'f') return (c - 'a' + 10); else return (c - 'A' + 10); } static QChar convertHex(QChar c1, QChar c2) { return QChar((convertHex(c1.unicode()) << 4) + convertHex(c2.unicode())); } static QChar convertUnicode(QChar c1, QChar c2, QChar c3, QChar c4) { return QChar((convertHex(c3.unicode()) << 4) + convertHex(c4.unicode()), (convertHex(c1.unicode()) << 4) + convertHex(c2.unicode())); } Lexer::Lexer(Engine *engine) : _engine(engine) , _codePtr(0) , _lastLinePtr(0) , _tokenLinePtr(0) , _tokenStartPtr(0) , _char(QLatin1Char('\n')) , _errorCode(NoError) , _currentLineNumber(0) , _tokenValue(0) , _parenthesesState(IgnoreParentheses) , _parenthesesCount(0) , _stackToken(-1) , _patternFlags(0) , _tokenKind(0) , _tokenLength(0) , _tokenLine(0) , _validTokenText(false) , _prohibitAutomaticSemicolon(false) , _restrictedKeyword(false) , _terminator(false) , _followsClosingBrace(false) , _delimited(true) , _qmlMode(true) { if (engine) engine->setLexer(this); } bool Lexer::qmlMode() const { return _qmlMode; } QString Lexer::code() const { return _code; } void Lexer::setCode(const QString &code, int lineno, bool qmlMode) { if (_engine) _engine->setCode(code); _qmlMode = qmlMode; _code = code; _tokenText.clear(); _tokenText.reserve(1024); _errorMessage.clear(); _tokenSpell = QStringRef(); _codePtr = code.unicode(); _lastLinePtr = _codePtr; _tokenLinePtr = _codePtr; _tokenStartPtr = _codePtr; _char = QLatin1Char('\n'); _errorCode = NoError; _currentLineNumber = lineno; _tokenValue = 0; // parentheses state _parenthesesState = IgnoreParentheses; _parenthesesCount = 0; _stackToken = -1; _patternFlags = 0; _tokenLength = 0; _tokenLine = lineno; _validTokenText = false; _prohibitAutomaticSemicolon = false; _restrictedKeyword = false; _terminator = false; _followsClosingBrace = false; _delimited = true; } void Lexer::scanChar() { _char = *_codePtr++; if (_char == QLatin1Char('\n')) { _lastLinePtr = _codePtr; // points to the first character after the newline ++_currentLineNumber; } } int Lexer::lex() { const int previousTokenKind = _tokenKind; _tokenSpell = QStringRef(); _tokenKind = scanToken(); _tokenLength = _codePtr - _tokenStartPtr - 1; _delimited = false; _restrictedKeyword = false; _followsClosingBrace = (previousTokenKind == T_RBRACE); // update the flags switch (_tokenKind) { case T_LBRACE: case T_SEMICOLON: case T_COLON: _delimited = true; break; case T_IF: case T_FOR: case T_WHILE: case T_WITH: _parenthesesState = CountParentheses; _parenthesesCount = 0; break; case T_DO: _parenthesesState = BalancedParentheses; break; case T_CONTINUE: case T_BREAK: case T_RETURN: case T_THROW: _restrictedKeyword = true; break; } // switch // update the parentheses state switch (_parenthesesState) { case IgnoreParentheses: break; case CountParentheses: if (_tokenKind == T_RPAREN) { --_parenthesesCount; if (_parenthesesCount == 0) _parenthesesState = BalancedParentheses; } else if (_tokenKind == T_LPAREN) { ++_parenthesesCount; } break; case BalancedParentheses: _parenthesesState = IgnoreParentheses; break; } // switch return _tokenKind; } bool Lexer::isUnicodeEscapeSequence(const QChar *chars) { if (isHexDigit(chars[0]) && isHexDigit(chars[1]) && isHexDigit(chars[2]) && isHexDigit(chars[3])) return true; return false; } QChar Lexer::decodeUnicodeEscapeCharacter(bool *ok) { if (_char == QLatin1Char('u') && isUnicodeEscapeSequence(&_codePtr[0])) { scanChar(); // skip u const QChar c1 = _char; scanChar(); const QChar c2 = _char; scanChar(); const QChar c3 = _char; scanChar(); const QChar c4 = _char; scanChar(); if (ok) *ok = true; return convertUnicode(c1, c2, c3, c4); } *ok = false; return QChar(); } int Lexer::scanToken() { if (_stackToken != -1) { int tk = _stackToken; _stackToken = -1; return tk; } _terminator = false; again: _validTokenText = false; _tokenLinePtr = _lastLinePtr; while (_char.isSpace()) { if (_char == QLatin1Char('\n')) { _tokenLinePtr = _codePtr; if (_restrictedKeyword) { // automatic semicolon insertion _tokenLine = _currentLineNumber; _tokenStartPtr = _codePtr - 1; // ### TODO: insert it before the optional \r sequence. return T_SEMICOLON; } else { _terminator = true; syncProhibitAutomaticSemicolon(); } } scanChar(); } _tokenStartPtr = _codePtr - 1; _tokenLine = _currentLineNumber; if (_char.isNull()) return EOF_SYMBOL; const QChar ch = _char; scanChar(); switch (ch.unicode()) { case '~': return T_TILDE; case '}': return T_RBRACE; case '|': if (_char == QLatin1Char('|')) { scanChar(); return T_OR_OR; } else if (_char == QLatin1Char('=')) { scanChar(); return T_OR_EQ; } return T_OR; case '{': return T_LBRACE; case '^': if (_char == QLatin1Char('=')) { scanChar(); return T_XOR_EQ; } return T_XOR; case ']': return T_RBRACKET; case '[': return T_LBRACKET; case '?': return T_QUESTION; case '>': if (_char == QLatin1Char('>')) { scanChar(); if (_char == QLatin1Char('>')) { scanChar(); if (_char == QLatin1Char('=')) { scanChar(); return T_GT_GT_GT_EQ; } return T_GT_GT_GT; } else if (_char == QLatin1Char('=')) { scanChar(); return T_GT_GT_EQ; } return T_GT_GT; } else if (_char == QLatin1Char('=')) { scanChar(); return T_GE; } return T_GT; case '=': if (_char == QLatin1Char('=')) { scanChar(); if (_char == QLatin1Char('=')) { scanChar(); return T_EQ_EQ_EQ; } return T_EQ_EQ; } return T_EQ; case '<': if (_char == QLatin1Char('=')) { scanChar(); return T_LE; } else if (_char == QLatin1Char('<')) { scanChar(); if (_char == QLatin1Char('=')) { scanChar(); return T_LT_LT_EQ; } return T_LT_LT; } return T_LT; case ';': return T_SEMICOLON; case ':': return T_COLON; case '/': if (_char == QLatin1Char('*')) { scanChar(); while (!_char.isNull()) { if (_char == QLatin1Char('*')) { scanChar(); if (_char == QLatin1Char('/')) { scanChar(); if (_engine) { _engine->addComment(tokenOffset() + 2, _codePtr - _tokenStartPtr - 1 - 4, tokenStartLine(), tokenStartColumn() + 2); } goto again; } } else { scanChar(); } } } else if (_char == QLatin1Char('/')) { while (!_char.isNull() && _char != QLatin1Char('\n')) { scanChar(); } if (_engine) { _engine->addComment(tokenOffset() + 2, _codePtr - _tokenStartPtr - 1 - 2, tokenStartLine(), tokenStartColumn() + 2); } goto again; } if (_char == QLatin1Char('=')) { scanChar(); return T_DIVIDE_EQ; } return T_DIVIDE_; case '.': if (_char.isDigit()) { QVarLengthArray chars; chars.append(ch.unicode()); // append the `.' while (_char.isDigit()) { chars.append(_char.unicode()); scanChar(); } if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) { if (_codePtr[0].isDigit() || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) && _codePtr[1].isDigit())) { chars.append(_char.unicode()); scanChar(); // consume `e' if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) { chars.append(_char.unicode()); scanChar(); // consume the sign } while (_char.isDigit()) { chars.append(_char.unicode()); scanChar(); } } } chars.append('\0'); const char *begin = chars.constData(); const char *end = 0; bool ok = false; _tokenValue = qstrtod(begin, &end, &ok); if (end - begin != chars.size() - 1) { _errorCode = IllegalExponentIndicator; _errorMessage = QCoreApplication::translate("QmlParser", "Illegal syntax for exponential number"); return T_ERROR; } return T_NUMERIC_LITERAL; } return T_DOT; case '-': if (_char == QLatin1Char('=')) { scanChar(); return T_MINUS_EQ; } else if (_char == QLatin1Char('-')) { scanChar(); if (_terminator && !_delimited && !_prohibitAutomaticSemicolon) { _stackToken = T_MINUS_MINUS; return T_SEMICOLON; } return T_MINUS_MINUS; } return T_MINUS; case ',': return T_COMMA; case '+': if (_char == QLatin1Char('=')) { scanChar(); return T_PLUS_EQ; } else if (_char == QLatin1Char('+')) { scanChar(); if (_terminator && !_delimited && !_prohibitAutomaticSemicolon) { _stackToken = T_PLUS_PLUS; return T_SEMICOLON; } return T_PLUS_PLUS; } return T_PLUS; case '*': if (_char == QLatin1Char('=')) { scanChar(); return T_STAR_EQ; } return T_STAR; case ')': return T_RPAREN; case '(': return T_LPAREN; case '&': if (_char == QLatin1Char('=')) { scanChar(); return T_AND_EQ; } else if (_char == QLatin1Char('&')) { scanChar(); return T_AND_AND; } return T_AND; case '%': if (_char == QLatin1Char('=')) { scanChar(); return T_REMAINDER_EQ; } return T_REMAINDER; case '!': if (_char == QLatin1Char('=')) { scanChar(); if (_char == QLatin1Char('=')) { scanChar(); return T_NOT_EQ_EQ; } return T_NOT_EQ; } return T_NOT; case '\'': case '"': { const QChar quote = ch; bool multilineStringLiteral = false; const QChar *startCode = _codePtr; if (_engine) { while (!_char.isNull()) { if (_char == QLatin1Char('\n') || _char == QLatin1Char('\\')) { break; } else if (_char == quote) { _tokenSpell = _engine->midRef(startCode - _code.unicode() - 1, _codePtr - startCode); scanChar(); return T_STRING_LITERAL; } scanChar(); } } _validTokenText = true; _tokenText.resize(0); startCode--; while (startCode != _codePtr - 1) _tokenText += *startCode++; while (! _char.isNull()) { if (_char == QLatin1Char('\n')) { multilineStringLiteral = true; _tokenText += _char; scanChar(); } else if (_char == quote) { scanChar(); if (_engine) _tokenSpell = _engine->newStringRef(_tokenText); return multilineStringLiteral ? T_MULTILINE_STRING_LITERAL : T_STRING_LITERAL; } else if (_char == QLatin1Char('\\')) { scanChar(); QChar u; bool ok = false; switch (_char.unicode()) { // unicode escape sequence case 'u': u = decodeUnicodeEscapeCharacter(&ok); if (! ok) u = _char; break; // hex escape sequence case 'x': case 'X': if (isHexDigit(_codePtr[0]) && isHexDigit(_codePtr[1])) { scanChar(); const QChar c1 = _char; scanChar(); const QChar c2 = _char; scanChar(); u = convertHex(c1, c2); } else { u = _char; } break; // single character escape sequence case '\\': u = QLatin1Char('\\'); scanChar(); break; case '\'': u = QLatin1Char('\''); scanChar(); break; case '\"': u = QLatin1Char('\"'); scanChar(); break; case 'b': u = QLatin1Char('\b'); scanChar(); break; case 'f': u = QLatin1Char('\f'); scanChar(); break; case 'n': u = QLatin1Char('\n'); scanChar(); break; case 'r': u = QLatin1Char('\r'); scanChar(); break; case 't': u = QLatin1Char('\t'); scanChar(); break; case 'v': u = QLatin1Char('\v'); scanChar(); break; case '0': if (! _codePtr[1].isDigit()) { scanChar(); u = QLatin1Char('\0'); } else { // ### parse deprecated octal escape sequence ? u = _char; } break; case '\r': while (_char == QLatin1Char('\r')) scanChar(); if (_char == QLatin1Char('\n')) { u = _char; scanChar(); } else { u = QLatin1Char('\n'); } break; case '\n': u = _char; scanChar(); break; default: // non escape character u = _char; scanChar(); } _tokenText += u; } else { _tokenText += _char; scanChar(); } } _errorCode = UnclosedStringLiteral; _errorMessage = QCoreApplication::translate("QmlParser", "Unclosed string at end of line"); return T_ERROR; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return scanNumber(ch); default: if (ch.isLetter() || ch == QLatin1Char('$') || ch == QLatin1Char('_') || (ch == QLatin1Char('\\') && _char == QLatin1Char('u'))) { bool identifierWithEscapeChars = false; if (ch == QLatin1Char('\\')) { identifierWithEscapeChars = true; _tokenText.resize(0); bool ok = false; _tokenText += decodeUnicodeEscapeCharacter(&ok); _validTokenText = true; if (! ok) { _errorCode = IllegalUnicodeEscapeSequence; _errorMessage = QCoreApplication::translate("QmlParser", "Illegal unicode escape sequence"); return T_ERROR; } } while (true) { if (_char.isLetterOrNumber() || _char == QLatin1Char('$') || _char == QLatin1Char('_')) { if (identifierWithEscapeChars) _tokenText += _char; scanChar(); } else if (_char == QLatin1Char('\\') && _codePtr[0] == QLatin1Char('u')) { if (! identifierWithEscapeChars) { identifierWithEscapeChars = true; _tokenText.resize(0); _tokenText.insert(0, _tokenStartPtr, _codePtr - _tokenStartPtr - 1); _validTokenText = true; } scanChar(); // skip '\\' bool ok = false; _tokenText += decodeUnicodeEscapeCharacter(&ok); if (! ok) { _errorCode = IllegalUnicodeEscapeSequence; _errorMessage = QCoreApplication::translate("QmlParser", "Illegal unicode escape sequence"); return T_ERROR; } } else { _tokenLength = _codePtr - _tokenStartPtr - 1; int kind = T_IDENTIFIER; if (! identifierWithEscapeChars) kind = classify(_tokenStartPtr, _tokenLength, _qmlMode); if (_engine) { if (kind == T_IDENTIFIER && identifierWithEscapeChars) _tokenSpell = _engine->newStringRef(_tokenText); else _tokenSpell = _engine->midRef(_tokenStartPtr - _code.unicode(), _tokenLength); } return kind; } } } break; } return T_ERROR; } int Lexer::scanNumber(QChar ch) { if (ch != QLatin1Char('0')) { double integer = ch.unicode() - '0'; QChar n = _char; const QChar *code = _codePtr; while (n.isDigit()) { integer = integer * 10 + (n.unicode() - '0'); n = *code++; } if (n != QLatin1Char('.') && n != QLatin1Char('e') && n != QLatin1Char('E')) { if (code != _codePtr) { _codePtr = code - 1; scanChar(); } _tokenValue = integer; return T_NUMERIC_LITERAL; } } QVarLengthArray chars; chars.append(ch.unicode()); if (ch == QLatin1Char('0') && (_char == QLatin1Char('x') || _char == QLatin1Char('X'))) { // parse hex integer literal chars.append(_char.unicode()); scanChar(); // consume `x' while (isHexDigit(_char)) { chars.append(_char.unicode()); scanChar(); } _tokenValue = integerFromString(chars.constData(), chars.size(), 16); return T_NUMERIC_LITERAL; } // decimal integer literal while (_char.isDigit()) { chars.append(_char.unicode()); scanChar(); // consume the digit } if (_char == QLatin1Char('.')) { chars.append(_char.unicode()); scanChar(); // consume `.' while (_char.isDigit()) { chars.append(_char.unicode()); scanChar(); } if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) { if (_codePtr[0].isDigit() || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) && _codePtr[1].isDigit())) { chars.append(_char.unicode()); scanChar(); // consume `e' if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) { chars.append(_char.unicode()); scanChar(); // consume the sign } while (_char.isDigit()) { chars.append(_char.unicode()); scanChar(); } } } } else if (_char == QLatin1Char('e') || _char == QLatin1Char('E')) { if (_codePtr[0].isDigit() || ((_codePtr[0] == QLatin1Char('+') || _codePtr[0] == QLatin1Char('-')) && _codePtr[1].isDigit())) { chars.append(_char.unicode()); scanChar(); // consume `e' if (_char == QLatin1Char('+') || _char == QLatin1Char('-')) { chars.append(_char.unicode()); scanChar(); // consume the sign } while (_char.isDigit()) { chars.append(_char.unicode()); scanChar(); } } } if (chars.size() == 1) { // if we ended up with a single digit, then it was a '0' _tokenValue = 0; return T_NUMERIC_LITERAL; } chars.append('\0'); const char *begin = chars.constData(); const char *end = 0; bool ok = false; _tokenValue = qstrtod(begin, &end, &ok); if (end - begin != chars.size() - 1) { _errorCode = IllegalExponentIndicator; _errorMessage = QCoreApplication::translate("QmlParser", "Illegal syntax for exponential number"); return T_ERROR; } return T_NUMERIC_LITERAL; } bool Lexer::scanRegExp(RegExpBodyPrefix prefix) { _tokenText.resize(0); _validTokenText = true; _patternFlags = 0; if (prefix == EqualPrefix) _tokenText += QLatin1Char('='); while (true) { switch (_char.unicode()) { case 0: // eof case '\n': case '\r': // line terminator _errorMessage = QCoreApplication::translate("QmlParser", "Unterminated regular expression literal"); return false; case '/': scanChar(); // scan the flags _patternFlags = 0; while (isIdentLetter(_char)) { int flag = regExpFlagFromChar(_char); if (flag == 0) { _errorMessage = QCoreApplication::translate("QmlParser", "Invalid regular expression flag '%0'") .arg(QChar(_char)); return false; } _patternFlags |= flag; scanChar(); } _tokenLength = _codePtr - _tokenStartPtr - 1; return true; case '\\': // regular expression backslash sequence _tokenText += _char; scanChar(); if (_char.isNull() || isLineTerminator()) { _errorMessage = QCoreApplication::translate("QmlParser", "Unterminated regular expression backslash sequence"); return false; } _tokenText += _char; scanChar(); break; case '[': // regular expression class _tokenText += _char; scanChar(); while (! _char.isNull() && ! isLineTerminator()) { if (_char == QLatin1Char(']')) break; else if (_char == QLatin1Char('\\')) { // regular expression backslash sequence _tokenText += _char; scanChar(); if (_char.isNull() || isLineTerminator()) { _errorMessage = QCoreApplication::translate("QmlParser", "Unterminated regular expression backslash sequence"); return false; } _tokenText += _char; scanChar(); } else { _tokenText += _char; scanChar(); } } if (_char != QLatin1Char(']')) { _errorMessage = QCoreApplication::translate("QmlParser", "Unterminated regular expression class"); return false; } _tokenText += _char; scanChar(); // skip ] break; default: _tokenText += _char; scanChar(); } // switch } // while return false; } bool Lexer::isLineTerminator() const { return (_char == QLatin1Char('\n') || _char == QLatin1Char('\r')); } bool Lexer::isIdentLetter(QChar ch) { // ASCII-biased, since all reserved words are ASCII, aand hence the // bulk of content to be parsed. if ((ch >= QLatin1Char('a') && ch <= QLatin1Char('z')) || (ch >= QLatin1Char('A') && ch <= QLatin1Char('Z')) || ch == QLatin1Char('$') || ch == QLatin1Char('_')) return true; if (ch.unicode() < 128) return false; return ch.isLetterOrNumber(); } bool Lexer::isDecimalDigit(ushort c) { return (c >= '0' && c <= '9'); } bool Lexer::isHexDigit(QChar c) { return ((c >= QLatin1Char('0') && c <= QLatin1Char('9')) || (c >= QLatin1Char('a') && c <= QLatin1Char('f')) || (c >= QLatin1Char('A') && c <= QLatin1Char('F'))); } bool Lexer::isOctalDigit(ushort c) { return (c >= '0' && c <= '7'); } int Lexer::tokenEndLine() const { return _currentLineNumber; } int Lexer::tokenEndColumn() const { return _codePtr - _lastLinePtr; } QString Lexer::tokenText() const { if (_validTokenText) return _tokenText; if (_tokenKind == T_STRING_LITERAL) return QString(_tokenStartPtr + 1, _tokenLength - 2); return QString(_tokenStartPtr, _tokenLength); } Lexer::Error Lexer::errorCode() const { return _errorCode; } QString Lexer::errorMessage() const { return _errorMessage; } void Lexer::syncProhibitAutomaticSemicolon() { if (_parenthesesState == BalancedParentheses) { // we have seen something like "if (foo)", which means we should // never insert an automatic semicolon at this point, since it would // then be expanded into an empty statement (ECMA-262 7.9.1) _prohibitAutomaticSemicolon = true; _parenthesesState = IgnoreParentheses; } else { _prohibitAutomaticSemicolon = false; } } bool Lexer::prevTerminator() const { return _terminator; } bool Lexer::followsClosingBrace() const { return _followsClosingBrace; } bool Lexer::canInsertAutomaticSemicolon(int token) const { return token == T_RBRACE || token == EOF_SYMBOL || _terminator || _followsClosingBrace; } bool Lexer::scanDirectives(Directives *directives) { if (_qmlMode) { // the directives are a Javascript-only extension. return false; } lex(); // fetch the first token if (_tokenKind != T_DOT) return true; do { lex(); // skip T_DOT const int lineNumber = tokenStartLine(); if (! (_tokenKind == T_IDENTIFIER || _tokenKind == T_RESERVED_WORD)) return false; // expected a valid QML/JS directive const QString directiveName = tokenText(); if (! (directiveName == QLatin1String("pragma") || directiveName == QLatin1String("import"))) return false; // not a valid directive name // it must be a pragma or an import directive. if (directiveName == QLatin1String("pragma")) { // .pragma library if (! (lex() == T_IDENTIFIER && tokenText() == QLatin1String("library"))) return false; // expected `library // we found a .pragma library directive directives->pragmaLibrary(); } else { Q_ASSERT(directiveName == QLatin1String("import")); lex(); // skip .import QString pathOrUri; QString version; bool fileImport = false; // file or uri import if (_tokenKind == T_STRING_LITERAL) { // .import T_STRING_LITERAL as T_IDENTIFIER fileImport = true; pathOrUri = tokenText(); } else if (_tokenKind == T_IDENTIFIER) { // .import T_IDENTIFIER (. T_IDENTIFIER)* T_NUMERIC_LITERAL as T_IDENTIFIER pathOrUri = tokenText(); lex(); // skip the first T_IDENTIFIER for (; _tokenKind == T_DOT; lex()) { if (lex() != T_IDENTIFIER) return false; pathOrUri += QLatin1Char('.'); pathOrUri += tokenText(); } if (_tokenKind != T_NUMERIC_LITERAL) return false; // expected the module version number version = tokenText(); } // // recognize the mandatory `as' followed by the module name // if (! (lex() == T_RESERVED_WORD && tokenText() == QLatin1String("as"))) return false; // expected `as' if (lex() != T_IDENTIFIER) return false; // expected module name const QString module = tokenText(); if (fileImport) directives->importFile(pathOrUri, module); else directives->importModule(pathOrUri, version, module); } if (tokenStartLine() != lineNumber) return false; // the directives cannot span over multiple lines // fetch the first token after the .pragma/.import directive lex(); } while (_tokenKind == T_DOT); return true; } } // namespace QbsQmlJS #include "qmljskeywords_p.h" qbs-src-1.4.5/src/lib/corelib/parser/qmljslexer_p.h000066400000000000000000000145221266132464200222330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QMLJSLEXER_P_H #define QMLJSLEXER_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include "qmljsglobal_p.h" #include "qmljsgrammar_p.h" #include namespace QbsQmlJS { class Engine; class QML_PARSER_EXPORT Directives { public: virtual ~Directives() {} virtual void pragmaLibrary() { } virtual void importFile(const QString &jsfile, const QString &module) { Q_UNUSED(jsfile); Q_UNUSED(module); } virtual void importModule(const QString &uri, const QString &version, const QString &module) { Q_UNUSED(uri); Q_UNUSED(version); Q_UNUSED(module); } }; class QML_PARSER_EXPORT Lexer: public QmlJSGrammar { public: enum { T_ABSTRACT = T_RESERVED_WORD, T_BOOLEAN = T_RESERVED_WORD, T_BYTE = T_RESERVED_WORD, T_CHAR = T_RESERVED_WORD, T_CLASS = T_RESERVED_WORD, T_DOUBLE = T_RESERVED_WORD, T_ENUM = T_RESERVED_WORD, T_EXPORT = T_RESERVED_WORD, T_EXTENDS = T_RESERVED_WORD, T_FINAL = T_RESERVED_WORD, T_FLOAT = T_RESERVED_WORD, T_GOTO = T_RESERVED_WORD, T_IMPLEMENTS = T_RESERVED_WORD, T_INT = T_RESERVED_WORD, T_INTERFACE = T_RESERVED_WORD, T_LET = T_RESERVED_WORD, T_LONG = T_RESERVED_WORD, T_NATIVE = T_RESERVED_WORD, T_PACKAGE = T_RESERVED_WORD, T_PRIVATE = T_RESERVED_WORD, T_PROTECTED = T_RESERVED_WORD, T_SHORT = T_RESERVED_WORD, T_STATIC = T_RESERVED_WORD, T_SUPER = T_RESERVED_WORD, T_SYNCHRONIZED = T_RESERVED_WORD, T_THROWS = T_RESERVED_WORD, T_TRANSIENT = T_RESERVED_WORD, T_VOLATILE = T_RESERVED_WORD, T_YIELD = T_RESERVED_WORD }; enum Error { NoError, IllegalCharacter, UnclosedStringLiteral, IllegalEscapeSequence, IllegalUnicodeEscapeSequence, UnclosedComment, IllegalExponentIndicator, IllegalIdentifier }; enum RegExpBodyPrefix { NoPrefix, EqualPrefix }; enum RegExpFlag { RegExp_Global = 0x01, RegExp_IgnoreCase = 0x02, RegExp_Multiline = 0x04 }; public: Lexer(Engine *engine); bool qmlMode() const; QString code() const; void setCode(const QString &code, int lineno, bool qmlMode = true); int lex(); bool scanRegExp(RegExpBodyPrefix prefix = NoPrefix); bool scanDirectives(Directives *directives); int regExpFlags() const { return _patternFlags; } QString regExpPattern() const { return _tokenText; } int tokenKind() const { return _tokenKind; } int tokenOffset() const { return _tokenStartPtr - _code.unicode(); } int tokenLength() const { return _tokenLength; } int tokenStartLine() const { return _tokenLine; } int tokenStartColumn() const { return _tokenStartPtr - _tokenLinePtr + 1; } int tokenEndLine() const; int tokenEndColumn() const; inline QStringRef tokenSpell() const { return _tokenSpell; } double tokenValue() const { return _tokenValue; } QString tokenText() const; Error errorCode() const; QString errorMessage() const; bool prevTerminator() const; bool followsClosingBrace() const; bool canInsertAutomaticSemicolon(int token) const; enum ParenthesesState { IgnoreParentheses, CountParentheses, BalancedParentheses }; protected: int classify(const QChar *s, int n, bool qmlMode); private: inline void scanChar(); int scanToken(); int scanNumber(QChar ch); bool isLineTerminator() const; static bool isIdentLetter(QChar c); static bool isDecimalDigit(ushort c); static bool isHexDigit(QChar c); static bool isOctalDigit(ushort c); static bool isUnicodeEscapeSequence(const QChar *chars); void syncProhibitAutomaticSemicolon(); QChar decodeUnicodeEscapeCharacter(bool *ok); private: Engine *_engine; QString _code; QString _tokenText; QString _errorMessage; QStringRef _tokenSpell; const QChar *_codePtr; const QChar *_lastLinePtr; const QChar *_tokenLinePtr; const QChar *_tokenStartPtr; QChar _char; Error _errorCode; int _currentLineNumber; double _tokenValue; // parentheses state ParenthesesState _parenthesesState; int _parenthesesCount; int _stackToken; int _patternFlags; int _tokenKind; int _tokenLength; int _tokenLine; bool _validTokenText; bool _prohibitAutomaticSemicolon; bool _restrictedKeyword; bool _terminator; bool _followsClosingBrace; bool _delimited; bool _qmlMode; }; } // namespace QbsQmlJS #endif // LEXER_H qbs-src-1.4.5/src/lib/corelib/parser/qmljsmemorypool_p.h000066400000000000000000000101051266132464200233070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QMLJSMEMORYPOOL_P_H #define QMLJSMEMORYPOOL_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include "qmljsglobal_p.h" #include #include #include #include namespace QbsQmlJS { class QML_PARSER_EXPORT MemoryPool : public QSharedData { MemoryPool(const MemoryPool &other); void operator =(const MemoryPool &other); public: MemoryPool() : _blocks(0), _allocatedBlocks(0), _blockCount(-1), _ptr(0), _end(0) { } ~MemoryPool() { if (_blocks) { for (int i = 0; i < _allocatedBlocks; ++i) { if (char *b = _blocks[i]) free(b); } free(_blocks); } } inline void *allocate(size_t size) { size = (size + 7) & ~7; if (_ptr && (_ptr + size < _end)) { void *addr = _ptr; _ptr += size; return addr; } return allocate_helper(size); } void reset() { _blockCount = -1; _ptr = _end = 0; } private: void *allocate_helper(size_t size) { Q_ASSERT(size < BLOCK_SIZE); if (++_blockCount == _allocatedBlocks) { if (! _allocatedBlocks) _allocatedBlocks = DEFAULT_BLOCK_COUNT; else _allocatedBlocks *= 2; _blocks = (char **) realloc(_blocks, sizeof(char *) * _allocatedBlocks); for (int index = _blockCount; index < _allocatedBlocks; ++index) _blocks[index] = 0; } char *&block = _blocks[_blockCount]; if (! block) block = (char *) malloc(BLOCK_SIZE); _ptr = block; _end = _ptr + BLOCK_SIZE; void *addr = _ptr; _ptr += size; return addr; } private: char **_blocks; int _allocatedBlocks; int _blockCount; char *_ptr; char *_end; enum { BLOCK_SIZE = 8 * 1024, DEFAULT_BLOCK_COUNT = 8 }; }; class QML_PARSER_EXPORT Managed { Managed(const Managed &other); void operator = (const Managed &other); public: Managed() {} ~Managed() {} void *operator new(size_t size, MemoryPool *pool) { return pool->allocate(size); } void operator delete(void *) {} void operator delete(void *, MemoryPool *) {} }; } // namespace QbsQmlJS #endif qbs-src-1.4.5/src/lib/corelib/parser/qmljsparser.cpp000066400000000000000000001427531266132464200224340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #include #include #include "qmljsengine_p.h" #include "qmljslexer_p.h" #include "qmljsast_p.h" #include "qmljsmemorypool_p.h" #include "qmljsparser_p.h" #include // // This file is automatically generated from qmljs.g. // Changes will be lost. // namespace QbsQmlJS { void Parser::reallocateStack() { if (! stack_size) stack_size = 128; else stack_size <<= 1; sym_stack = reinterpret_cast (realloc(sym_stack, stack_size * sizeof(Value))); state_stack = reinterpret_cast (realloc(state_stack, stack_size * sizeof(int))); location_stack = reinterpret_cast (realloc(location_stack, stack_size * sizeof(AST::SourceLocation))); string_stack = reinterpret_cast (realloc(string_stack, stack_size * sizeof(QStringRef))); } Parser::Parser(Engine *engine): driver(engine), pool(engine->pool()), tos(0), stack_size(0), sym_stack(0), state_stack(0), location_stack(0), string_stack(0), program(0), first_token(0), last_token(0) { } Parser::~Parser() { if (stack_size) { free(sym_stack); free(state_stack); free(location_stack); free(string_stack); } } static inline AST::SourceLocation location(Lexer *lexer) { AST::SourceLocation loc; loc.offset = lexer->tokenOffset(); loc.length = lexer->tokenLength(); loc.startLine = lexer->tokenStartLine(); loc.startColumn = lexer->tokenStartColumn(); return loc; } AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) { QVarLengthArray nameIds; QVarLengthArray locations; AST::ExpressionNode *it = expr; while (AST::FieldMemberExpression *m = AST::cast(it)) { nameIds.append(m->name); locations.append(m->identifierToken); it = m->base; } if (AST::IdentifierExpression *idExpr = AST::cast(it)) { AST::UiQualifiedId *q = new (pool) AST::UiQualifiedId(idExpr->name); q->identifierToken = idExpr->identifierToken; AST::UiQualifiedId *currentId = q; for (int i = nameIds.size() - 1; i != -1; --i) { currentId = new (pool) AST::UiQualifiedId(currentId, nameIds[i]); currentId->identifierToken = locations[i]; } return currentId->finish(); } return 0; } bool Parser::parse(int startToken) { Lexer *lexer = driver->lexer(); bool hadErrors = false; int yytoken = -1; int action = 0; token_buffer[0].token = startToken; first_token = &token_buffer[0]; if (startToken == T_FEED_JS_PROGRAM) { Directives ignoreDirectives; Directives *directives = driver->directives(); if (!directives) directives = &ignoreDirectives; lexer->scanDirectives(directives); token_buffer[1].token = lexer->tokenKind(); token_buffer[1].dval = lexer->tokenValue(); token_buffer[1].loc = location(lexer); token_buffer[1].spell = lexer->tokenSpell(); last_token = &token_buffer[2]; } else { last_token = &token_buffer[1]; } tos = -1; program = 0; do { if (++tos == stack_size) reallocateStack(); state_stack[tos] = action; _Lcheck_token: if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) { yyprevlloc = yylloc; if (first_token == last_token) { yytoken = lexer->lex(); yylval = lexer->tokenValue(); yytokenspell = lexer->tokenSpell(); yylloc = location(lexer); } else { yytoken = first_token->token; yylval = first_token->dval; yytokenspell = first_token->spell; yylloc = first_token->loc; ++first_token; } } action = t_action(action, yytoken); if (action > 0) { if (action != ACCEPT_STATE) { yytoken = -1; sym(1).dval = yylval; stringRef(1) = yytokenspell; loc(1) = yylloc; } else { --tos; return ! hadErrors; } } else if (action < 0) { const int r = -action - 1; tos -= rhs[r]; switch (r) { case 0: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; case 1: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; case 2: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; case 3: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; case 4: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; case 5: { sym(1).Node = sym(2).Node; program = sym(1).Node; } break; case 6: { sym(1).UiProgram = new (pool) AST::UiProgram(sym(1).UiImportList, sym(2).UiObjectMemberList->finish()); } break; case 8: { sym(1).Node = sym(1).UiImportList->finish(); } break; case 9: { sym(1).Node = new (pool) AST::UiImportList(sym(1).UiImport); } break; case 10: { sym(1).Node = new (pool) AST::UiImportList(sym(1).UiImportList, sym(2).UiImport); } break; case 13: { sym(1).UiImport->semicolonToken = loc(2); } break; case 15: { sym(1).UiImport->versionToken = loc(2); sym(1).UiImport->semicolonToken = loc(3); } break; case 17: { sym(1).UiImport->versionToken = loc(2); sym(1).UiImport->asToken = loc(3); sym(1).UiImport->importIdToken = loc(4); sym(1).UiImport->importId = stringRef(4); sym(1).UiImport->semicolonToken = loc(5); } break; case 19: { sym(1).UiImport->asToken = loc(2); sym(1).UiImport->importIdToken = loc(3); sym(1).UiImport->importId = stringRef(3); sym(1).UiImport->semicolonToken = loc(4); } break; case 20: { AST::UiImport *node = 0; if (AST::StringLiteral *importIdLiteral = AST::cast(sym(2).Expression)) { node = new (pool) AST::UiImport(importIdLiteral->value); node->fileNameToken = loc(2); } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) { node = new (pool) AST::UiImport(qualifiedId); node->fileNameToken = loc(2); } sym(1).Node = node; if (node) { node->importToken = loc(1); } else { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), QLatin1String("Expected a qualified name id or a string literal"))); return false; // ### remove me } } break; case 21: { sym(1).Node = 0; } break; case 22: { sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember); } break; case 23: { sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember); } break; case 24: { AST::UiObjectMemberList *node = new (pool) AST:: UiObjectMemberList( sym(1).UiObjectMemberList, sym(2).UiObjectMember); sym(1).Node = node; } break; case 25: { sym(1).Node = new (pool) AST::UiArrayMemberList(sym(1).UiObjectMember); } break; case 26: { AST::UiArrayMemberList *node = new (pool) AST::UiArrayMemberList( sym(1).UiArrayMemberList, sym(3).UiObjectMember); node->commaToken = loc(2); sym(1).Node = node; } break; case 27: { AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer((AST::UiObjectMemberList*)0); node->lbraceToken = loc(1); node->rbraceToken = loc(2); sym(1).Node = node; } break; case 28: { AST::UiObjectInitializer *node = new (pool) AST::UiObjectInitializer(sym(2).UiObjectMemberList->finish()); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; case 29: { AST::UiObjectDefinition *node = new (pool) AST::UiObjectDefinition(sym(1).UiQualifiedId, sym(2).UiObjectInitializer); sym(1).Node = node; } break; case 31: { AST::UiArrayBinding *node = new (pool) AST::UiArrayBinding( sym(1).UiQualifiedId, sym(4).UiArrayMemberList->finish()); node->colonToken = loc(2); node->lbracketToken = loc(3); node->rbracketToken = loc(5); sym(1).Node = node; } break; case 32: { AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding( sym(1).UiQualifiedId, sym(3).UiQualifiedId, sym(4).UiObjectInitializer); node->colonToken = loc(2); sym(1).Node = node; } break; case 33: { AST::UiObjectBinding *node = new (pool) AST::UiObjectBinding( sym(3).UiQualifiedId, sym(1).UiQualifiedId, sym(4).UiObjectInitializer); node->colonToken = loc(2); node->hasOnToken = true; sym(1).Node = node; } break; case 41: { AST::UiScriptBinding *node = new (pool) AST::UiScriptBinding( sym(1).UiQualifiedId, sym(3).Statement); node->colonToken = loc(2); sym(1).Node = node; } break; case 45: { sym(1).Node = 0; } break; case 46: { sym(1).Node = sym(1).UiParameterList->finish (); } break; case 47: { AST::UiParameterList *node = new (pool) AST::UiParameterList(stringRef(1), stringRef(2)); node->propertyTypeToken = loc(1); node->identifierToken = loc(2); sym(1).Node = node; } break; case 48: { AST::UiParameterList *node = new (pool) AST::UiParameterList(sym(1).UiParameterList, stringRef(3), stringRef(4)); node->commaToken = loc(2); node->identifierToken = loc(4); sym(1).Node = node; } break; case 50: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(QStringRef(), stringRef(2)); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(2); node->parameters = sym(4).UiParameterList; node->semicolonToken = loc(6); sym(1).Node = node; } break; case 52: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(QStringRef(), stringRef(2)); node->type = AST::UiPublicMember::Signal; node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(2); node->semicolonToken = loc(3); sym(1).Node = node; } break; case 54: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(4), stringRef(6)); node->typeModifier = stringRef(2); node->propertyToken = loc(1); node->typeModifierToken = loc(2); node->typeToken = loc(4); node->identifierToken = loc(6); node->semicolonToken = loc(7); sym(1).Node = node; } break; case 56: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3)); node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(3); node->semicolonToken = loc(4); sym(1).Node = node; } break; case 58: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4)); node->isDefaultMember = true; node->defaultToken = loc(1); node->propertyToken = loc(2); node->typeToken = loc(3); node->identifierToken = loc(4); node->semicolonToken = loc(5); sym(1).Node = node; } break; case 59: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3), sym(5).Statement); node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(3); node->colonToken = loc(4); sym(1).Node = node; } break; case 60: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4), sym(6).Statement); node->isReadonlyMember = true; node->readonlyToken = loc(1); node->propertyToken = loc(2); node->typeToken = loc(3); node->identifierToken = loc(4); node->colonToken = loc(5); sym(1).Node = node; } break; case 61: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4), sym(6).Statement); node->isDefaultMember = true; node->defaultToken = loc(1); node->propertyToken = loc(2); node->typeToken = loc(3); node->identifierToken = loc(4); node->colonToken = loc(5); sym(1).Node = node; } break; case 62: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(4), stringRef(6)); node->typeModifier = stringRef(2); node->propertyToken = loc(1); node->typeModifierToken = loc(2); node->typeToken = loc(4); node->identifierToken = loc(6); node->semicolonToken = loc(7); // insert a fake ';' before ':' AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(6)); propertyName->identifierToken = loc(6); propertyName->next = 0; AST::UiArrayBinding *binding = new (pool) AST::UiArrayBinding( propertyName, sym(9).UiArrayMemberList->finish()); binding->colonToken = loc(7); binding->lbracketToken = loc(8); binding->rbracketToken = loc(10); node->binding = binding; sym(1).Node = node; } break; case 63: { AST::UiPublicMember *node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3)); node->propertyToken = loc(1); node->typeToken = loc(2); node->identifierToken = loc(3); node->semicolonToken = loc(4); // insert a fake ';' before ':' AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(3)); propertyName->identifierToken = loc(3); propertyName->next = 0; AST::UiObjectBinding *binding = new (pool) AST::UiObjectBinding( propertyName, sym(5).UiQualifiedId, sym(6).UiObjectInitializer); binding->colonToken = loc(4); node->binding = binding; sym(1).Node = node; } break; case 64: { sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); } break; case 65: { sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node); } break; case 71: { AST::ThisExpression *node = new (pool) AST::ThisExpression(); node->thisToken = loc(1); sym(1).Node = node; } break; case 72: { AST::IdentifierExpression *node = new (pool) AST::IdentifierExpression(stringRef(1)); node->identifierToken = loc(1); sym(1).Node = node; } break; case 73: { AST::NullExpression *node = new (pool) AST::NullExpression(); node->nullToken = loc(1); sym(1).Node = node; } break; case 74: { AST::TrueLiteral *node = new (pool) AST::TrueLiteral(); node->trueToken = loc(1); sym(1).Node = node; } break; case 75: { AST::FalseLiteral *node = new (pool) AST::FalseLiteral(); node->falseToken = loc(1); sym(1).Node = node; } break; case 76: { AST::NumericLiteral *node = new (pool) AST::NumericLiteral(sym(1).dval); node->literalToken = loc(1); sym(1).Node = node; } break; case 77: case 78: { AST::StringLiteral *node = new (pool) AST::StringLiteral(stringRef(1)); node->literalToken = loc(1); sym(1).Node = node; } break; case 79: { bool rx = lexer->scanRegExp(Lexer::NoPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); return false; // ### remove me } loc(1).length = lexer->tokenLength(); yylloc = loc(1); // adjust the location of the current token AST::RegExpLiteral *node = new (pool) AST::RegExpLiteral( driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags()); node->literalToken = loc(1); sym(1).Node = node; } break; case 80: { bool rx = lexer->scanRegExp(Lexer::EqualPrefix); if (!rx) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); return false; } loc(1).length = lexer->tokenLength(); yylloc = loc(1); // adjust the location of the current token AST::RegExpLiteral *node = new (pool) AST::RegExpLiteral( driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags()); node->literalToken = loc(1); sym(1).Node = node; } break; case 81: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral((AST::Elision *) 0); node->lbracketToken = loc(1); node->rbracketToken = loc(2); sym(1).Node = node; } break; case 82: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).Elision->finish()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; case 83: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish ()); node->lbracketToken = loc(1); node->rbracketToken = loc(3); sym(1).Node = node; } break; case 84: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), (AST::Elision *) 0); node->lbracketToken = loc(1); node->commaToken = loc(3); node->rbracketToken = loc(4); sym(1).Node = node; } break; case 85: { AST::ArrayLiteral *node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), sym(4).Elision->finish()); node->lbracketToken = loc(1); node->commaToken = loc(3); node->rbracketToken = loc(5); sym(1).Node = node; } break; case 86: { AST::ObjectLiteral *node = 0; if (sym(2).Node) node = new (pool) AST::ObjectLiteral( sym(2).PropertyNameAndValueList->finish ()); else node = new (pool) AST::ObjectLiteral(); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; case 87: { AST::ObjectLiteral *node = new (pool) AST::ObjectLiteral( sym(2).PropertyNameAndValueList->finish ()); node->lbraceToken = loc(1); node->rbraceToken = loc(4); sym(1).Node = node; } break; case 88: { AST::NestedExpression *node = new (pool) AST::NestedExpression(sym(2).Expression); node->lparenToken = loc(1); node->rparenToken = loc(3); sym(1).Node = node; } break; case 89: { if (AST::ArrayMemberExpression *mem = AST::cast(sym(1).Expression)) { diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken, QLatin1String("Ignored annotation"))); sym(1).Expression = mem->base; } if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) { sym(1).UiQualifiedId = qualifiedId; } else { sym(1).UiQualifiedId = 0; diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), QLatin1String("Expected a qualified name id"))); return false; // ### recover } } break; case 90: { sym(1).Node = new (pool) AST::ElementList((AST::Elision *) 0, sym(1).Expression); } break; case 91: { sym(1).Node = new (pool) AST::ElementList(sym(1).Elision->finish(), sym(2).Expression); } break; case 92: { AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, (AST::Elision *) 0, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; case 93: { AST::ElementList *node = new (pool) AST::ElementList(sym(1).ElementList, sym(3).Elision->finish(), sym(4).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; case 94: { AST::Elision *node = new (pool) AST::Elision(); node->commaToken = loc(1); sym(1).Node = node; } break; case 95: { AST::Elision *node = new (pool) AST::Elision(sym(1).Elision); node->commaToken = loc(2); sym(1).Node = node; } break; case 96: { AST::PropertyNameAndValueList *node = new (pool) AST::PropertyNameAndValueList( sym(1).PropertyName, sym(3).Expression); node->colonToken = loc(2); sym(1).Node = node; } break; case 97: { AST::PropertyNameAndValueList *node = new (pool) AST::PropertyNameAndValueList( sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression); node->commaToken = loc(2); node->colonToken = loc(4); sym(1).Node = node; } break; case 98: { AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; case 99: case 100: { AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; case 101: { AST::StringLiteralPropertyName *node = new (pool) AST::StringLiteralPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; case 102: { AST::NumericLiteralPropertyName *node = new (pool) AST::NumericLiteralPropertyName(sym(1).dval); node->propertyNameToken = loc(1); sym(1).Node = node; } break; case 103: { AST::IdentifierPropertyName *node = new (pool) AST::IdentifierPropertyName(stringRef(1)); node->propertyNameToken = loc(1); sym(1).Node = node; } break; case 139: { AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; case 140: { AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; case 141: { AST::NewMemberExpression *node = new (pool) AST::NewMemberExpression(sym(2).Expression, sym(4).ArgumentList); node->newToken = loc(1); node->lparenToken = loc(3); node->rparenToken = loc(5); sym(1).Node = node; } break; case 143: { AST::NewExpression *node = new (pool) AST::NewExpression(sym(2).Expression); node->newToken = loc(1); sym(1).Node = node; } break; case 144: { AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; case 145: { AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; case 146: { AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression); node->lbracketToken = loc(2); node->rbracketToken = loc(4); sym(1).Node = node; } break; case 147: { AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3)); node->dotToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; case 148: { sym(1).Node = 0; } break; case 149: { sym(1).Node = sym(1).ArgumentList->finish(); } break; case 150: { sym(1).Node = new (pool) AST::ArgumentList(sym(1).Expression); } break; case 151: { AST::ArgumentList *node = new (pool) AST::ArgumentList(sym(1).ArgumentList, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; case 155: { AST::PostIncrementExpression *node = new (pool) AST::PostIncrementExpression(sym(1).Expression); node->incrementToken = loc(2); sym(1).Node = node; } break; case 156: { AST::PostDecrementExpression *node = new (pool) AST::PostDecrementExpression(sym(1).Expression); node->decrementToken = loc(2); sym(1).Node = node; } break; case 158: { AST::DeleteExpression *node = new (pool) AST::DeleteExpression(sym(2).Expression); node->deleteToken = loc(1); sym(1).Node = node; } break; case 159: { AST::VoidExpression *node = new (pool) AST::VoidExpression(sym(2).Expression); node->voidToken = loc(1); sym(1).Node = node; } break; case 160: { AST::TypeOfExpression *node = new (pool) AST::TypeOfExpression(sym(2).Expression); node->typeofToken = loc(1); sym(1).Node = node; } break; case 161: { AST::PreIncrementExpression *node = new (pool) AST::PreIncrementExpression(sym(2).Expression); node->incrementToken = loc(1); sym(1).Node = node; } break; case 162: { AST::PreDecrementExpression *node = new (pool) AST::PreDecrementExpression(sym(2).Expression); node->decrementToken = loc(1); sym(1).Node = node; } break; case 163: { AST::UnaryPlusExpression *node = new (pool) AST::UnaryPlusExpression(sym(2).Expression); node->plusToken = loc(1); sym(1).Node = node; } break; case 164: { AST::UnaryMinusExpression *node = new (pool) AST::UnaryMinusExpression(sym(2).Expression); node->minusToken = loc(1); sym(1).Node = node; } break; case 165: { AST::TildeExpression *node = new (pool) AST::TildeExpression(sym(2).Expression); node->tildeToken = loc(1); sym(1).Node = node; } break; case 166: { AST::NotExpression *node = new (pool) AST::NotExpression(sym(2).Expression); node->notToken = loc(1); sym(1).Node = node; } break; case 168: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Mul, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 169: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Div, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 170: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Mod, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 172: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Add, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 173: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Sub, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 175: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::LShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 176: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::RShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 177: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::URShift, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 179: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 180: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 181: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 182: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 183: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 184: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::In, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 186: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Lt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 187: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Gt, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 188: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Le, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 189: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Ge, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 190: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::InstanceOf, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 192: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 193: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 194: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 195: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 197: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Equal, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 198: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::NotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 199: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 200: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::StrictNotEqual, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 202: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 204: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitAnd, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 206: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 208: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitXor, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 210: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 212: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::BitOr, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 214: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 216: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::And, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 218: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Or, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 220: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Or, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 222: { AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); node->colonToken = loc(4); sym(1).Node = node; } break; case 224: { AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, sym(3).Expression, sym(5).Expression); node->questionToken = loc(2); node->colonToken = loc(4); sym(1).Node = node; } break; case 226: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 228: { AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression); node->operatorToken = loc(2); sym(1).Node = node; } break; case 229: { sym(1).ival = QSOperator::Assign; } break; case 230: { sym(1).ival = QSOperator::InplaceMul; } break; case 231: { sym(1).ival = QSOperator::InplaceDiv; } break; case 232: { sym(1).ival = QSOperator::InplaceMod; } break; case 233: { sym(1).ival = QSOperator::InplaceAdd; } break; case 234: { sym(1).ival = QSOperator::InplaceSub; } break; case 235: { sym(1).ival = QSOperator::InplaceLeftShift; } break; case 236: { sym(1).ival = QSOperator::InplaceRightShift; } break; case 237: { sym(1).ival = QSOperator::InplaceURightShift; } break; case 238: { sym(1).ival = QSOperator::InplaceAnd; } break; case 239: { sym(1).ival = QSOperator::InplaceXor; } break; case 240: { sym(1).ival = QSOperator::InplaceOr; } break; case 242: { AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; case 243: { sym(1).Node = 0; } break; case 246: { AST::Expression *node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression); node->commaToken = loc(2); sym(1).Node = node; } break; case 247: { sym(1).Node = 0; } break; case 264: { AST::Block *node = new (pool) AST::Block(sym(2).StatementList); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; case 265: { sym(1).Node = new (pool) AST::StatementList(sym(1).Statement); } break; case 266: { sym(1).Node = new (pool) AST::StatementList(sym(1).StatementList, sym(2).Statement); } break; case 267: { sym(1).Node = 0; } break; case 268: { sym(1).Node = sym(1).StatementList->finish (); } break; case 270: { AST::VariableStatement *node = new (pool) AST::VariableStatement( sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST)); node->declarationKindToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; case 271: { sym(1).ival = T_CONST; } break; case 272: { sym(1).ival = T_VAR; } break; case 273: { sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); } break; case 274: { AST::VariableDeclarationList *node = new (pool) AST::VariableDeclarationList( sym(1).VariableDeclarationList, sym(3).VariableDeclaration); node->commaToken = loc(2); sym(1).Node = node; } break; case 275: { sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration); } break; case 276: { sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclarationList, sym(3).VariableDeclaration); } break; case 277: { AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; case 278: { AST::VariableDeclaration *node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression); node->identifierToken = loc(1); sym(1).Node = node; } break; case 279: { // ### TODO: AST for initializer sym(1) = sym(2); } break; case 280: { sym(1).Node = 0; } break; case 282: { // ### TODO: AST for initializer sym(1) = sym(2); } break; case 283: { sym(1).Node = 0; } break; case 285: { AST::EmptyStatement *node = new (pool) AST::EmptyStatement(); node->semicolonToken = loc(1); sym(1).Node = node; } break; case 287: { AST::ExpressionStatement *node = new (pool) AST::ExpressionStatement(sym(1).Expression); node->semicolonToken = loc(2); sym(1).Node = node; } break; case 288: { AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement, sym(7).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); node->elseToken = loc(6); sym(1).Node = node; } break; case 289: { AST::IfStatement *node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement); node->ifToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; case 291: { AST::DoWhileStatement *node = new (pool) AST::DoWhileStatement(sym(2).Statement, sym(5).Expression); node->doToken = loc(1); node->whileToken = loc(3); node->lparenToken = loc(4); node->rparenToken = loc(6); node->semicolonToken = loc(7); sym(1).Node = node; } break; case 292: { AST::WhileStatement *node = new (pool) AST::WhileStatement(sym(3).Expression, sym(5).Statement); node->whileToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; case 293: { AST::ForStatement *node = new (pool) AST::ForStatement(sym(3).Expression, sym(5).Expression, sym(7).Expression, sym(9).Statement); node->forToken = loc(1); node->lparenToken = loc(2); node->firstSemicolonToken = loc(4); node->secondSemicolonToken = loc(6); node->rparenToken = loc(8); sym(1).Node = node; } break; case 294: { AST::LocalForStatement *node = new (pool) AST::LocalForStatement( sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression, sym(8).Expression, sym(10).Statement); node->forToken = loc(1); node->lparenToken = loc(2); node->varToken = loc(3); node->firstSemicolonToken = loc(5); node->secondSemicolonToken = loc(7); node->rparenToken = loc(9); sym(1).Node = node; } break; case 295: { AST:: ForEachStatement *node = new (pool) AST::ForEachStatement(sym(3).Expression, sym(5).Expression, sym(7).Statement); node->forToken = loc(1); node->lparenToken = loc(2); node->inToken = loc(4); node->rparenToken = loc(6); sym(1).Node = node; } break; case 296: { AST::LocalForEachStatement *node = new (pool) AST::LocalForEachStatement( sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); node->forToken = loc(1); node->lparenToken = loc(2); node->varToken = loc(3); node->inToken = loc(5); node->rparenToken = loc(7); sym(1).Node = node; } break; case 298: { AST::ContinueStatement *node = new (pool) AST::ContinueStatement(); node->continueToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; case 300: { AST::ContinueStatement *node = new (pool) AST::ContinueStatement(stringRef(2)); node->continueToken = loc(1); node->identifierToken = loc(2); node->semicolonToken = loc(3); sym(1).Node = node; } break; case 302: { AST::BreakStatement *node = new (pool) AST::BreakStatement(QStringRef()); node->breakToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; case 304: { AST::BreakStatement *node = new (pool) AST::BreakStatement(stringRef(2)); node->breakToken = loc(1); node->identifierToken = loc(2); node->semicolonToken = loc(3); sym(1).Node = node; } break; case 306: { AST::ReturnStatement *node = new (pool) AST::ReturnStatement(sym(2).Expression); node->returnToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; case 307: { AST::WithStatement *node = new (pool) AST::WithStatement(sym(3).Expression, sym(5).Statement); node->withToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; case 308: { AST::SwitchStatement *node = new (pool) AST::SwitchStatement(sym(3).Expression, sym(5).CaseBlock); node->switchToken = loc(1); node->lparenToken = loc(2); node->rparenToken = loc(4); sym(1).Node = node; } break; case 309: { AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(3); sym(1).Node = node; } break; case 310: { AST::CaseBlock *node = new (pool) AST::CaseBlock(sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); node->lbraceToken = loc(1); node->rbraceToken = loc(5); sym(1).Node = node; } break; case 311: { sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClause); } break; case 312: { sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClauses, sym(2).CaseClause); } break; case 313: { sym(1).Node = 0; } break; case 314: { sym(1).Node = sym(1).CaseClauses->finish (); } break; case 315: { AST::CaseClause *node = new (pool) AST::CaseClause(sym(2).Expression, sym(4).StatementList); node->caseToken = loc(1); node->colonToken = loc(3); sym(1).Node = node; } break; case 316: { AST::DefaultClause *node = new (pool) AST::DefaultClause(sym(3).StatementList); node->defaultToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; case 317: case 318: { AST::LabelledStatement *node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; case 319: { AST::LabelledStatement *node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement); node->identifierToken = loc(1); node->colonToken = loc(2); sym(1).Node = node; } break; case 321: { AST::ThrowStatement *node = new (pool) AST::ThrowStatement(sym(2).Expression); node->throwToken = loc(1); node->semicolonToken = loc(3); sym(1).Node = node; } break; case 322: { AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch); node->tryToken = loc(1); sym(1).Node = node; } break; case 323: { AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; case 324: { AST::TryStatement *node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch, sym(4).Finally); node->tryToken = loc(1); sym(1).Node = node; } break; case 325: { AST::Catch *node = new (pool) AST::Catch(stringRef(3), sym(5).Block); node->catchToken = loc(1); node->lparenToken = loc(2); node->identifierToken = loc(3); node->rparenToken = loc(4); sym(1).Node = node; } break; case 326: { AST::Finally *node = new (pool) AST::Finally(sym(2).Block); node->finallyToken = loc(1); sym(1).Node = node; } break; case 328: { AST::DebuggerStatement *node = new (pool) AST::DebuggerStatement(); node->debuggerToken = loc(1); node->semicolonToken = loc(2); sym(1).Node = node; } break; case 329: { AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); node->identifierToken = loc(2); node->lparenToken = loc(3); node->rparenToken = loc(5); node->lbraceToken = loc(6); node->rbraceToken = loc(8); sym(1).Node = node; } break; case 330: { AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody); node->functionToken = loc(1); if (! stringRef(2).isNull()) node->identifierToken = loc(2); node->lparenToken = loc(3); node->rparenToken = loc(5); node->lbraceToken = loc(6); node->rbraceToken = loc(8); sym(1).Node = node; } break; case 331: { AST::FormalParameterList *node = new (pool) AST::FormalParameterList(stringRef(1)); node->identifierToken = loc(1); sym(1).Node = node; } break; case 332: { AST::FormalParameterList *node = new (pool) AST::FormalParameterList(sym(1).FormalParameterList, stringRef(3)); node->commaToken = loc(2); node->identifierToken = loc(3); sym(1).Node = node; } break; case 333: { sym(1).Node = 0; } break; case 334: { sym(1).Node = sym(1).FormalParameterList->finish (); } break; case 335: { sym(1).Node = 0; } break; case 337: { sym(1).Node = new (pool) AST::FunctionBody(sym(1).SourceElements->finish ()); } break; case 339: { sym(1).Node = new (pool) AST::Program(sym(1).SourceElements->finish ()); } break; case 340: { sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElement); } break; case 341: { sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElements, sym(2).SourceElement); } break; case 342: { sym(1).Node = new (pool) AST::StatementSourceElement(sym(1).Statement); } break; case 343: { sym(1).Node = new (pool) AST::FunctionSourceElement(sym(1).FunctionDeclaration); } break; case 344: { stringRef(1) = QStringRef(); } break; case 346: { sym(1).Node = 0; } break; } // switch action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT); } // if } while (action != 0); if (first_token == last_token) { const int errorState = state_stack[tos]; // automatic insertion of `;' if (yytoken != -1 && t_action(errorState, T_AUTOMATIC_SEMICOLON) && lexer->canInsertAutomaticSemicolon(yytoken)) { SavedToken &tk = token_buffer[0]; tk.token = yytoken; tk.dval = yylval; tk.spell = yytokenspell; tk.loc = yylloc; yylloc = yyprevlloc; yylloc.offset += yylloc.length; yylloc.startColumn += yylloc.length; yylloc.length = 0; //const QString msg = qApp->translate("QmlParser", "Missing `;'"); //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg)); first_token = &token_buffer[0]; last_token = &token_buffer[1]; yytoken = T_SEMICOLON; yylval = 0; action = errorState; goto _Lcheck_token; } hadErrors = true; token_buffer[0].token = yytoken; token_buffer[0].dval = yylval; token_buffer[0].spell = yytokenspell; token_buffer[0].loc = yylloc; token_buffer[1].token = yytoken = lexer->lex(); token_buffer[1].dval = yylval = lexer->tokenValue(); token_buffer[1].spell = yytokenspell = lexer->tokenSpell(); token_buffer[1].loc = yylloc = location(lexer); if (t_action(errorState, yytoken)) { QString msg; int token = token_buffer[0].token; if (token < 0 || token >= TERMINAL_COUNT) msg = qApp->translate("QmlParser", "Syntax error"); else msg = qApp->translate("QmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); action = errorState; goto _Lcheck_token; } static int tokens[] = { T_PLUS, T_EQ, T_COMMA, T_COLON, T_SEMICOLON, T_RPAREN, T_RBRACKET, T_RBRACE, T_NUMERIC_LITERAL, T_IDENTIFIER, T_LPAREN, T_LBRACKET, T_LBRACE, EOF_SYMBOL }; for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) { int a = t_action(errorState, *tk); if (a > 0 && t_action(a, yytoken)) { const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[*tk])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); yytoken = *tk; yylval = 0; yylloc = token_buffer[0].loc; yylloc.length = 0; first_token = &token_buffer[0]; last_token = &token_buffer[2]; action = errorState; goto _Lcheck_token; } } for (int tk = 1; tk < TERMINAL_COUNT; ++tk) { if (tk == T_AUTOMATIC_SEMICOLON || tk == T_FEED_UI_PROGRAM || tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION || tk == T_FEED_JS_SOURCE_ELEMENT) continue; int a = t_action(errorState, tk); if (a > 0 && t_action(a, yytoken)) { const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[tk])); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); yytoken = tk; yylval = 0; yylloc = token_buffer[0].loc; yylloc.length = 0; action = errorState; goto _Lcheck_token; } } const QString msg = qApp->translate("QmlParser", "Syntax error"); diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); } return false; } } // namespace QbsQmlJS qbs-src-1.4.5/src/lib/corelib/parser/qmljsparser_p.h000066400000000000000000000150151266132464200224060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // // // This file is automatically generated from qmljs.g. // Changes will be lost. // #ifndef QMLJSPARSER_P_H #define QMLJSPARSER_P_H #include "qmljsglobal_p.h" #include "qmljsgrammar_p.h" #include "qmljsast_p.h" #include "qmljsengine_p.h" #include #include namespace QbsQmlJS { class Engine; class QML_PARSER_EXPORT Parser: protected QmlJSGrammar { public: union Value { int ival; double dval; AST::ArgumentList *ArgumentList; AST::CaseBlock *CaseBlock; AST::CaseClause *CaseClause; AST::CaseClauses *CaseClauses; AST::Catch *Catch; AST::DefaultClause *DefaultClause; AST::ElementList *ElementList; AST::Elision *Elision; AST::ExpressionNode *Expression; AST::Finally *Finally; AST::FormalParameterList *FormalParameterList; AST::FunctionBody *FunctionBody; AST::FunctionDeclaration *FunctionDeclaration; AST::Node *Node; AST::PropertyName *PropertyName; AST::PropertyNameAndValueList *PropertyNameAndValueList; AST::SourceElement *SourceElement; AST::SourceElements *SourceElements; AST::Statement *Statement; AST::StatementList *StatementList; AST::Block *Block; AST::VariableDeclaration *VariableDeclaration; AST::VariableDeclarationList *VariableDeclarationList; AST::UiProgram *UiProgram; AST::UiImportList *UiImportList; AST::UiImport *UiImport; AST::UiParameterList *UiParameterList; AST::UiPublicMember *UiPublicMember; AST::UiObjectDefinition *UiObjectDefinition; AST::UiObjectInitializer *UiObjectInitializer; AST::UiObjectBinding *UiObjectBinding; AST::UiScriptBinding *UiScriptBinding; AST::UiArrayBinding *UiArrayBinding; AST::UiObjectMember *UiObjectMember; AST::UiObjectMemberList *UiObjectMemberList; AST::UiArrayMemberList *UiArrayMemberList; AST::UiQualifiedId *UiQualifiedId; }; public: Parser(Engine *engine); ~Parser(); // parse a UI program bool parse() { return parse(T_FEED_UI_PROGRAM); } bool parseStatement() { return parse(T_FEED_JS_STATEMENT); } bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); } bool parseSourceElement() { return parse(T_FEED_JS_SOURCE_ELEMENT); } bool parseUiObjectMember() { return parse(T_FEED_UI_OBJECT_MEMBER); } bool parseProgram() { return parse(T_FEED_JS_PROGRAM); } AST::UiProgram *ast() const { return AST::cast(program); } AST::Statement *statement() const { if (! program) return 0; return program->statementCast(); } AST::ExpressionNode *expression() const { if (! program) return 0; return program->expressionCast(); } AST::UiObjectMember *uiObjectMember() const { if (! program) return 0; return program->uiObjectMemberCast(); } AST::Node *rootNode() const { return program; } QList diagnosticMessages() const { return diagnostic_messages; } inline DiagnosticMessage diagnosticMessage() const { foreach (const DiagnosticMessage &d, diagnostic_messages) { if (d.kind != DiagnosticMessage::Warning) return d; } return DiagnosticMessage(); } inline QString errorMessage() const { return diagnosticMessage().message; } inline int errorLineNumber() const { return diagnosticMessage().loc.startLine; } inline int errorColumnNumber() const { return diagnosticMessage().loc.startColumn; } protected: bool parse(int startToken); void reallocateStack(); inline Value &sym(int index) { return sym_stack [tos + index - 1]; } inline QStringRef &stringRef(int index) { return string_stack [tos + index - 1]; } inline AST::SourceLocation &loc(int index) { return location_stack [tos + index - 1]; } AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr); protected: Engine *driver; MemoryPool *pool; int tos; int stack_size; Value *sym_stack; int *state_stack; AST::SourceLocation *location_stack; QStringRef *string_stack; AST::Node *program; // error recovery enum { TOKEN_BUFFER_SIZE = 3 }; struct SavedToken { int token; double dval; AST::SourceLocation loc; QStringRef spell; }; double yylval; QStringRef yytokenspell; AST::SourceLocation yylloc; AST::SourceLocation yyprevlloc; SavedToken token_buffer[TOKEN_BUFFER_SIZE]; SavedToken *first_token; SavedToken *last_token; QList diagnostic_messages; }; } // end of namespace QbsQmlJS #define J_SCRIPT_REGEXPLITERAL_RULE1 79 #define J_SCRIPT_REGEXPLITERAL_RULE2 80 #endif // QMLJSPARSER_P_H qbs-src-1.4.5/src/lib/corelib/qbs.h000066400000000000000000000041111266132464200170100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_H #define QBS_H #include "api/jobs.h" #include "api/languageinfo.h" #include "api/project.h" #include "api/projectdata.h" #include "api/rulecommand.h" #include "logging/ilogsink.h" #include "tools/architectures.h" #include "tools/buildoptions.h" #include "tools/cleanoptions.h" #include "tools/error.h" #include "tools/generateoptions.h" #include "tools/installoptions.h" #include "tools/preferences.h" #include "tools/profile.h" #include "tools/processresult.h" #include "tools/settings.h" #include "tools/settingsmodel.h" #include "tools/setupprojectparameters.h" #endif // QBS_H qbs-src-1.4.5/src/lib/corelib/tools/000077500000000000000000000000001266132464200172155ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/corelib/tools/architectures.cpp000066400000000000000000000062431266132464200225730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "architectures.h" #include #include #include namespace qbs { QString canonicalArchitecture(const QString &architecture) { QMap archMap; archMap.insert(QLatin1String("x86"), QStringList() << QLatin1String("i386") << QLatin1String("i486") << QLatin1String("i586") << QLatin1String("i686") << QLatin1String("ia32") << QLatin1String("ia-32") << QLatin1String("x86_32") << QLatin1String("x86-32") << QLatin1String("intel32") << QLatin1String("mingw32")); archMap.insert(QLatin1String("x86_64"), QStringList() << QLatin1String("x86-64") << QLatin1String("x64") << QLatin1String("amd64") << QLatin1String("ia32e") << QLatin1String("em64t") << QLatin1String("intel64") << QLatin1String("mingw64")); archMap.insert(QLatin1String("arm64"), QStringList() << QLatin1String("aarch64")); archMap.insert(QLatin1String("ia64"), QStringList() << QLatin1String("ia-64") << QLatin1String("itanium")); archMap.insert(QLatin1String("ppc"), QStringList() << QLatin1String("powerpc")); archMap.insert(QLatin1String("ppc64"), QStringList() << QLatin1String("powerpc64")); archMap.insert(QLatin1String("ppc64le"), QStringList() << QLatin1String("powerpc64le")); QMapIterator i(archMap); while (i.hasNext()) { i.next(); if (i.value().contains(architecture.toLower())) return i.key(); } return architecture; } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/architectures.h000066400000000000000000000033151266132464200222350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_ARCHITECTURES_H #define QBS_ARCHITECTURES_H #include "qbs_export.h" namespace qbs { QBS_EXPORT QString canonicalArchitecture(const QString &architecture); } // namespace qbs #endif // Include guard. qbs-src-1.4.5/src/lib/corelib/tools/buildgraphlocker.cpp000066400000000000000000000117301266132464200232440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "buildgraphlocker.h" #include "error.h" #include "processutils.h" #include "version.h" #include #include #include #include #include namespace qbs { namespace Internal { static bool hasQtBug45497() { return Version::fromString(QLatin1String(qVersion())) < Version(5, 5, 1); } BuildGraphLocker::BuildGraphLocker(const QString &buildGraphFilePath, const Logger &logger) : m_lockFile(buildGraphFilePath + QLatin1String(".lock")) , m_logger(logger) { const QString buildDir = QFileInfo(buildGraphFilePath).absolutePath(); rememberCreatedDirectories(buildDir); if (!QDir::root().mkpath(buildDir)) { throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1': Failed to create directory.") .arg(buildGraphFilePath)); } m_lockFile.setStaleLockTime(0); int attemptsToGetInfo = 0; do { if (m_lockFile.tryLock(250)) return; switch (m_lockFile.error()) { case QLockFile::LockFailedError: { qint64 pid; QString hostName; QString appName; if (m_lockFile.getLockInfo(&pid, &hostName, &appName)) { if (!hasQtBug45497() || appName == processNameByPid(pid)) { throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1': " "Already locked by '%2' (PID %3).") .arg(buildGraphFilePath, appName).arg(pid)); } // The process id was reused by some other process. m_logger.qbsInfo() << Tr::tr("Removing stale lock file."); m_lockFile.removeStaleLockFile(); } break; } case QLockFile::PermissionError: throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1': Permission denied.") .arg(buildGraphFilePath)); case QLockFile::UnknownError: case QLockFile::NoError: throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1' (reason unknown).") .arg(buildGraphFilePath)); } } while (++attemptsToGetInfo < 10); // This very unlikely case arises if tryLock() repeatedly returns LockFailedError // with the subsequent getLockInfo() failing as well. throw ErrorInfo(Tr::tr("Cannot lock build graph file '%1' (reason unknown).") .arg(buildGraphFilePath)); } BuildGraphLocker::~BuildGraphLocker() { m_lockFile.unlock(); removeEmptyCreatedDirectories(); } void BuildGraphLocker::rememberCreatedDirectories(const QString &buildDir) { QString parentDir = buildDir; while (!QFileInfo::exists(parentDir)) { m_createdParentDirs.enqueue(parentDir); parentDir = QDir::cleanPath(parentDir + QLatin1String("/..")); } } void BuildGraphLocker::removeEmptyCreatedDirectories() { QDir root = QDir::root(); while (!m_createdParentDirs.isEmpty()) { const QString parentDir = m_createdParentDirs.dequeue(); QDirIterator it(parentDir, QDir::AllEntries | QDir::NoDotAndDotDot | QDir::System, QDirIterator::Subdirectories); if (it.hasNext()) break; if (!root.rmdir(parentDir)) { m_logger.printWarning(ErrorInfo(Tr::tr("Failed to remove empty directory '%1'.") .arg(parentDir))); } } } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/buildgraphlocker.h000066400000000000000000000041311266132464200227060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_BUILDGRAPHLOCKER_H #define QBS_BUILDGRAPHLOCKER_H #include #include #include #include namespace qbs { namespace Internal { class BuildGraphLocker { public: explicit BuildGraphLocker(const QString &buildGraphFilePath, const Logger &logger); ~BuildGraphLocker(); private: void rememberCreatedDirectories(const QString &buildDir); void removeEmptyCreatedDirectories(); QLockFile m_lockFile; Logger m_logger; QQueue m_createdParentDirs; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.4.5/src/lib/corelib/tools/buildoptions.cpp000066400000000000000000000216521266132464200224420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "buildoptions.h" #include #include namespace qbs { namespace Internal { class BuildOptionsPrivate : public QSharedData { public: BuildOptionsPrivate() : maxJobCount(0), dryRun(false), keepGoing(false), forceTimestampCheck(false), logElapsedTime(false), echoMode(defaultCommandEchoMode()), install(true), removeExistingInstallation(false) { } QStringList changedFiles; QStringList filesToConsider; QStringList activeFileTags; int maxJobCount; bool dryRun; bool keepGoing; bool forceTimestampCheck; bool logElapsedTime; CommandEchoMode echoMode; bool install; bool removeExistingInstallation; }; } // namespace Internal /*! * \class BuildOptions * \brief The \c BuildOptions class comprises parameters that influence the behavior of * build and clean operations. */ /*! * \brief Creates a \c BuildOptions object and initializes its members to sensible default values. */ BuildOptions::BuildOptions() : d(new Internal::BuildOptionsPrivate) { } BuildOptions::BuildOptions(const BuildOptions &other) : d(other.d) { } BuildOptions &BuildOptions::operator=(const BuildOptions &other) { d = other.d; return *this; } BuildOptions::~BuildOptions() { } /*! * \brief If non-empty, qbs pretends that only these files have changed. * By default, this list is empty. */ QStringList BuildOptions::changedFiles() const { return d->changedFiles; } /*! * \brief If the given list is empty, qbs will pretend only the listed files are changed. * \note The list elements must be absolute file paths. */ void BuildOptions::setChangedFiles(const QStringList &changedFiles) { d->changedFiles = changedFiles; } /*! * \brief The list of files to consider. * \sa setFilesToConsider. * By default, this list is empty. */ QStringList BuildOptions::filesToConsider() const { return d->filesToConsider; } /*! * \brief If the given list is non-empty, qbs will run only commands whose rule has at least one * of these files as an input. * \note The list elements must be absolute file paths. */ void BuildOptions::setFilesToConsider(const QStringList &files) { d->filesToConsider = files; } /*! * \brief The list of active file tags. * \sa setActiveFileTags */ QStringList BuildOptions::activeFileTags() const { return d->activeFileTags; } /*! * \brief Set the list of active file tags. * If this list is non-empty, then every transformer with non-matching output file tags is skipped. * E.g. call \c setFilesToConsider() with "foo.cpp" and \c setActiveFileTags() with "obj" to * run the compiler on foo.cpp without further processing like linking. * \sa activeFileTags */ void BuildOptions::setActiveFileTags(const QStringList &fileTags) { d->activeFileTags = fileTags; } /*! * \brief Returns the default value for \c maxJobCount. * This value will be used when \c maxJobCount has not been set explicitly. */ int BuildOptions::defaultMaxJobCount() { return QThread::idealThreadCount(); } /*! * \brief Returns the maximum number of build commands to run concurrently. * If the value is not valid (i.e. <= 0), a sensible one will be derived at build time * from the number of available processor cores at build time. * The default is 0. * \sa BuildOptions::defaultMaxJobCount */ int BuildOptions::maxJobCount() const { return d->maxJobCount; } /*! * \brief Controls how many build commands can be run in parallel. * A value <= 0 leaves the decision to qbs. */ void BuildOptions::setMaxJobCount(int jobCount) { d->maxJobCount = jobCount; } /*! * \brief Returns true iff qbs will not actually execute any commands, but just show what * would happen. * The default is false. */ bool BuildOptions::dryRun() const { return d->dryRun; } /*! * \brief Controls whether qbs will actually build something. * If the argument is true, qbs will just emit information about what it would do. Otherwise, * the build is actually done. * \note After you build with this setting enabled, the next call to \c build() on the same * \c Project object will do nothing, since the internal state needs to be updated the same way * as if an actual build had happened. You'll need to create a new \c Project object to do * a real build afterwards. */ void BuildOptions::setDryRun(bool dryRun) { d->dryRun = dryRun; } /*! * \brief Returns true iff a build will continue after an error. * E.g. a failed compile command will result in a warning message being printed, instead of * stopping the build process right away. However, there might still be fatal errors after which the * build process cannot continue. * The default is \c false. */ bool BuildOptions::keepGoing() const { return d->keepGoing; } /*! * \brief Controls whether a qbs will try to continue building after an error has occurred. */ void BuildOptions::setKeepGoing(bool keepGoing) { d->keepGoing = keepGoing; } /*! * \brief Returns true if qbs is to use physical timestamps instead of the timestamps stored in the * build graph. * The default is \c false. */ bool BuildOptions::forceTimestampCheck() const { return d->forceTimestampCheck; } /*! * \brief Controls whether qbs should use physical timestamps for up-to-date checks. */ void BuildOptions::setForceTimestampCheck(bool enabled) { d->forceTimestampCheck = enabled; } /*! * \brief Returns true iff the time the operation takes will be logged. * The default is \c false. */ bool BuildOptions::logElapsedTime() const { return d->logElapsedTime; } /*! * \brief Controls whether the build time will be measured and logged. */ void BuildOptions::setLogElapsedTime(bool log) { d->logElapsedTime = log; } /*! * \brief The kind of output that is displayed when executing commands. */ CommandEchoMode BuildOptions::echoMode() const { return d->echoMode; } /*! * \brief Controls the kind of output that is displayed when executing commands. */ void BuildOptions::setEchoMode(CommandEchoMode echoMode) { d->echoMode = echoMode; } /*! * \brief Returns true iff installation should happen as part of the build. * The default is \c true. */ bool BuildOptions::install() const { return d->install; } /*! * \brief Controls whether to install artifacts as part of the build process. */ void BuildOptions::setInstall(bool install) { d->install = install; } /*! * \brief Returns true iff an existing installation will be removed prior to building. * The default is false. */ bool BuildOptions::removeExistingInstallation() const { return d->removeExistingInstallation; } /*! * Controls whether to remove an existing installation before installing. * \note qbs may do some safety checks and refuse to remove certain directories such as * a user's home directory. You should still be careful with this option, since it * deletes recursively. */ void BuildOptions::setRemoveExistingInstallation(bool removeExisting) { d->removeExistingInstallation = removeExisting; } bool operator==(const BuildOptions &bo1, const BuildOptions &bo2) { return bo1.changedFiles() == bo2.changedFiles() && bo1.dryRun() == bo2.dryRun() && bo1.keepGoing() == bo2.keepGoing() && bo1.logElapsedTime() == bo2.logElapsedTime() && bo1.echoMode() == bo2.echoMode() && bo1.maxJobCount() == bo2.maxJobCount() && bo1.install() == bo2.install() && bo1.removeExistingInstallation() == bo2.removeExistingInstallation(); } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/buildoptions.h000066400000000000000000000061351266132464200221060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_BUILDOPTIONS_H #define QBS_BUILDOPTIONS_H #include "qbs_export.h" #include "commandechomode.h" #include #include namespace qbs { namespace Internal { class BuildOptionsPrivate; } class QBS_EXPORT BuildOptions { public: BuildOptions(); BuildOptions(const BuildOptions &other); BuildOptions &operator=(const BuildOptions &other); ~BuildOptions(); QStringList filesToConsider() const; void setFilesToConsider(const QStringList &files); QStringList changedFiles() const; void setChangedFiles(const QStringList &changedFiles); QStringList activeFileTags() const; void setActiveFileTags(const QStringList &fileTags); static int defaultMaxJobCount(); int maxJobCount() const; void setMaxJobCount(int jobCount); bool dryRun() const; void setDryRun(bool dryRun); bool keepGoing() const; void setKeepGoing(bool keepGoing); bool forceTimestampCheck() const; void setForceTimestampCheck(bool enabled); bool logElapsedTime() const; void setLogElapsedTime(bool log); CommandEchoMode echoMode() const; void setEchoMode(CommandEchoMode echoMode); bool install() const; void setInstall(bool install); bool removeExistingInstallation() const; void setRemoveExistingInstallation(bool removeExisting); private: QSharedDataPointer d; }; bool operator==(const BuildOptions &bo1, const BuildOptions &bo2); inline bool operator!=(const BuildOptions &bo1, const BuildOptions &bo2) { return !(bo1 == bo2); } } // namespace qbs #endif // QBS_BUILDOPTIONS_H qbs-src-1.4.5/src/lib/corelib/tools/cleanoptions.cpp000066400000000000000000000107241266132464200224230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "cleanoptions.h" #include namespace qbs { namespace Internal { class CleanOptionsPrivate : public QSharedData { public: CleanOptionsPrivate() : cleanType(CleanOptions::CleanupAll), dryRun(false), keepGoing(false), logElapsedTime(false) { } CleanOptions::CleanType cleanType; bool dryRun; bool keepGoing; bool logElapsedTime; }; } /*! * \class CleanOptions * \brief The \c CleanOptions class comprises parameters that influence the behavior of * cleaning operations. */ /*! * \enum CleanOptions::CleanType * This enum type specifies which kind of build artifacts to remove. * \value CleanupAll Indicates that all files created by the build process should be removed. * \value CleanupTemporaries Indicates that only intermediate build artifacts should be removed. * If, for example, the product to clean up for is a Linux shared library, the .so file * would be left on the disk, but the .o files would be removed. */ CleanOptions::CleanOptions() : d(new Internal::CleanOptionsPrivate) { } CleanOptions::CleanOptions(const CleanOptions &other) : d(other.d) { } CleanOptions &CleanOptions::operator=(const CleanOptions &other) { d = other.d; return *this; } CleanOptions::~CleanOptions() { } /*! * \brief Returns information about which type of artifacts will be removed. */ CleanOptions::CleanType CleanOptions::cleanType() const { return d->cleanType; } /*! * \brief Controls which kind of artifacts to remove. * \sa CleanOptions::CleanType */ void CleanOptions::setCleanType(CleanOptions::CleanType cleanType) { d->cleanType = cleanType; } /*! * \brief Returns true iff qbs will not actually remove any files, but just show what would happen. * The default is false. */ bool CleanOptions::dryRun() const { return d->dryRun; } /*! * \brief Controls whether clean-up will actually take place. * If the argument is true, then qbs will emit information about which files would be removed * instead of actually doing it. */ void CleanOptions::setDryRun(bool dryRun) { d->dryRun = dryRun; } /*! * Returns true iff clean-up will continue if an error occurs. * The default is false. */ bool CleanOptions::keepGoing() const { return d->keepGoing; } /*! * \brief Controls whether to abort on errors. * If the argument is true, then if a file cannot be removed e.g. due to a permission problem, * a warning will be printed and the clean-up will continue. If the argument is false, * then the clean-up will abort immediately in case of an error. */ void CleanOptions::setKeepGoing(bool keepGoing) { d->keepGoing = keepGoing; } /*! * \brief Returns true iff the time the operation takes will be logged. * The default is false. */ bool CleanOptions::logElapsedTime() const { return d->logElapsedTime; } /*! * \brief Controls whether the clean-up time will be measured and logged. */ void CleanOptions::setLogElapsedTime(bool log) { d->logElapsedTime = log; } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/cleanoptions.h000066400000000000000000000044571266132464200220760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_CLEANOPTIONS_H #define QBS_CLEANOPTIONS_H #include "qbs_export.h" #include #include namespace qbs { namespace Internal { class CleanOptionsPrivate; } class QBS_EXPORT CleanOptions { public: CleanOptions(); CleanOptions(const CleanOptions &other); CleanOptions &operator=(const CleanOptions &other); ~CleanOptions(); enum CleanType { CleanupAll, CleanupTemporaries }; CleanType cleanType() const; void setCleanType(CleanType cleanType); bool dryRun() const; void setDryRun(bool dryRun); bool keepGoing() const; void setKeepGoing(bool keepGoing); bool logElapsedTime() const; void setLogElapsedTime(bool log); private: QSharedDataPointer d; }; } // namespace qbs #endif // Include guard qbs-src-1.4.5/src/lib/corelib/tools/codelocation.cpp000066400000000000000000000102341266132464200223640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "codelocation.h" #include #include #include #include #include #include #include #include namespace qbs { class CodeLocation::CodeLocationPrivate : public QSharedData { public: QString filePath; int line; int column; }; CodeLocation::CodeLocation() { } CodeLocation::CodeLocation(const QString &aFilePath, int aLine, int aColumn, bool checkPath) : d(new CodeLocationPrivate) { QBS_ASSERT(!checkPath || Internal::FileInfo::isAbsolute(aFilePath), qDebug() << aFilePath); d->filePath = aFilePath; d->line = aLine; d->column = aColumn; } CodeLocation::CodeLocation(const CodeLocation &other) : d(other.d) { } CodeLocation &CodeLocation::operator=(const CodeLocation &other) { d = other.d; return *this; } CodeLocation::~CodeLocation() { } QString CodeLocation::filePath() const { return d ? d->filePath : QString(); } int CodeLocation::line() const { return d ? d->line : -1; } int CodeLocation::column() const { return d ? d->column : -1; } bool CodeLocation::isValid() const { return !filePath().isEmpty(); } QString CodeLocation::toString() const { QString str; if (isValid()) { str = QDir::toNativeSeparators(filePath()); QString lineAndColumn; if (line() > 0 && !str.contains(QRegExp(QLatin1String(":[0-9]+$")))) lineAndColumn += QLatin1Char(':') + QString::number(line()); if (column() > 0 && !str.contains(QRegExp(QLatin1String(":[0-9]+:[0-9]+$")))) lineAndColumn += QLatin1Char(':') + QString::number(column()); str += lineAndColumn; } return str; } void CodeLocation::load(Internal::PersistentPool &pool) { int isValid; pool.stream() >> isValid; if (!isValid) return; d = new CodeLocationPrivate; d->filePath = pool.idLoadString(); pool.stream() >> d->line; pool.stream() >> d->column; } void CodeLocation::store(Internal::PersistentPool &pool) const { if (d) { pool.stream() << 1; pool.storeString(d->filePath); pool.stream() << d->line; pool.stream() << d->column; } else { pool.stream() << 0; } } bool operator==(const CodeLocation &cl1, const CodeLocation &cl2) { if (cl1.d == cl2.d) return true; return cl1.filePath() == cl2.filePath() && cl1.line() == cl2.line() && cl1.column() == cl2.column(); } bool operator!=(const CodeLocation &cl1, const CodeLocation &cl2) { return !(cl1 == cl2); } QDebug operator<<(QDebug debug, const CodeLocation &location) { return debug << location.toString(); } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/codelocation.h000066400000000000000000000053401266132464200220330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_SOURCELOCATION_H #define QBS_SOURCELOCATION_H #include "qbs_export.h" #include #include QT_BEGIN_NAMESPACE class QDataStream; class QString; QT_END_NAMESPACE namespace qbs { namespace Internal { class PersistentPool; } class QBS_EXPORT CodeLocation { friend QBS_EXPORT bool operator==(const CodeLocation &cl1, const CodeLocation &cl2); public: CodeLocation(); CodeLocation(const QString &aFilePath, int aLine = -1, int aColumn = -1, bool checkPath = true); CodeLocation(const CodeLocation &other); CodeLocation &operator=(const CodeLocation &other); ~CodeLocation(); QString filePath() const; int line() const; int column() const; bool isValid() const; QString toString() const; void load(Internal::PersistentPool &pool); void store(Internal::PersistentPool &pool) const; private: class CodeLocationPrivate; QExplicitlySharedDataPointer d; }; QBS_EXPORT bool operator==(const CodeLocation &cl1, const CodeLocation &cl2); QBS_EXPORT bool operator!=(const CodeLocation &cl1, const CodeLocation &cl2); QDebug operator<<(QDebug debug, const CodeLocation &location); } // namespace qbs #endif // QBS_SOURCELOCATION_H qbs-src-1.4.5/src/lib/corelib/tools/commandechomode.cpp000066400000000000000000000056661266132464200230600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "commandechomode.h" /*! * \enum CommandEchoMode * This enum type specifies the kind of output to display when executing commands. * \value CommandEchoModeSilent Indicates that no output will be printed. * \value CommandEchoModeSummary Indicates that descriptions will be printed. * \value CommandEchoModeCommandLine Indidcates that full command line invocations will be printed. */ namespace qbs { CommandEchoMode defaultCommandEchoMode() { return CommandEchoModeSummary; } QString commandEchoModeName(CommandEchoMode mode) { switch (mode) { case CommandEchoModeSilent: return QLatin1String("silent"); case CommandEchoModeSummary: return QLatin1String("summary"); case CommandEchoModeCommandLine: return QLatin1String("command-line"); default: break; } return QString(); } CommandEchoMode commandEchoModeFromName(const QString &name) { CommandEchoMode mode = defaultCommandEchoMode(); for (int i = 0; i <= static_cast(CommandEchoModeLast); ++i) { if (commandEchoModeName(static_cast(i)) == name) { mode = static_cast(i); break; } } return mode; } QStringList allCommandEchoModeStrings() { QStringList result; for (int i = 0; i <= static_cast(CommandEchoModeLast); ++i) result << commandEchoModeName(static_cast(i)); return result; } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/commandechomode.h000066400000000000000000000041201266132464200225050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_COMMANDECHOMODE_H #define QBS_COMMANDECHOMODE_H #include "qbs_export.h" #include #include namespace qbs { enum CommandEchoMode { CommandEchoModeSilent, CommandEchoModeSummary, CommandEchoModeCommandLine, CommandEchoModeLast = CommandEchoModeCommandLine }; QBS_EXPORT CommandEchoMode defaultCommandEchoMode(); QBS_EXPORT QString commandEchoModeName(CommandEchoMode mode); QBS_EXPORT CommandEchoMode commandEchoModeFromName(const QString &name); QBS_EXPORT QStringList allCommandEchoModeStrings(); } // namespace qbs #endif // QBS_COMMANDECHOMODE_H qbs-src-1.4.5/src/lib/corelib/tools/error.cpp000066400000000000000000000116051266132464200210550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "error.h" #include #include namespace qbs { class ErrorItem::ErrorItemPrivate : public QSharedData { public: QString description; CodeLocation codeLocation; }; /*! * \class ErrorData * \brief The \c ErrorData class describes (part of) an error resulting from a qbs operation. * It is always delivered as part of an \c Error. * \sa Error */ ErrorItem::ErrorItem() : d(new ErrorItemPrivate) { } ErrorItem::ErrorItem(const QString &description, const CodeLocation &codeLocation) : d(new ErrorItemPrivate) { d->description = description; d->codeLocation = codeLocation; } ErrorItem::ErrorItem(const ErrorItem &rhs) : d(rhs.d) { } ErrorItem &ErrorItem::operator=(const ErrorItem &other) { d = other.d; return *this; } ErrorItem::~ErrorItem() { } QString ErrorItem::description() const { return d->description; } CodeLocation ErrorItem::codeLocation() const { return d->codeLocation; } /*! * \fn const QString &ErrorData::description() const * \brief A general description of the error. */ /*! * \fn const QString &ErrorData::codeLocation() const * \brief The location at which file in which the error occurred. * \note This information might not be applicable, in which case location().isValid() returns false */ /*! * \brief A full textual description of the error using all available information. */ QString ErrorItem::toString() const { QString str = codeLocation().toString(); if (!str.isEmpty()) str += QLatin1Char(' '); return str += description(); } class ErrorInfo::ErrorInfoPrivate : public QSharedData { public: ErrorInfoPrivate() : internalError(false) { } QList items; bool internalError; }; /*! * \class Error * \brief Represents an error resulting from a qbs operation. * It is made up of one or more \c ErrorData objects. * \sa ErrorData */ ErrorInfo::ErrorInfo() : d(new ErrorInfoPrivate) { } ErrorInfo::ErrorInfo(const ErrorInfo &rhs) : d(rhs.d) { } ErrorInfo::ErrorInfo(const QString &description, const CodeLocation &location, bool internalError) : d(new ErrorInfoPrivate) { append(description, location); d->internalError = internalError; } ErrorInfo &ErrorInfo::operator =(const ErrorInfo &other) { d = other.d; return *this; } ErrorInfo::~ErrorInfo() { } void ErrorInfo::append(const QString &description, const CodeLocation &location) { d->items.append(ErrorItem(description, location)); } void ErrorInfo::prepend(const QString &description, const CodeLocation &location) { d->items.prepend(ErrorItem(description, location)); } /*! * \brief A list of concrete error description. * Most often, there will be one element in this list, but there can be more e.g. to illustrate * how an error condition propagates through several source files. */ QList ErrorInfo::items() const { return d->items; } void ErrorInfo::clear() { d->items.clear(); } /*! * \brief A complete textual description of the error. * All "sub-errors" will be represented. * \sa Error::entries() */ QString ErrorInfo::toString() const { QStringList lines; foreach (const ErrorItem &e, d->items) lines.append(e.toString()); return lines.join(QLatin1Char('\n')); } /*! * \brief Returns true if this error represents a bug in qbs, false otherwise. */ bool ErrorInfo::isInternalError() const { return d->internalError; } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/error.h000066400000000000000000000057721266132464200205320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_ERROR #define QBS_ERROR #include "codelocation.h" #include #include #include #include QT_BEGIN_NAMESPACE class QString; QT_END_NAMESPACE namespace qbs { class CodeLocation; class QBS_EXPORT ErrorItem { friend class ErrorInfo; public: ErrorItem(); ErrorItem(const ErrorItem &rhs); ErrorItem &operator=(const ErrorItem &other); ~ErrorItem(); QString description() const; CodeLocation codeLocation() const; QString toString() const; private: ErrorItem(const QString &description, const CodeLocation &codeLocation); class ErrorItemPrivate; QExplicitlySharedDataPointer d; }; class QBS_EXPORT ErrorInfo { public: ErrorInfo(); ErrorInfo(const ErrorInfo &rhs); ErrorInfo(const QString &description, const CodeLocation &location = CodeLocation(), bool internalError = false); ErrorInfo &operator=(const ErrorInfo &other); ~ErrorInfo(); void append(const QString &description, const CodeLocation &location = CodeLocation()); void prepend(const QString &description, const CodeLocation &location = CodeLocation()); QList items() const; bool hasError() const { return !items().isEmpty(); } void clear(); QString toString() const; bool isInternalError() const; private: class ErrorInfoPrivate; QSharedDataPointer d; }; } // namespace qbs Q_DECLARE_METATYPE(qbs::ErrorInfo) #endif // QBS_ERROR qbs-src-1.4.5/src/lib/corelib/tools/executablefinder.cpp000066400000000000000000000123461266132464200232400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "executablefinder.h" #include "fileinfo.h" #include "hostosinfo.h" #include namespace qbs { namespace Internal { static QStringList populateExecutableSuffixes() { QStringList result; result << QString(); if (HostOsInfo::isWindowsHost()) { result << QLatin1String(".com") << QLatin1String(".exe") << QLatin1String(".bat") << QLatin1String(".cmd"); } return result; } QStringList ExecutableFinder::m_executableSuffixes = populateExecutableSuffixes(); ExecutableFinder::ExecutableFinder(const ResolvedProductPtr &m_product, const QProcessEnvironment &env, const Logger &logger) : m_product(m_product) , m_environment(env) , m_logger(logger) { } QString ExecutableFinder::findExecutable(const QString &path, const QString &workingDirPath) { QString filePath = QDir::fromNativeSeparators(path); //if (FileInfo::fileName(filePath) == filePath) if (!FileInfo::isAbsolute(filePath)) return findInPath(filePath, workingDirPath); else if (HostOsInfo::isWindowsHost()) return findBySuffix(filePath); return filePath; } QString ExecutableFinder::findBySuffix(const QString &filePath) const { QString fullProgramPath = cachedFilePath(filePath); if (!fullProgramPath.isEmpty()) return fullProgramPath; fullProgramPath = filePath; if (m_logger.traceEnabled()) m_logger.qbsTrace() << "[EXEC] looking for executable by suffix " << fullProgramPath; const QString emptyDirectory; candidateCheck(emptyDirectory, fullProgramPath, fullProgramPath); cacheFilePath(filePath, fullProgramPath); return fullProgramPath; } bool ExecutableFinder::candidateCheck(const QString &directory, const QString &program, QString &fullProgramPath) const { for (int i = 0; i < m_executableSuffixes.count(); ++i) { QString candidate = directory + program + m_executableSuffixes.at(i); if (m_logger.traceEnabled()) m_logger.qbsTrace() << "[EXEC] candidate: " << candidate; QFileInfo fi(candidate); if (fi.isFile() && fi.isExecutable()) { fullProgramPath = candidate; return true; } } return false; } QString ExecutableFinder::findInPath(const QString &filePath, const QString &workingDirPath) const { QString fullProgramPath = cachedFilePath(filePath); if (!fullProgramPath.isEmpty()) return fullProgramPath; fullProgramPath = filePath; if (m_logger.traceEnabled()) m_logger.qbsTrace() << "[EXEC] looking for executable in PATH " << fullProgramPath; QStringList pathEnv = m_environment.value(QLatin1String("PATH")) .split(HostOsInfo::pathListSeparator(), QString::SkipEmptyParts); if (HostOsInfo::isWindowsHost()) pathEnv.prepend(QLatin1String(".")); for (int i = 0; i < pathEnv.count(); ++i) { QString directory = pathEnv.at(i); if (directory == QLatin1String(".")) directory = workingDirPath; if (!directory.isEmpty()) { const QChar lastChar = directory.at(directory.count() - 1); if (lastChar != QLatin1Char('/') && lastChar != QLatin1Char('\\')) directory.append(QLatin1Char('/')); } if (candidateCheck(directory, fullProgramPath, fullProgramPath)) break; } cacheFilePath(filePath, fullProgramPath); return fullProgramPath; } QString ExecutableFinder::cachedFilePath(const QString &filePath) const { return m_product ? m_product->cachedExecutablePath(filePath) : QString(); } void ExecutableFinder::cacheFilePath(const QString &filePath, const QString &fullFilePath) const { if (m_product) m_product->cacheExecutablePath(filePath, fullFilePath); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/executablefinder.h000066400000000000000000000052141266132464200227010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_EXECUTABLEFINDER_H #define QBS_EXECUTABLEFINDER_H #include #include #include namespace qbs { namespace Internal { /*! * \brief Helper class for finding an executable in the PATH of the build environment. */ class ExecutableFinder { public: ExecutableFinder(const ResolvedProductPtr &product, const QProcessEnvironment &env, const Logger &logger); QString findExecutable(const QString &path, const QString &workingDirPath); private: static QStringList m_executableSuffixes; QString findBySuffix(const QString &filePath) const; bool candidateCheck(const QString &directory, const QString &program, QString &fullProgramPath) const; QString findInPath(const QString &filePath, const QString &workingDirPath) const; QString cachedFilePath(const QString &filePath) const; void cacheFilePath(const QString &filePaht, const QString &filePath) const; ResolvedProductPtr m_product; const QProcessEnvironment &m_environment; Logger m_logger; }; } // namespace Internal } // namespace qbs #endif // QBS_EXECUTABLEFINDER_H qbs-src-1.4.5/src/lib/corelib/tools/fileinfo.cpp000066400000000000000000000366551266132464200215330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "fileinfo.h" #include #include #include #include #include #include #include #if defined(Q_OS_UNIX) #include #include #include #elif defined(Q_OS_WIN) #include #endif namespace qbs { namespace Internal { QString FileInfo::fileName(const QString &fp) { int last = fp.lastIndexOf(QLatin1Char('/')); if (last < 0) return fp; return fp.mid(last + 1); } QString FileInfo::baseName(const QString &fp) { QString fn = fileName(fp); int dot = fn.indexOf(QLatin1Char('.')); if (dot < 0) return fn; return fn.mid(0, dot); } QString FileInfo::completeBaseName(const QString &fp) { QString fn = fileName(fp); int dot = fn.lastIndexOf(QLatin1Char('.')); if (dot < 0) return fn; return fn.mid(0, dot); } QString FileInfo::path(const QString &fp) { if (fp.isEmpty()) return QString(); if (fp.at(fp.size() - 1) == QLatin1Char('/')) return fp; int last = fp.lastIndexOf(QLatin1Char('/')); if (last < 0) return QLatin1String("."); QString p = QDir::cleanPath(fp.mid(0, last)); if (p.isEmpty() || (HostOsInfo::isWindowsHost() && p.length() == 2 && p.at(0).isLetter() && p.at(1) == QLatin1Char(':'))) { // Make sure we don't return Windows drive roots without an ending slash. // Those paths are considered relative. p.append(QLatin1Char('/')); } return p; } void FileInfo::splitIntoDirectoryAndFileName(const QString &filePath, QString *dirPath, QString *fileName) { int idx = filePath.lastIndexOf(QLatin1Char('/')); if (idx < 0) { dirPath->clear(); *fileName = filePath; return; } *dirPath = filePath.left(idx); *fileName = filePath.mid(idx + 1); } void FileInfo::splitIntoDirectoryAndFileName(const QString &filePath, QStringRef *dirPath, QStringRef *fileName) { int idx = filePath.lastIndexOf(QLatin1Char('/')); if (idx < 0) { dirPath->clear(); *fileName = QStringRef(&filePath); return; } *dirPath = filePath.leftRef(idx); *fileName = filePath.midRef(idx + 1); } bool FileInfo::exists(const QString &fp) { return FileInfo(fp).exists(); } // from creator/src/shared/proparser/ioutils.cpp bool FileInfo::isAbsolute(const QString &path) { const int n = path.size(); if (n == 0) return false; const QChar at0 = path.at(0); if (at0 == QLatin1Char('/')) return true; if (HostOsInfo::isWindowsHost()) { if (at0 == QLatin1Char('\\')) return true; // Unlike QFileInfo, this won't accept a relative path with a drive letter. // Such paths result in a royal mess anyway ... if (n >= 3 && path.at(1) == QLatin1Char(':') && at0.isLetter() && (path.at(2) == QLatin1Char('/') || path.at(2) == QLatin1Char('\\'))) return true; } return false; } bool FileInfo::isPattern(const QString &str) { return isPattern(QStringRef(&str)); } bool FileInfo::isPattern(const QStringRef &str) { for (int i = 0; i < str.size(); ++i) { const QChar ch = str.at(i); if (ch == QLatin1Char('*') || ch == QLatin1Char('?') || ch == QLatin1Char(']') || ch == QLatin1Char('[')) { return true; } } return false; } /** * Concatenates the paths \a base and \a rel. * Base must be an absolute path. * Double dots at the start of \a rel are handled. * This function assumes that both paths are clean, that is they don't contain * double slashes or redundant dot parts. */ QString FileInfo::resolvePath(const QString &base, const QString &rel) { QBS_ASSERT(isAbsolute(base), qDebug("base: %s, rel: %s", qPrintable(base), qPrintable(rel)); return QString()); if (isAbsolute(rel)) return rel; if (rel.size() == 1 && rel.at(0) == QLatin1Char('.')) return base; if (rel.size() == 1 && rel.at(0) == QLatin1Char('~')) return QDir::homePath(); if (rel.startsWith(QLatin1String("~/"))) return QDir::homePath() + rel.mid(1); QString r = base; if (r.endsWith(QLatin1Char('/'))) r.chop(1); QString s = rel; while (s.startsWith(QLatin1String("../"))) { s.remove(0, 3); int idx = r.lastIndexOf(QLatin1Char('/')); if (idx >= 0) r.truncate(idx); } if (s == QLatin1String("..")) { int idx = r.lastIndexOf(QLatin1Char('/')); if (idx >= 0) r.truncate(idx); return r; } r.reserve(r.length() + 1 + s.length()); r += QLatin1Char('/'); r += s; return r; } bool FileInfo::globMatches(const QRegExp ®exp, const QString &fileName) { const QString pattern = regexp.pattern(); // May be it's simple wildcard, i.e. "*.cpp"? if (pattern.startsWith(QLatin1Char('*')) && !isPattern(pattern.midRef(1))) { // Yes, it's rather simple to just check the extension return fileName.endsWith(pattern.midRef(1)); } return regexp.exactMatch(fileName); } bool FileInfo::isFileCaseCorrect(const QString &filePath) { #if defined(Q_OS_WIN) // QFileInfo::canonicalFilePath() does not return the real case of the file path on Windows. QFileInfo fi(filePath); const QString absolute = fi.absoluteFilePath(); WIN32_FIND_DATA fd; HANDLE hFindFile = ::FindFirstFile((wchar_t*)absolute.utf16(), &fd); if (hFindFile == INVALID_HANDLE_VALUE) return false; const QString actualFileName = QString::fromWCharArray(fd.cFileName); FindClose(hFindFile); return actualFileName == fi.fileName(); #elif defined(Q_OS_DARWIN) QFileInfo fi(filePath); return fi.fileName() == fileName(fi.canonicalFilePath()); #else Q_UNUSED(filePath) return true; #endif } bool FileInfo::fileExists(const QFileInfo &fi) { return fi.isSymLink() || fi.exists(); } #if defined(Q_OS_WIN) #define z(x) reinterpret_cast(const_cast(&x)) template struct CompileTimeAssert; template<> struct CompileTimeAssert {}; FileInfo::FileInfo(const QString &fileName) { static CompileTimeAssert< sizeof(FileInfo::InternalStatType) == sizeof(WIN32_FILE_ATTRIBUTE_DATA) > internal_type_has_wrong_size; Q_UNUSED(internal_type_has_wrong_size); if (!GetFileAttributesEx(reinterpret_cast(fileName.utf16()), GetFileExInfoStandard, &m_stat)) { ZeroMemory(z(m_stat), sizeof(WIN32_FILE_ATTRIBUTE_DATA)); z(m_stat)->dwFileAttributes = INVALID_FILE_ATTRIBUTES; } } bool FileInfo::exists() const { return z(m_stat)->dwFileAttributes != INVALID_FILE_ATTRIBUTES; } FileTime FileInfo::lastModified() const { const FileTime::InternalType* ft_it; ft_it = reinterpret_cast(&z(m_stat)->ftLastWriteTime); return FileTime(*ft_it); } FileTime FileInfo::lastStatusChange() const { return lastModified(); } bool FileInfo::isDir() const { return z(m_stat)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; } static QString resolveSymlinks(const QString &fileName) { QFileInfo fi(fileName); while (fi.isSymLink()) fi.setFile(fi.symLinkTarget()); return fi.absoluteFilePath(); } QString applicationDirPath() { static const QString appDirPath = FileInfo::path(resolveSymlinks(QCoreApplication::applicationFilePath())); return appDirPath; } #elif defined(Q_OS_UNIX) FileInfo::FileInfo(const QString &fileName) { if (stat(fileName.toLocal8Bit(), &m_stat) == -1) m_stat.st_mtime = 0; } bool FileInfo::exists() const { return m_stat.st_mtime != 0; } FileTime FileInfo::lastModified() const { return m_stat.st_mtime; } FileTime FileInfo::lastStatusChange() const { return m_stat.st_ctime; } bool FileInfo::isDir() const { return S_ISDIR(m_stat.st_mode); } #endif // adapted from qtc/plugins/vcsbase/cleandialog.cpp bool removeFileRecursion(const QFileInfo &f, QString *errorMessage) { if (!FileInfo::fileExists(f)) return true; if (f.isDir() && !f.isSymLink()) { const QDir dir(f.absoluteFilePath()); // QDir::System is needed for broken symlinks. foreach (const QFileInfo &fi, dir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System)) removeFileRecursion(fi, errorMessage); QDir parent = f.absoluteDir(); if (!parent.rmdir(f.fileName())) { errorMessage->append(Tr::tr("The directory %1 could not be deleted."). arg(QDir::toNativeSeparators(f.absoluteFilePath()))); return false; } } else { QFile file(f.absoluteFilePath()); file.setPermissions(f.permissions() | QFile::WriteUser); if (!file.remove()) { if (!errorMessage->isEmpty()) errorMessage->append(QLatin1Char('\n')); errorMessage->append(Tr::tr("The file %1 could not be deleted."). arg(QDir::toNativeSeparators(f.absoluteFilePath()))); return false; } } return true; } bool removeDirectoryWithContents(const QString &path, QString *errorMessage) { QFileInfo f(path); if (f.exists() && !f.isDir()) { *errorMessage = Tr::tr("%1 is not a directory.").arg(QDir::toNativeSeparators(path)); return false; } return removeFileRecursion(f, errorMessage); } /*! * Returns the stored link target of the symbolic link \a{filePath}. * Unlike QFileInfo::symLinkTarget, this will not make the link target an absolute path. */ static QByteArray storedLinkTarget(const QString &filePath) { QByteArray result; #ifdef Q_OS_UNIX const QByteArray nativeFilePath = QFile::encodeName(filePath); ssize_t len; while (true) { struct stat sb; if (lstat(nativeFilePath.constData(), &sb)) { qWarning("storedLinkTarget: lstat for %s failed with error code %d", nativeFilePath.constData(), errno); return QByteArray(); } result.resize(sb.st_size); len = readlink(nativeFilePath.constData(), result.data(), sb.st_size + 1); if (len < 0) { qWarning("storedLinkTarget: readlink for %s failed with error code %d", nativeFilePath.constData(), errno); return QByteArray(); } if (len < sb.st_size) { result.resize(len); break; } if (len == sb.st_size) break; } #else Q_UNUSED(filePath); #endif // Q_OS_UNIX return result; } static bool createSymLink(const QByteArray &path1, const QString &path2) { #ifdef Q_OS_UNIX const QByteArray newPath = QFile::encodeName(path2); unlink(newPath.constData()); return symlink(path1.constData(), newPath.constData()) == 0; #else Q_UNUSED(path1); Q_UNUSED(path2); return false; #endif // Q_OS_UNIX } /*! Copies the directory specified by \a srcFilePath recursively to \a tgtFilePath. \a tgtFilePath will contain the target directory, which will be created. Example usage: \code QString error; book ok = Utils::FileUtils::copyRecursively("/foo/bar", "/foo/baz", &error); if (!ok) qDebug() << error; \endcode This will copy the contents of /foo/bar into to the baz directory under /foo, which will be created in the process. \return Whether the operation succeeded. \note Function was adapted from qtc/src/libs/fileutils.cpp */ bool copyFileRecursion(const QString &srcFilePath, const QString &tgtFilePath, bool preserveSymLinks, QString *errorMessage) { QFileInfo srcFileInfo(srcFilePath); QFileInfo tgtFileInfo(tgtFilePath); const QString targetDirPath = tgtFileInfo.absoluteDir().path(); if (!QDir::root().mkpath(targetDirPath)) { *errorMessage = Tr::tr("The directory '%1' could not be created.") .arg(QDir::toNativeSeparators(targetDirPath)); return false; } if (HostOsInfo::isAnyUnixHost() && preserveSymLinks && srcFileInfo.isSymLink()) { // For now, disable symlink preserving copying on Windows. // MS did a good job to prevent people from using symlinks - even if they are supported. if (!createSymLink(storedLinkTarget(srcFilePath), tgtFilePath)) { *errorMessage = Tr::tr("The symlink '%1' could not be created.") .arg(tgtFilePath); return false; } } else if (srcFileInfo.isDir()) { QDir sourceDir(srcFilePath); QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System); foreach (const QString &fileName, fileNames) { const QString newSrcFilePath = srcFilePath + QLatin1Char('/') + fileName; const QString newTgtFilePath = tgtFilePath + QLatin1Char('/') + fileName; if (!copyFileRecursion(newSrcFilePath, newTgtFilePath, preserveSymLinks, errorMessage)) return false; } } else { if (tgtFileInfo.exists() && srcFileInfo.lastModified() <= tgtFileInfo.lastModified()) return true; QFile file(srcFilePath); QFile targetFile(tgtFilePath); if (targetFile.exists()) { targetFile.setPermissions(targetFile.permissions() | QFile::WriteUser); if (!targetFile.remove()) { *errorMessage = Tr::tr("Could not remove file '%1'. %2") .arg(QDir::toNativeSeparators(tgtFilePath), targetFile.errorString()); } } if (!file.copy(tgtFilePath)) { *errorMessage = Tr::tr("Could not copy file '%1' to '%2'. %3") .arg(QDir::toNativeSeparators(srcFilePath), QDir::toNativeSeparators(tgtFilePath), file.errorString()); return false; } } return true; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/fileinfo.h000066400000000000000000000066461266132464200211750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_FILEINFO_H #define QBS_FILEINFO_H #include "filetime.h" #include "qbs_export.h" #if defined(Q_OS_UNIX) #include #endif #include QT_FORWARD_DECLARE_CLASS(QFileInfo) namespace qbs { namespace Internal { class FileInfo { public: FileInfo(const QString &fileName); bool exists() const; FileTime lastModified() const; FileTime lastStatusChange() const; bool isDir() const; static QString fileName(const QString &fp); static QString baseName(const QString &fp); static QString completeBaseName(const QString &fp); static QString path(const QString &fp); static void splitIntoDirectoryAndFileName(const QString &filePath, QString *dirPath, QString *fileName); static void splitIntoDirectoryAndFileName(const QString &filePath, QStringRef *dirPath, QStringRef *fileName); static bool exists(const QString &fp); static bool isAbsolute(const QString &fp); static bool isPattern(const QStringRef &str); static bool isPattern(const QString &str); static QString resolvePath(const QString &base, const QString &rel); static bool globMatches(const QRegExp &pattern, const QString &subject); static bool isFileCaseCorrect(const QString &filePath); // Symlink-correct check. static bool fileExists(const QFileInfo &fi); private: #if defined(Q_OS_WIN) struct InternalStatType { quint8 z[36]; }; #elif defined(Q_OS_UNIX) typedef struct stat InternalStatType; #else # error unknown platform #endif InternalStatType m_stat; }; bool removeFileRecursion(const QFileInfo &f, QString *errorMessage); // FIXME: Used by tests. bool QBS_EXPORT removeDirectoryWithContents(const QString &path, QString *errorMessage); bool QBS_EXPORT copyFileRecursion(const QString &sourcePath, const QString &targetPath, bool preserveSymLinks, QString *errorMessage); } // namespace Internal } // namespace qbs #endif qbs-src-1.4.5/src/lib/corelib/tools/filetime.h000066400000000000000000000067401266132464200211730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_FILETIME_H #define QBS_FILETIME_H #include #include #if defined(Q_OS_UNIX) #include #endif namespace qbs { namespace Internal { class FileTime { public: #if defined(Q_OS_UNIX) typedef time_t InternalType; #elif defined(Q_OS_WIN) typedef quint64 InternalType; #else # error unknown platform #endif FileTime(); FileTime(const InternalType &ft) : m_fileTime(ft) { } bool operator < (const FileTime &rhs) const; bool operator > (const FileTime &rhs) const; bool operator <= (const FileTime &rhs) const; bool operator >= (const FileTime &rhs) const; bool operator == (const FileTime &rhs) const; bool operator != (const FileTime &rhs) const; void clear(); bool isValid() const; QString toString() const; static FileTime currentTime(); static FileTime oldestTime(); friend class FileInfo; InternalType m_fileTime; }; inline bool FileTime::operator > (const FileTime &rhs) const { return rhs < *this; } inline bool FileTime::operator <= (const FileTime &rhs) const { return operator < (rhs) || operator == (rhs); } inline bool FileTime::operator >= (const FileTime &rhs) const { return operator > (rhs) || operator == (rhs); } inline bool FileTime::operator == (const FileTime &rhs) const { return m_fileTime == rhs.m_fileTime; } inline bool FileTime::operator != (const FileTime &rhs) const { return !operator==(rhs); } } // namespace Internal } // namespace qbs QT_BEGIN_NAMESPACE inline QDataStream& operator>>(QDataStream &stream, qbs::Internal::FileTime &ft) { quint64 u; stream >> u; ft.m_fileTime = u; return stream; } inline QDataStream& operator<<(QDataStream &stream, const qbs::Internal::FileTime &ft) { stream << (quint64)ft.m_fileTime; return stream; } inline QDebug operator<<(QDebug dbg, const qbs::Internal::FileTime &t) { dbg.nospace() << t.toString(); return dbg.space(); } QT_END_NAMESPACE #endif // QBS_FILETIME_H qbs-src-1.4.5/src/lib/corelib/tools/filetime_unix.cpp000066400000000000000000000041721266132464200225660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "filetime.h" #include #include #include namespace qbs { namespace Internal { FileTime::FileTime() : m_fileTime(0) { } bool FileTime::operator < (const FileTime &rhs) const { return m_fileTime < rhs.m_fileTime; } void FileTime::clear() { m_fileTime = 0; } bool FileTime::isValid() const { return m_fileTime != 0; } FileTime FileTime::currentTime() { return time(0); } FileTime FileTime::oldestTime() { return 1; } QString FileTime::toString() const { QDateTime dt; dt.setTime_t(m_fileTime); return dt.toString(); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/filetime_win.cpp000066400000000000000000000065561266132464200224100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "filetime.h" #include #include namespace qbs { namespace Internal { template struct CompileTimeAssert; template<> struct CompileTimeAssert {}; FileTime::FileTime() : m_fileTime(0) { static CompileTimeAssert internal_type_has_wrong_size; Q_UNUSED(internal_type_has_wrong_size); } bool FileTime::operator < (const FileTime &rhs) const { const FILETIME *const t1 = reinterpret_cast(&m_fileTime); const FILETIME *const t2 = reinterpret_cast(&rhs.m_fileTime); return CompareFileTime(t1, t2) < 0; } void FileTime::clear() { m_fileTime = 0; } bool FileTime::isValid() const { return m_fileTime != 0; } FileTime FileTime::currentTime() { FileTime result; SYSTEMTIME st; GetSystemTime(&st); FILETIME *const ft = reinterpret_cast(&result.m_fileTime); SystemTimeToFileTime(&st, ft); return result; } FileTime FileTime::oldestTime() { SYSTEMTIME st = { 1601, 1, 5, 2 }; FileTime result; FILETIME *const ft = reinterpret_cast(&result.m_fileTime); SystemTimeToFileTime(&st, ft); return result; } QString FileTime::toString() const { const FILETIME *const ft = reinterpret_cast(&m_fileTime); SYSTEMTIME stUTC, stLocal; FileTimeToSystemTime(ft, &stUTC); SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal); const QString result = QString::fromLatin1("%1.%2.%3 %4:%5:%6") .arg(stLocal.wDay, 2, 10, QLatin1Char('0')).arg(stLocal.wMonth, 2, 10, QLatin1Char('0')).arg(stLocal.wYear) .arg(stLocal.wHour, 2, 10, QLatin1Char('0')).arg(stLocal.wMinute, 2, 10, QLatin1Char('0')).arg(stLocal.wSecond, 2, 10, QLatin1Char('0')); return result; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/generateoptions.cpp000066400000000000000000000052741266132464200231370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "generateoptions.h" #include #include namespace qbs { namespace Internal { class GenerateOptionsPrivate : public QSharedData { public: GenerateOptionsPrivate() : generatorName() {} QString generatorName; }; } // namespace Internal /*! * \class GenerateOptions * \brief The \c GenerateOptions class comprises parameters that influence the behavior of * generate operations. */ GenerateOptions::GenerateOptions() : d(new Internal::GenerateOptionsPrivate) { } GenerateOptions::GenerateOptions(const GenerateOptions &other) : d(other.d) { } GenerateOptions &GenerateOptions::operator=(const GenerateOptions &other) { d = other.d; return *this; } GenerateOptions::~GenerateOptions() { } /*! * Returns the name of the generator used to create the external build system files. * The default is empty. */ QString GenerateOptions::generatorName() const { return d->generatorName; } /*! * \brief Sets the name of the generator used to create the external build system files. */ void GenerateOptions::setGeneratorName(const QString &generatorName) { d->generatorName = generatorName; } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/generateoptions.h000066400000000000000000000042601266132464200225760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_GENERATEOPTIONS_H #define QBS_GENERATEOPTIONS_H #include "qbs_export.h" #include QT_BEGIN_NAMESPACE class QString; QT_END_NAMESPACE namespace qbs { namespace Internal { class GenerateOptionsPrivate; } class QBS_EXPORT GenerateOptions { public: GenerateOptions(); GenerateOptions(const GenerateOptions &other); GenerateOptions &operator=(const GenerateOptions &other); ~GenerateOptions(); QString generatorName() const; void setGeneratorName(const QString &generatorName); private: QSharedDataPointer d; }; } // namespace qbs #endif // QBS_GENERATEOPTIONS_H qbs-src-1.4.5/src/lib/corelib/tools/hostosinfo.h000066400000000000000000000130671266132464200215700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_HOSTOSINFO_H #define QBS_HOSTOSINFO_H #include "qbs_export.h" #include "version.h" #include #include #include #include #include #if defined(Q_OS_WIN) #define QBS_HOST_EXE_SUFFIX ".exe" #define QBS_HOST_DYNAMICLIB_PREFIX "" #define QBS_HOST_DYNAMICLIB_SUFFIX ".dll" #elif defined(Q_OS_DARWIN) #define QBS_HOST_EXE_SUFFIX "" #define QBS_HOST_DYNAMICLIB_PREFIX "lib" #define QBS_HOST_DYNAMICLIB_SUFFIX ".dylib" #else #define QBS_HOST_EXE_SUFFIX "" #define QBS_HOST_DYNAMICLIB_PREFIX "lib" #define QBS_HOST_DYNAMICLIB_SUFFIX ".so" #endif // Q_OS_WIN namespace qbs { namespace Internal { class QBS_EXPORT HostOsInfo // Exported for use by command-line tools. { public: // Add more as needed. enum HostOs { HostOsWindows, HostOsLinux, HostOsOsx, HostOsOtherUnix, HostOsOther }; static inline HostOs hostOs(); static inline Version hostOsVersion() { Version v; if (HostOsInfo::isWindowsHost()) { QSettings settings(QString::fromLatin1("HKEY_LOCAL_MACHINE\\Software\\" "Microsoft\\Windows NT\\CurrentVersion"), QSettings::NativeFormat); v = v.fromString(settings.value(QStringLiteral("CurrentVersion")).toString() + QLatin1Char('.') + settings.value(QStringLiteral("CurrentBuildNumber")).toString()); Q_ASSERT(v.isValid()); } else if (HostOsInfo::isOsxHost()) { QSettings settings(QStringLiteral("/System/Library/CoreServices/SystemVersion.plist"), QSettings::NativeFormat); v = v.fromString(settings.value(QStringLiteral("ProductVersion")).toString()); Q_ASSERT(v.isValid()); } return v; } static bool isWindowsHost() { return hostOs() == HostOsWindows; } static bool isLinuxHost() { return hostOs() == HostOsLinux; } static bool isOsxHost() { return hostOs() == HostOsOsx; } static inline bool isAnyUnixHost(); static inline QString rfc1034Identifier(const QString &str); static QString appendExecutableSuffix(const QString &executable) { QString finalName = executable; if (isWindowsHost()) finalName += QLatin1String(QBS_HOST_EXE_SUFFIX); return finalName; } static QString dynamicLibraryName(const QString &libraryBaseName) { return QLatin1String(QBS_HOST_DYNAMICLIB_PREFIX) + libraryBaseName + QLatin1String(QBS_HOST_DYNAMICLIB_SUFFIX); } static Qt::CaseSensitivity fileNameCaseSensitivity() { return isWindowsHost() ? Qt::CaseInsensitive: Qt::CaseSensitive; } static QString libraryPathEnvironmentVariable() { if (isWindowsHost()) return QStringLiteral("PATH"); if (isOsxHost()) return QStringLiteral("DYLD_LIBRARY_PATH"); return QStringLiteral("LD_LIBRARY_PATH"); } static QChar pathListSeparator() { return isWindowsHost() ? QLatin1Char(';') : QLatin1Char(':'); } static Qt::KeyboardModifier controlModifier() { return isOsxHost() ? Qt::MetaModifier : Qt::ControlModifier; } }; HostOsInfo::HostOs HostOsInfo::hostOs() { #if defined(Q_OS_WIN) return HostOsWindows; #elif defined(Q_OS_LINUX) return HostOsLinux; #elif defined(Q_OS_DARWIN) return HostOsOsx; #elif defined(Q_OS_UNIX) return HostOsOtherUnix; #else return HostOsOther; #endif } bool HostOsInfo::isAnyUnixHost() { #ifdef Q_OS_UNIX return true; #else return false; #endif } QString HostOsInfo::rfc1034Identifier(const QString &str) { QString s = str; for (int i = 0; i < s.size(); ++i) { QCharRef ch = s[i]; const char c = ch.toLatin1(); const bool okChar = (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.'; if (!okChar) ch = QChar::fromLatin1('-'); } return s; } } // namespace Internal } // namespace qbs #endif // QBS_HOSTOSINFO_H qbs-src-1.4.5/src/lib/corelib/tools/id.cpp000066400000000000000000000163641266132464200203270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "id.h" #include "qbsassert.h" #include #include #include namespace qbs { namespace Internal { /*! \class qbs::Internal::Id \brief The class Id encapsulates an identifier that is unique within a specific running process, using the qbs library. \c{Id} is used as facility to identify objects of interest in a more typesafe and faster manner than a plain \c QString or \c QByteArray would provide. An id is internally represented as a 32 bit integer (its \c UID) and associated with a plain 7-bit-clean ASCII name used for display and persistency. This class is copied from Qt Creator. */ class StringHolder { public: StringHolder() : n(0), str(0) {} StringHolder(const char *s, int length) : n(length), str(s) { if (!n) length = n = qstrlen(s); h = 0; while (length--) { h = (h << 4) + *s++; h ^= (h & 0xf0000000) >> 23; h &= 0x0fffffff; } } int n; const char *str; uint h; }; static bool operator==(const StringHolder &sh1, const StringHolder &sh2) { // sh.n is unlikely to discriminate better than the hash. return sh1.h == sh2.h && sh1.str && sh2.str && strcmp(sh1.str, sh2.str) == 0; } static uint qHash(const StringHolder &sh) { return sh.h; } struct IdCache : public QHash { #ifndef QBS_ALLOW_STATIC_LEAKS ~IdCache() { for (IdCache::iterator it = begin(); it != end(); ++it) delete[](const_cast(it.key().str)); } #endif }; static int firstUnusedId = Id::IdsPerPlugin * Id::ReservedPlugins; static QHash stringFromId; static IdCache idFromString; static int theId(const char *str, int n = 0) { QBS_ASSERT(str && *str, return 0); StringHolder sh(str, n); int res = idFromString.value(sh, 0); if (res == 0) { res = firstUnusedId++; sh.str = qstrdup(sh.str); idFromString[sh] = res; stringFromId[res] = sh; } return res; } static int theId(const QByteArray &ba) { return theId(ba.constData(), ba.size()); } /*! \fn qbs::Internal::Id(int uid) \brief Constructs an id given a UID. The UID is an integer value that is unique within the running process. It is the callers responsibility to ensure the uniqueness of the passed integer. The recommended approach is to use \c{registerId()} with an value taken from the plugin's private range. \sa registerId() */ /*! Constructs an id given its associated name. The internal representation will be unspecified, but consistent within a process. */ Id::Id(const char *name) : m_id(theId(name, 0)) {} /*! \overload */ Id::Id(const QByteArray &name) : m_id(theId(name)) {} ///*! // \overload // \deprecated //*/ //Id::Id(const QString &name) // : m_id(theId(name.toUtf8())) //{} /*! Returns an internal representation of the id. */ QByteArray Id::name() const { return stringFromId.value(m_id).str; } /*! Returns a string representation of the id suitable for UI display. This should not be used to create a persistent version of the Id, use \c{toSetting()} instead. \sa fromString(), toSetting() */ QString Id::toString() const { return QString::fromUtf8(stringFromId.value(m_id).str); } /*! Creates an id from a string representation. This should not be used to handle a persistent version of the Id, use \c{fromSetting()} instead. \deprecated \sa toString(), fromSetting() */ Id Id::fromString(const QString &name) { return Id(theId(name.toUtf8())); } /*! Creates an id from a string representation. This should not be used to handle a persistent version of the Id, use \c{fromSetting()} instead. \deprecated \sa toString(), fromSetting() */ Id Id::fromName(const QByteArray &name) { return Id(theId(name)); } /*! Returns a persistent value representing the id which is suitable to be stored in QSettings. \sa fromSetting() */ QVariant Id::toSetting() const { return QVariant(QString::fromUtf8(stringFromId.value(m_id).str)); } /*! Reconstructs an id from a persistent value. \sa toSetting() */ Id Id::fromSetting(const QVariant &variant) { const QByteArray ba = variant.toString().toUtf8(); if (ba.isEmpty()) return Id(); return Id(theId(ba)); } /*! Constructs a derived id. This can be used to construct groups of ids logically belonging together. The associated internal name will be generated by appending \c{suffix}. */ Id Id::withSuffix(int suffix) const { const QByteArray ba = name() + QByteArray::number(suffix); return Id(ba.constData()); } /*! \overload */ Id Id::withSuffix(const char *suffix) const { const QByteArray ba = name() + suffix; return Id(ba.constData()); } /*! Constructs a derived id. This can be used to construct groups of ids logically belonging together. The associated internal name will be generated by prepending \c{prefix}. */ Id Id::withPrefix(const char *prefix) const { const QByteArray ba = prefix + name(); return Id(ba.constData()); } /*! Associates a id with its uid and its string representation. The uid should be taken from the plugin's private range. \sa fromSetting() */ void Id::registerId(int uid, const char *name) { StringHolder sh(name, 0); idFromString[sh] = uid; stringFromId[uid] = sh; } bool Id::operator==(const char *name) const { const char *string = stringFromId.value(m_id).str; if (string && name) return strcmp(string, name) == 0; else return false; } bool Id::alphabeticallyBefore(Id other) const { return toString().compare(other.toString(), Qt::CaseInsensitive) < 0; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/id.h000066400000000000000000000063161266132464200177700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_TOOLS_ID_H #define QBS_TOOLS_ID_H #include #include #include namespace qbs { namespace Internal { class Id { public: enum { IdsPerPlugin = 10000, ReservedPlugins = 1000 }; Id() : m_id(0) {} Id(int uid) : m_id(uid) {} Id(const char *name); // explicit Id(const QString &name); explicit Id(const QByteArray &name); Id withSuffix(int suffix) const; Id withSuffix(const char *name) const; Id withPrefix(const char *name) const; QByteArray name() const; QString toString() const; // Avoid. QVariant toSetting() const; // Good to use. bool isValid() const { return m_id; } bool operator==(Id id) const { return m_id == id.m_id; } bool operator==(const char *name) const; bool operator!=(Id id) const { return m_id != id.m_id; } bool operator!=(const char *name) const { return !operator==(name); } bool operator<(Id id) const { return m_id < id.m_id; } bool operator>(Id id) const { return m_id > id.m_id; } bool alphabeticallyBefore(Id other) const; int uniqueIdentifier() const { return m_id; } static Id fromUniqueIdentifier(int uid) { return Id(uid); } static Id fromString(const QString &str); // FIXME: avoid. static Id fromName(const QByteArray &ba); // FIXME: avoid. static Id fromSetting(const QVariant &variant); // Good to use. static void registerId(int uid, const char *name); private: // Intentionally unimplemented Id(const QLatin1String &); int m_id; }; inline uint qHash(const Id &id) { return id.uniqueIdentifier(); } } // namespace Internal } // namespace qbs Q_DECLARE_METATYPE(qbs::Internal::Id) Q_DECLARE_METATYPE(QList) #endif // QBS_TOOLS_ID_H qbs-src-1.4.5/src/lib/corelib/tools/installoptions.cpp000066400000000000000000000145751266132464200230170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "installoptions.h" #include "propertyfinder.h" #include "language/language.h" #include #include namespace qbs { namespace Internal { class InstallOptionsPrivate : public QSharedData { public: InstallOptionsPrivate() : useSysroot(false), removeExisting(false), dryRun(false), keepGoing(false), logElapsedTime(false) {} QString installRoot; bool useSysroot; bool removeExisting; bool dryRun; bool keepGoing; bool logElapsedTime; }; QString effectiveInstallRoot(const InstallOptions &options, const TopLevelProject *project) { const QString installRoot = options.installRoot(); if (!installRoot.isEmpty()) return installRoot; QVariantMap configForPropertyFinder; configForPropertyFinder.insert(QLatin1String("modules"), project->buildConfiguration()); if (options.installIntoSysroot()) { return PropertyFinder().propertyValue(configForPropertyFinder, QLatin1String("qbs"), QLatin1String("sysroot")).toString(); } return PropertyFinder().propertyValue(configForPropertyFinder, QLatin1String("qbs"), QLatin1String("installRoot")).toString(); } } // namespace Internal /*! * \class InstallOptions * \brief The \c InstallOptions class comprises parameters that influence the behavior of * install operations. */ InstallOptions::InstallOptions() : d(new Internal::InstallOptionsPrivate) { } InstallOptions::InstallOptions(const InstallOptions &other) : d(other.d) { } InstallOptions &InstallOptions::operator=(const InstallOptions &other) { d = other.d; return *this; } InstallOptions::~InstallOptions() { } /*! * \brief The default install root, relative to the build directory. */ QString InstallOptions::defaultInstallRoot() { return QLatin1String("install-root"); } /*! * Returns the base directory for the installation. * The \c qbs.installPrefix path is relative to this root. If the string is empty, either the value of * qbs.sysroot or "/install-root" will be used, depending on what \c installIntoSysroot() * returns. * The default is empty. */ QString InstallOptions::installRoot() const { return d->installRoot; } /*! * \brief Sets the base directory for the installation. * \note The argument must either be an empty string or an absolute path to a directory * (which might not yet exist, in which case it will be created). */ void InstallOptions::setInstallRoot(const QString &installRoot) { d->installRoot = installRoot; if (!QDir(installRoot).isRoot()) { while (d->installRoot.endsWith(QLatin1Char('/'))) d->installRoot.chop(1); } } /*! * Returns whether to use the sysroot as the default install root. * The default is false. */ bool InstallOptions::installIntoSysroot() const { return d->useSysroot; } void InstallOptions::setInstallIntoSysroot(bool useSysroot) { d->useSysroot = useSysroot; } /*! * \brief Returns true iff an existing installation will be removed prior to installing. * The default is false. */ bool InstallOptions::removeExistingInstallation() const { return d->removeExisting; } /*! * Controls whether to remove an existing installation before installing. * \note qbs may do some safety checks and refuse to remove certain directories such as * a user's home directory. You should still be careful with this option, since it * deletes recursively. */ void InstallOptions::setRemoveExistingInstallation(bool removeExisting) { d->removeExisting = removeExisting; } /*! * \brief Returns true iff qbs will not actually copy any files, but just show what would happen. * The default is false. */ bool InstallOptions::dryRun() const { return d->dryRun; } /*! * \brief Controls whether installation will actually take place. * If the argument is true, then qbs will emit information about which files would be copied * instead of actually doing it. */ void InstallOptions::setDryRun(bool dryRun) { d->dryRun = dryRun; } /*! * Returns true iff installation will continue if an error occurs. * The default is false. */ bool InstallOptions::keepGoing() const { return d->keepGoing; } /*! * \brief Controls whether to abort on errors. * If the argument is true, then if a file cannot be copied e.g. due to a permission problem, * a warning will be printed and the installation will continue. If the argument is false, * then the installation will abort immediately in case of an error. */ void InstallOptions::setKeepGoing(bool keepGoing) { d->keepGoing = keepGoing; } /*! * \brief Returns true iff the time the operation takes will be logged. * The default is false. */ bool InstallOptions::logElapsedTime() const { return d->logElapsedTime; } /*! * \brief Controls whether the installation time will be measured and logged. */ void InstallOptions::setLogElapsedTime(bool logElapsedTime) { d->logElapsedTime = logElapsedTime; } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/installoptions.h000066400000000000000000000052361266132464200224560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_INSTALLOPTIONS_H #define QBS_INSTALLOPTIONS_H #include "qbs_export.h" #include #include namespace qbs { class InstallOptions; namespace Internal { class InstallOptionsPrivate; class TopLevelProject; QString effectiveInstallRoot(const InstallOptions &options, const TopLevelProject *project); } class QBS_EXPORT InstallOptions { public: InstallOptions(); InstallOptions(const InstallOptions &other); InstallOptions &operator=(const InstallOptions &other); ~InstallOptions(); static QString defaultInstallRoot(); QString installRoot() const; void setInstallRoot(const QString &installRoot); bool installIntoSysroot() const; void setInstallIntoSysroot(bool useSysroot); bool removeExistingInstallation() const; void setRemoveExistingInstallation(bool removeExisting); bool dryRun() const; void setDryRun(bool dryRun); bool keepGoing() const; void setKeepGoing(bool keepGoing); bool logElapsedTime() const; void setLogElapsedTime(bool logElapsedTime); private: QSharedDataPointer d; }; } // namespace qbs #endif // QBS_INSTALLOPTIONS_H qbs-src-1.4.5/src/lib/corelib/tools/persistence.cpp000066400000000000000000000210531266132464200222460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "persistence.h" #include "fileinfo.h" #include #include #include #include #include namespace qbs { namespace Internal { static const char QBS_PERSISTENCE_MAGIC[] = "QBSPERSISTENCE-80"; PersistentPool::PersistentPool(const Logger &logger) : m_logger(logger) { m_stream.setVersion(QDataStream::Qt_4_8); } PersistentPool::~PersistentPool() { closeStream(); } void PersistentPool::load(const QString &filePath) { QScopedPointer file(new QFile(filePath)); if (!file->exists()) throw ErrorInfo(Tr::tr("No build graph exists yet for this configuration.")); if (!file->open(QFile::ReadOnly)) { throw ErrorInfo(Tr::tr("Could not open open build graph file '%1': %2") .arg(filePath, file->errorString())); } m_stream.setDevice(file.data()); QByteArray magic; m_stream >> magic; if (magic != QBS_PERSISTENCE_MAGIC) { file->close(); file->remove(); m_stream.setDevice(0); throw ErrorInfo(Tr::tr("Cannot use stored build graph at '%1': Incompatible file format. " "Expected magic token '%2', got '%3'.") .arg(filePath, QString::fromLatin1(QBS_PERSISTENCE_MAGIC), QString::fromLatin1(magic))); } m_stream >> m_headData.projectConfig; file.take(); m_loadedRaw.clear(); m_loaded.clear(); m_storageIndices.clear(); m_stringStorage.clear(); m_inverseStringStorage.clear(); } void PersistentPool::setupWriteStream(const QString &filePath) { QString dirPath = FileInfo::path(filePath); if (!FileInfo::exists(dirPath) && !QDir().mkpath(dirPath)) { throw ErrorInfo(Tr::tr("Failure storing build graph: Cannot create directory '%1'.") .arg(dirPath)); } if (QFile::exists(filePath) && !QFile::remove(filePath)) { throw ErrorInfo(Tr::tr("Failure storing build graph: Cannot remove old file '%1'") .arg(filePath)); } QBS_CHECK(!QFile::exists(filePath)); QScopedPointer file(new QFile(filePath)); if (!file->open(QFile::WriteOnly)) { throw ErrorInfo(Tr::tr("Failure storing build graph: " "Cannot open file '%1' for writing: %2").arg(filePath, file->errorString())); } m_stream.setDevice(file.take()); m_stream << QByteArray(qstrlen(QBS_PERSISTENCE_MAGIC), 0) << m_headData.projectConfig; m_lastStoredObjectId = 0; m_lastStoredStringId = 0; } void PersistentPool::finalizeWriteStream() { if (m_stream.status() != QDataStream::Ok) throw ErrorInfo(Tr::tr("Failure serializing build graph.")); m_stream.device()->seek(0); m_stream << QByteArray(QBS_PERSISTENCE_MAGIC); if (m_stream.status() != QDataStream::Ok) throw ErrorInfo(Tr::tr("Failure serializing build graph.")); QFile * const file = static_cast(m_stream.device()); if (!file->flush()) { file->close(); file->remove(); throw ErrorInfo(Tr::tr("Failure serializing build graph: %1").arg(file->errorString())); } } void PersistentPool::closeStream() { delete m_stream.device(); m_stream.setDevice(0); } void PersistentPool::store(const PersistentObject *object) { if (!object) { m_stream << -1; return; } PersistentObjectId id = m_storageIndices.value(object, -1); if (id < 0) { id = m_lastStoredObjectId++; m_storageIndices.insert(object, id); m_stream << id; object->store(*this); } else { m_stream << id; } } void PersistentPool::store(const QVariantMap &map) { m_stream << map.count(); for (QVariantMap::ConstIterator it = map.constBegin(); it != map.constEnd(); ++it) { storeString(it.key()); store(it.value()); } } QVariantMap PersistentPool::loadVariantMap() { int count; m_stream >> count; QVariantMap map; for (int i = 0; i < count; ++i) { const QString key = idLoadString(); const QVariant value = loadVariant(); map.insert(key, value); } return map; } void PersistentPool::store(const QVariant &variant) { const quint32 type = static_cast(variant.type()); m_stream << type; switch (type) { case QMetaType::QString: storeString(variant.toString()); break; case QMetaType::QStringList: storeStringList(variant.toStringList()); break; case QMetaType::QVariantList: storeContainer(variant.toList()); break; case QMetaType::QVariantMap: store(variant.toMap()); break; default: m_stream << variant; } } QVariant PersistentPool::loadVariant() { quint32 type; m_stream >> type; QVariant value; switch (type) { case QMetaType::QString: value = idLoadString(); break; case QMetaType::QStringList: value = idLoadStringList(); break; case QMetaType::QVariantList: { QVariantList l; int count; m_stream >> count; for (int i = 0; i < count; ++i) l << loadVariant(); value = l; break; } case QMetaType::QVariantMap: value = loadVariantMap(); break; default: m_stream >> value; } return value; } void PersistentPool::clear() { m_loaded.clear(); m_storageIndices.clear(); m_stringStorage.clear(); m_inverseStringStorage.clear(); } QDataStream &PersistentPool::stream() { return m_stream; } const int StringNotFoundId = -1; const int NullStringId = -2; void PersistentPool::storeString(const QString &t) { if (t.isNull()) { m_stream << NullStringId; return; } int id = m_inverseStringStorage.value(t, StringNotFoundId); if (id < 0) { id = m_lastStoredStringId++; m_inverseStringStorage.insert(t, id); m_stream << id << t; } else { m_stream << id; } } QString PersistentPool::loadString(int id) { if (id == NullStringId) return QString(); QBS_CHECK(id >= 0); if (id >= m_stringStorage.count()) { QString s; m_stream >> s; m_stringStorage.resize(id + 1); m_stringStorage[id] = s; return s; } return m_stringStorage.at(id); } QString PersistentPool::idLoadString() { int id; m_stream >> id; return loadString(id); } void PersistentPool::storeStringSet(const QSet &t) { m_stream << t.count(); foreach (const QString &s, t) storeString(s); } QSet PersistentPool::idLoadStringSet() { int i; m_stream >> i; QSet result; for (; --i >= 0;) result += idLoadString(); return result; } void PersistentPool::storeStringList(const QStringList &t) { m_stream << t.count(); foreach (const QString &s, t) storeString(s); } QStringList PersistentPool::idLoadStringList() { int i; m_stream >> i; QStringList result; for (; --i >= 0;) result += idLoadString(); return result; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/persistence.h000066400000000000000000000142301266132464200217120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PERSISTENCE #define QBS_PERSISTENCE #include "persistentobject.h" #include #include #include #include #include #include namespace qbs { namespace Internal { class PersistentPool { public: PersistentPool(const Logger &logger); ~PersistentPool(); class HeadData { public: QVariantMap projectConfig; }; void load(const QString &filePath); void setupWriteStream(const QString &filePath); void finalizeWriteStream(); void closeStream(); void clear(); QDataStream &stream(); template T *idLoad(); template void loadContainer(T &container); template QSharedPointer idLoadS(); template void loadContainerS(T &container); void store(const QSharedPointer &ptr) { store(ptr.data()); } void store(const PersistentObject *object); template void storeContainer(const T &container); void store(const QVariantMap &map); QVariantMap loadVariantMap(); void store(const QVariant &variant); QVariant loadVariant(); void storeString(const QString &t); QString loadString(int id); QString idLoadString(); void storeStringSet(const QSet &t); QSet loadStringSet(const QList &id); QSet idLoadStringSet(); void storeStringList(const QStringList &t); QStringList loadStringList(const QList &ids); QStringList idLoadStringList(); const HeadData &headData() const { return m_headData; } void setHeadData(const HeadData &hd) { m_headData = hd; } private: typedef int PersistentObjectId; template struct RemovePointer { typedef T Type; }; template struct RemovePointer { typedef T Type; }; template struct RemoveConst { typedef T Type; }; template struct RemoveConst { typedef T Type; }; template T *loadRaw(PersistentObjectId id); template QSharedPointer load(PersistentObjectId id); QDataStream m_stream; HeadData m_headData; QVector m_loadedRaw; QVector > m_loaded; QHash m_storageIndices; PersistentObjectId m_lastStoredObjectId; QVector m_stringStorage; QHash m_inverseStringStorage; PersistentObjectId m_lastStoredStringId; Logger m_logger; }; template inline T *PersistentPool::idLoad() { PersistentObjectId id; stream() >> id; return loadRaw(id); } template inline void PersistentPool::loadContainer(T &container) { int count; stream() >> count; container.clear(); container.reserve(count); for (int i = count; --i >= 0;) container += idLoad::Type>(); } template inline QSharedPointer PersistentPool::idLoadS() { PersistentObjectId id; m_stream >> id; return load(id); } template inline void PersistentPool::loadContainerS(T &container) { int count; stream() >> count; container.clear(); container.reserve(count); for (int i = count; --i >= 0;) container += idLoadS::Type>(); } template inline void PersistentPool::storeContainer(const T &container) { stream() << container.count(); typename T::const_iterator it = container.constBegin(); const typename T::const_iterator itEnd = container.constEnd(); for (; it != itEnd; ++it) store(*it); } template inline T *PersistentPool::loadRaw(PersistentObjectId id) { if (id < 0) return 0; if (id < m_loadedRaw.count()) { PersistentObject *obj = m_loadedRaw.value(id); return dynamic_cast(obj); } int i = m_loadedRaw.count(); m_loadedRaw.resize(id + 1); for (; i < m_loadedRaw.count(); ++i) m_loadedRaw[i] = 0; T * const t = new T; PersistentObject * const po = t; m_loadedRaw[id] = po; po->load(*this); return t; } template inline QSharedPointer PersistentPool::load(PersistentObjectId id) { if (id < 0) return QSharedPointer(); if (id < m_loaded.count()) { QSharedPointer obj = m_loaded.value(id); return obj.dynamicCast(); } m_loaded.resize(id + 1); const QSharedPointer t = T::create(); m_loaded[id] = t; PersistentObject * const po = t.data(); po->load(*this); return t; } } // namespace Internal } // namespace qbs #endif qbs-src-1.4.5/src/lib/corelib/tools/persistentobject.h000066400000000000000000000035471266132464200227660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PERSISTENTOBJECT_H #define QBS_PERSISTENTOBJECT_H namespace qbs { namespace Internal { class PersistentPool; class PersistentObject { public: virtual ~PersistentObject() {} virtual void load(PersistentPool &) = 0; virtual void store(PersistentPool &) const = 0; }; } // namespace Internal } // namespace qbs #endif // QBS_PERSISTENTOBJECT_H qbs-src-1.4.5/src/lib/corelib/tools/preferences.cpp000066400000000000000000000111721266132464200222240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "preferences.h" #include "buildoptions.h" #include "hostosinfo.h" #include "profile.h" #include "settings.h" namespace qbs { /*! * \class Preferences * \brief The \c Preferences class gives access to all general qbs preferences. * If a non-empty \c profileName is given, the profile's preferences take precedence over global * ones. Otherwise, the global preferences are used. */ Preferences::Preferences(Settings *settings, const QString &profileName) : m_settings(settings), m_profile(profileName) { } /*! * \brief Returns true <=> colored output should be used for printing messages. * This is only relevant for command-line frontends. */ bool Preferences::useColoredOutput() const { return getPreference(QLatin1String("useColoredOutput"), true).toBool(); } /*! * \brief Returns the number of parallel jobs to use for building. * Uses a sensible default value if there is no such setting. */ int Preferences::jobs() const { return getPreference(QLatin1String("jobs"), BuildOptions::defaultMaxJobCount()).toInt(); } /*! * \brief Returns the shell to use for the "qbs shell" command. * This is only relevant for command-line frontends. */ QString Preferences::shell() const { return getPreference(QLatin1String("shell")).toString(); } /*! * \brief Returns the default build directory used by Qbs if none is specified. */ QString Preferences::defaultBuildDirectory() const { return getPreference(QLatin1String("defaultBuildDirectory")).toString(); } /*! * \brief Returns the default echo mode used by Qbs if none is specified. */ CommandEchoMode Preferences::defaultEchoMode() const { return commandEchoModeFromName(getPreference(QLatin1String("defaultEchoMode")).toString()); } /*! * \brief Returns the list of paths where qbs looks for modules and imports. * In addition to user-supplied locations, they will also be looked up at \c{baseDir}/share/qbs. */ QStringList Preferences::searchPaths(const QString &baseDir) const { return pathList(QLatin1String("qbsSearchPaths"), baseDir + QLatin1String("/share/qbs")); } /*! * \brief Returns the list of paths where qbs looks for plugins. * In addition to user-supplied locations, they will be looked up at \c{baseDir}/qbs/plugins. */ QStringList Preferences::pluginPaths(const QString &baseDir) const { return pathList(QLatin1String("pluginsPath"), baseDir + QLatin1String("/qbs/plugins")); } QVariant Preferences::getPreference(const QString &key, const QVariant &defaultValue) const { const QString fullKey = QLatin1String("preferences.") + key; if (!m_profile.isEmpty()) { QVariant value = Profile(m_profile, m_settings).value(fullKey); if (value.isValid()) { if (key == QLatin1String("qbsSearchPaths")) // Merge with top-level value. value = value.toStringList() + m_settings->value(fullKey).toStringList(); return value; } } return m_settings->value(fullKey, defaultValue); } QStringList Preferences::pathList(const QString &key, const QString &defaultValue) const { QStringList paths = getPreference(key).toStringList(); paths << defaultValue; return paths; } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/preferences.h000066400000000000000000000046041266132464200216730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PREFERENCES_H #define QBS_PREFERENCES_H #include "qbs_export.h" #include "commandechomode.h" #include #include namespace qbs { class Settings; class QBS_EXPORT Preferences { public: explicit Preferences(Settings *settings, const QString &profileName = QString()); bool useColoredOutput() const; int jobs() const; QString shell() const; QString defaultBuildDirectory() const; CommandEchoMode defaultEchoMode() const; QStringList searchPaths(const QString &baseDir = QString()) const; QStringList pluginPaths(const QString &baseDir = QString()) const; private: QVariant getPreference(const QString &key, const QVariant &defaultValue = QVariant()) const; QStringList pathList(const QString &key, const QString &defaultValue) const; Settings *m_settings; QString m_profile; }; } // namespace qbs #endif // Header guard qbs-src-1.4.5/src/lib/corelib/tools/processresult.cpp000066400000000000000000000062271266132464200226450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "processresult.h" #include "processresult_p.h" /*! * \class SetupProjectParameters * \brief The \c ProcessResult class describes a finished qbs process command. */ namespace qbs { ProcessResult::ProcessResult() : d(new Internal::ProcessResultPrivate) { } ProcessResult::ProcessResult(const ProcessResult &other) : d(other.d) { } ProcessResult &ProcessResult::operator=(const ProcessResult &other) { d = other.d; return *this; } ProcessResult::~ProcessResult() { } /*! * \brief Returns true iff the command finished successfully. */ bool ProcessResult::success() const { return d->success; } /*! * \brief Returns the file path of the executable that was run. */ QString ProcessResult::executableFilePath() const { return d->executableFilePath; } /*! * \brief Returns the command-line arguments with which the command was invoked. */ QStringList ProcessResult::arguments() const { return d->arguments; } /*! * \brief Returns the working directory of the invoked command. */ QString ProcessResult::workingDirectory() const { return d->workingDirectory; } /*! * \brief Returns the exit status of the command. */ QProcess::ExitStatus ProcessResult::exitStatus() const { return d->exitStatus; } /*! * \brief Returns the exit code of the command. */ int ProcessResult::exitCode() const { return d->exitCode; } /*! * \brief Returns the data the command wrote to the standard output channel. */ QStringList ProcessResult::stdOut() const { return d->stdOut; } /*! * \brief Returns the data the command wrote to the standard error channel. */ QStringList ProcessResult::stdErr() const { return d->stdErr; } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/processresult.h000066400000000000000000000047311266132464200223100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROCESSRESULT_H #define QBS_PROCESSRESULT_H #include "qbs_export.h" #include #include #include #include #include namespace qbs { namespace Internal { class ProcessCommandExecutor; class ProcessResultPrivate; } class QBS_EXPORT ProcessResult { friend class qbs::Internal::ProcessCommandExecutor; public: ProcessResult(); ProcessResult(const ProcessResult &other); ProcessResult &operator=(const ProcessResult &other); ~ProcessResult(); bool success() const; QString executableFilePath() const; QStringList arguments() const; QString workingDirectory() const; QProcess::ExitStatus exitStatus() const; int exitCode() const; QStringList stdOut() const; QStringList stdErr() const; private: QExplicitlySharedDataPointer d; }; } // namespace qbs Q_DECLARE_METATYPE(qbs::ProcessResult) #endif // QBS_PROCESSRESULT_H qbs-src-1.4.5/src/lib/corelib/tools/processresult_p.h000066400000000000000000000037611266132464200226310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROCESSRESULT_P_H #define QBS_PROCESSRESULT_P_H #include #include #include namespace qbs { namespace Internal { class ProcessResultPrivate : public QSharedData { public: bool success; QString executableFilePath; QStringList arguments; QString workingDirectory; QProcess::ExitStatus exitStatus; int exitCode; QStringList stdOut; QStringList stdErr; }; } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.4.5/src/lib/corelib/tools/processutils.cpp000066400000000000000000000065211266132464200224640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "processutils.h" #if defined(Q_OS_WIN) # define PSAPI_VERSION 1 // To use GetModuleFileNameEx from Psapi.lib on all Win versions. # include # include #elif defined(Q_OS_DARWIN) # include #elif defined(Q_OS_LINUX) # include "fileinfo.h" # include # include #elif defined(Q_OS_BSD4) # include # include # include #else # error Missing implementation of processNameByPid for this platform. #endif namespace qbs { namespace Internal { QString processNameByPid(qint64 pid) { #if defined(Q_OS_WIN) HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, DWORD(pid)); if (!hProcess) return QString(); wchar_t buf[MAX_PATH]; const DWORD length = GetModuleFileNameEx(hProcess, NULL, buf, sizeof(buf) / sizeof(wchar_t)); CloseHandle(hProcess); if (!length) return QString(); QString name = QString::fromWCharArray(buf, length); int i = name.lastIndexOf(QLatin1Char('\\')); if (i >= 0) name.remove(0, i + 1); i = name.lastIndexOf(QLatin1Char('.')); if (i >= 0) name.truncate(i); return name; #elif defined(Q_OS_DARWIN) char name[1024]; proc_name(pid, name, sizeof(name) / sizeof(char)); return QString::fromUtf8(name); #elif defined(Q_OS_LINUX) char exePath[64]; char buf[PATH_MAX]; memset(buf, 0, sizeof(buf)); sprintf(exePath, "/proc/%lld/exe", pid); readlink(exePath, buf, sizeof(buf)); return FileInfo::fileName(QString::fromUtf8(buf)); #elif defined(Q_OS_BSD4) kinfo_proc *proc = kinfo_getproc(pid); if (!proc) return QString(); QString name = QString::fromUtf8(proc->ki_comm); free(proc); return name; #else return QString(); #endif } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/processutils.h000066400000000000000000000033551266132464200221330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROCESSUTILS_H #define QBS_PROCESSUTILS_H #include #include namespace qbs { namespace Internal { QString processNameByPid(qint64 pid); } // namespace Internal } // namespace qbs #endif // QBS_PROCESSUTILS_H qbs-src-1.4.5/src/lib/corelib/tools/profile.cpp000066400000000000000000000157151266132464200213720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "profile.h" #include "qbsassert.h" #include "settings.h" #include #include namespace qbs { /*! * \class Profile * \brief The \c Profile class gives access to the settings of a given profile. */ /*! * \enum Profile::KeySelection * This enum type specifies whether to enumerate keys recursively. * \value KeySelectionRecursive Indicates that key enumeration should happen recursively, i.e. * it should go up the base profile chain. * \value KeySelectionNonRecursive Indicates that only keys directly attached to a profile * should be listed. */ /*! * \brief Creates an object giving access to the settings for profile \c name. */ Profile::Profile(const QString &name, Settings *settings) : m_name(name), m_settings(settings) { QBS_ASSERT(name == cleanName(name), return); } bool Profile::exists() const { return !m_settings->allKeysWithPrefix(profileKey()).isEmpty(); } /*! * \brief Returns the value for property \c key in this profile. */ QVariant Profile::value(const QString &key, const QVariant &defaultValue, ErrorInfo *error) const { try { return possiblyInheritedValue(key, defaultValue, QStringList()); } catch (const ErrorInfo &e) { if (error) *error = e; return QVariant(); } } /*! * \brief Gives value \c value to the property \c key in this profile. */ void Profile::setValue(const QString &key, const QVariant &value) { m_settings->setValue(fullyQualifiedKey(key), value); if (key == baseProfileKey()) { QBS_ASSERT(value.toString() == cleanName(value.toString()), return); } } /*! * \brief Removes a key and the associated value from this profile. */ void Profile::remove(const QString &key) { m_settings->remove(fullyQualifiedKey(key)); } /*! * \brief Returns the name of this profile. */ QString Profile::name() const { return m_name; } /*! * \brief Returns all property keys in this profile. * If and only if selection is Profile::KeySelectionRecursive, this will also list keys defined * in base profiles. */ QStringList Profile::allKeys(KeySelection selection, ErrorInfo *error) const { try { return allKeysInternal(selection, QStringList()); } catch (const ErrorInfo &e) { if (error) *error = e; return QStringList(); } } /*! * \brief Returns the name of this profile's base profile. * The returned value is empty if the profile does not have a base profile. */ QString Profile::baseProfile() const { return localValue(baseProfileKey()).toString(); } /*! * \brief Sets a new base profile for this profile. */ void Profile::setBaseProfile(const QString &baseProfile) { setValue(baseProfileKey(), baseProfile); } /*! * \brief Removes this profile's base profile setting. */ void Profile::removeBaseProfile() { remove(baseProfileKey()); } /*! * \brief Removes this profile from the settings. */ void Profile::removeProfile() { m_settings->remove(profileKey()); } /*! * \brief Returns a string suitiable as a profile name. * Removes all dots and replaces them with hyphens. */ QString Profile::cleanName(const QString &name) { QString newName = name; return newName.replace(QLatin1Char('.'), QLatin1Char('-')); } QString Profile::profileKey() const { return QLatin1String("profiles.") + m_name; } QString Profile::baseProfileKey() { return QLatin1String("baseProfile"); } void Profile::checkBaseProfileExistence(const Profile &baseProfile) const { if (!baseProfile.exists()) throw ErrorInfo(Internal::Tr::tr("Profile \"%1\" has a non-existent base profile \"%2\".").arg( name(), baseProfile.name())); } QVariant Profile::localValue(const QString &key) const { return m_settings->value(fullyQualifiedKey(key)); } QString Profile::fullyQualifiedKey(const QString &key) const { return profileKey() + QLatin1Char('.') + key; } QVariant Profile::possiblyInheritedValue(const QString &key, const QVariant &defaultValue, QStringList profileChain) const { extendAndCheckProfileChain(profileChain); const QVariant v = localValue(key); if (v.isValid()) return v; const QString baseProfileName = baseProfile(); if (baseProfileName.isEmpty()) return defaultValue; Profile parentProfile(baseProfileName, m_settings); checkBaseProfileExistence(parentProfile); return parentProfile.possiblyInheritedValue(key, defaultValue, profileChain); } QStringList Profile::allKeysInternal(Profile::KeySelection selection, QStringList profileChain) const { extendAndCheckProfileChain(profileChain); QStringList keys = m_settings->allKeysWithPrefix(profileKey()); if (selection == KeySelectionNonRecursive) return keys; const QString baseProfileName = baseProfile(); if (baseProfileName.isEmpty()) return keys; Profile parentProfile(baseProfileName, m_settings); checkBaseProfileExistence(parentProfile); keys += parentProfile.allKeysInternal(KeySelectionRecursive, profileChain); keys.removeDuplicates(); keys.removeOne(baseProfileKey()); keys.sort(); return keys; } void Profile::extendAndCheckProfileChain(QStringList &chain) const { chain << m_name; if (Q_UNLIKELY(chain.count(m_name) > 1)) { throw ErrorInfo(Internal::Tr::tr("Circular profile inheritance. Cycle is '%1'.") .arg(chain.join(QLatin1String(" -> ")))); } } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/profile.h000066400000000000000000000064441266132464200210360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROFILE_H #define QBS_PROFILE_H #include "qbs_export.h" #include #include #include namespace qbs { class ErrorInfo; class Settings; class QBS_EXPORT Profile { public: explicit Profile(const QString &name, Settings *settings); bool exists() const; QVariant value(const QString &key, const QVariant &defaultValue = QVariant(), ErrorInfo *error = 0) const; void setValue(const QString &key, const QVariant &value); void remove(const QString &key); QString name() const; QString baseProfile() const; void setBaseProfile(const QString &baseProfile); void removeBaseProfile(); void removeProfile(); enum KeySelection { KeySelectionRecursive, KeySelectionNonRecursive }; QStringList allKeys(KeySelection selection, ErrorInfo *error = 0) const; static QString cleanName(const QString &name); private: static QString baseProfileKey(); void checkBaseProfileExistence(const Profile &baseProfile) const; QString profileKey() const; QVariant localValue(const QString &key) const; QString fullyQualifiedKey(const QString &key) const; QVariant possiblyInheritedValue(const QString &key, const QVariant &defaultValue, QStringList profileChain) const; QStringList allKeysInternal(KeySelection selection, QStringList profileChain) const; void extendAndCheckProfileChain(QStringList &chain) const; QString m_name; Settings *m_settings; }; namespace Internal { // Exported for autotests. class QBS_EXPORT TemporaryProfile { public: TemporaryProfile(const QString &name, Settings *settings) : p(name, settings) {} ~TemporaryProfile() { p.removeProfile(); } Profile p; }; } // namespace Internal } // namespace qbs #endif // Header guard qbs-src-1.4.5/src/lib/corelib/tools/progressobserver.cpp000066400000000000000000000073521266132464200233440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "progressobserver.h" namespace qbs { namespace Internal { /*! * \class ProgressObserver * The \c ProgressObserver class is used in long running qbs operations. It serves two purposes: * Firstly, it allows operations to indicate progress to a client. Secondly, a client can * signal to an operation that is should exit prematurely. * Clients of the qbs library are supposed to subclass this class and implement the virtual * functions in a way that lets users know about the current operation and its progress. */ /*! * \fn virtual void initialize(const QString &task, int maximum) = 0 * \brief Indicates that a new operation is starting. * Library code calls this function to indicate that it is starting a new task. * The \a task parameter is a textual description of that task suitable for presentation to a user. * The \a maximum parameter is an estimate of the maximum effort the operation is going to take. * This is helpful if the client wants to set up some sort of progress bar showing the * percentage of the work already done. */ /*! * \fn virtual void setProgressValue(int value) = 0 * \brief Sets the new progress value. * Library code calls this function to indicate that the current operation has progressed. * It will try hard to ensure that \a value will not exceed \c maximum(). * \sa ProgressObserver::maximum(). */ /*! * \fn virtual int progressValue() = 0 * \brief The current progress value. * Will typically reflect the \a value from the last call to \c setProgressValue() and should not * exceed \c maximum(). * \sa setProgressvalue() * \sa maximum() */ void ProgressObserver::incrementProgressValue(int increment) { setProgressValue(progressValue() + increment); } /*! * \fn virtual bool canceled() const = 0 * \brief Indicates whether the current operation should be canceled. * Library code will periodically call this function and abort the current operation * if it returns true. */ /*! * \fn virtual int maximum() const = 0 * \brief The expected maximum progress value. * This will typically be the value of \c maximum passed to \c initialize(). * \sa ProgressObserver::initialize() */ void ProgressObserver::setFinished() { setProgressValue(maximum()); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/progressobserver.h000066400000000000000000000043421266132464200230050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROGRESSOBSERVER_H #define QBS_PROGRESSOBSERVER_H #include QT_BEGIN_NAMESPACE class QString; QT_END_NAMESPACE namespace qbs { namespace Internal { class ProgressObserver { public: virtual ~ProgressObserver() { } virtual void initialize(const QString &task, int maximum) = 0; virtual void setProgressValue(int value) = 0; virtual int progressValue() = 0; virtual bool canceled() const = 0; virtual void setMaximum(int maximum) = 0; virtual int maximum() const = 0; void incrementProgressValue(int increment = 1); // Call this to ensure that the progress bar always goes to 100%. void setFinished(); }; } // namespace Internal } // namespace qbs #endif // QBS_PROGRESSOBSERVER_H qbs-src-1.4.5/src/lib/corelib/tools/projectgeneratormanager.cpp000066400000000000000000000051351266132464200246350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "projectgeneratormanager.h" #include #include #include #include #include #include namespace qbs { using namespace Internal; ProjectGeneratorManager::~ProjectGeneratorManager() { foreach (QLibrary * const lib, m_libs) { lib->unload(); delete lib; } } ProjectGeneratorManager *ProjectGeneratorManager::instance() { static ProjectGeneratorManager generatorPlugin; return &generatorPlugin; } ProjectGeneratorManager::ProjectGeneratorManager() { QList > generators; foreach (QSharedPointer generator, generators) { m_generators[generator->generatorName()] = generator; } } QStringList ProjectGeneratorManager::loadedGeneratorNames() { return instance()->m_generators.keys(); } QSharedPointer ProjectGeneratorManager::findGenerator(const QString &generatorName) { return instance()->m_generators.value(generatorName); } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/projectgeneratormanager.h000066400000000000000000000045011266132464200242760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROJECTGENERATORMANAGER_H #define QBS_PROJECTGENERATORMANAGER_H #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QLibrary; QT_END_NAMESPACE namespace qbs { class ProjectGenerator; namespace Internal { class Logger; } class QBS_EXPORT ProjectGeneratorManager { public: ~ProjectGeneratorManager(); static ProjectGeneratorManager *instance(); static QStringList loadedGeneratorNames(); static QSharedPointer findGenerator(const QString &generatorName); private: ProjectGeneratorManager(); private: QList m_libs; QMap > m_generators; }; } // namespace qbs #endif qbs-src-1.4.5/src/lib/corelib/tools/propertyfinder.cpp000066400000000000000000000054001266132464200227740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "propertyfinder.h" #include "qbsassert.h" #include namespace qbs { namespace Internal { QVariantList PropertyFinder::propertyValues(const QVariantMap &properties, const QString &moduleName, const QString &key) { QVariant v = propertyValue(properties, moduleName, key); return v.toList(); } QVariant PropertyFinder::propertyValue(const QVariantMap &properties, const QString &moduleName, const QString &key) { m_moduleName = moduleName; m_key = key; m_values.clear(); findModuleValues(properties); return m_values.isEmpty() ? QVariant() : m_values.first(); } void PropertyFinder::findModuleValues(const QVariantMap &properties) { const QVariantMap moduleProperties = properties.value(QLatin1String("modules")).toMap(); const QVariantMap::const_iterator modIt = moduleProperties.find(m_moduleName); if (modIt != moduleProperties.constEnd()) { const QVariantMap moduleMap = modIt->toMap(); const QVariant property = moduleMap.value(m_key); addToList(property); } } void PropertyFinder::addToList(const QVariant &value) { if (!value.isNull() && !m_values.contains(value)) m_values << value; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/propertyfinder.h000066400000000000000000000044061266132464200224460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PROPERTY_FINDER_H #define QBS_PROPERTY_FINDER_H #include #include namespace qbs { namespace Internal { class PropertyFinder { public: QVariantList propertyValues(const QVariantMap &properties, const QString &moduleName, const QString &key); // Note that this can still be a list if the property type itself is one. QVariant propertyValue(const QVariantMap &properties, const QString &moduleName, const QString &key); private: void findModuleValues(const QVariantMap &properties); void addToList(const QVariant &value); QString m_moduleName; QString m_key; QVariantList m_values; }; } // namespace Internal } // namespace qbs #endif // Include guard qbs-src-1.4.5/src/lib/corelib/tools/qbs_export.h000066400000000000000000000034021266132464200215530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_EXPORT_H #define QBS_EXPORT_H #include #ifdef QBS_STATIC_LIB # define QBS_EXPORT #else # ifdef QBS_LIBRARY # define QBS_EXPORT Q_DECL_EXPORT # else # define QBS_EXPORT Q_DECL_IMPORT # endif #endif #endif // Include guard. qbs-src-1.4.5/src/lib/corelib/tools/qbsassert.cpp000066400000000000000000000040241266132464200217300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "qbsassert.h" #include "error.h" #include namespace qbs { namespace Internal { void writeAssertLocation(const char *condition, const char *file, int line) { qDebug("SOFT ASSERT: %s in %s:%d", condition, file, line); } void throwAssertLocation(const char *condition, const char *file, int line) { throw ErrorInfo(QString::fromLatin1("ASSERT: %1").arg(QLatin1String(condition)), CodeLocation(QString::fromLocal8Bit(file), line, -1, false), true); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/qbsassert.h000066400000000000000000000047011266132464200213770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_QBSASSERT_H #define QBS_QBSASSERT_H #include "qbs_export.h" // TODO: Remove once we require 5.3. #ifndef Q_NORETURN #define Q_NORETURN #endif namespace qbs { namespace Internal { QBS_EXPORT void writeAssertLocation(const char *condition, const char *file, int line); QBS_EXPORT Q_NORETURN void throwAssertLocation(const char *condition, const char *file, int line); } // namespace Internal } // namespace qbs #define QBS_ASSERT(cond, action)\ if (Q_LIKELY(cond)) {} else {\ ::qbs::Internal::writeAssertLocation(#cond, __FILE__, __LINE__); action;\ } do {} while (0) // The do {} while (0) is here to enforce the use of a semicolon after QBS_ASSERT. // action can also be continue or break. Copied from qtcassert.h in Qt Creator. #define QBS_CHECK(cond)\ do {\ if (Q_LIKELY(cond)) {} else {\ ::qbs::Internal::throwAssertLocation(#cond, __FILE__, __LINE__);\ }\ } while (0) #endif // QBS_QBSASSERT_H qbs-src-1.4.5/src/lib/corelib/tools/qttools.cpp000066400000000000000000000033251266132464200214310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "qttools.h" QT_BEGIN_NAMESPACE uint qHash(const QStringList &list) { uint s = 0; foreach (const QString &n, list) s ^= qHash(n) + 0x9e3779b9 + (s << 6) + (s >> 2); return s; } QT_END_NAMESPACE qbs-src-1.4.5/src/lib/corelib/tools/qttools.h000066400000000000000000000032531266132464200210760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBSQTTOOLS_H #define QBSQTTOOLS_H #include #include QT_BEGIN_NAMESPACE uint qHash(const QStringList &list); QT_END_NAMESPACE #endif // QBSQTTOOLS_H qbs-src-1.4.5/src/lib/corelib/tools/scannerpluginmanager.cpp000066400000000000000000000103101266132464200241170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "scannerpluginmanager.h" #include #include #include #include #include #include namespace qbs { namespace Internal { ScannerPluginManager::~ScannerPluginManager() { foreach (QLibrary * const lib, m_libs) { lib->unload(); delete lib; } } ScannerPluginManager *ScannerPluginManager::instance() { static ScannerPluginManager scannerPlugin; return &scannerPlugin; } ScannerPluginManager::ScannerPluginManager() { } QList ScannerPluginManager::scannersForFileTag(const FileTag &fileTag) { return instance()->m_scannerPlugins.value(fileTag); } void ScannerPluginManager::loadPlugins(const QStringList &pluginPaths, const Logger &logger) { QStringList filters; if (HostOsInfo::isWindowsHost()) filters << QLatin1String("*.dll"); else if (HostOsInfo::isOsxHost()) filters << QLatin1String("*.dylib"); else filters << QLatin1String("*.so"); foreach (const QString &pluginPath, pluginPaths) { logger.qbsTrace() << QString::fromLocal8Bit("pluginmanager: loading plugins from '%1'.") .arg(QDir::toNativeSeparators(pluginPath)); QDirIterator it(pluginPath, filters, QDir::Files); while (it.hasNext()) { const QString fileName = it.next(); QScopedPointer lib(new QLibrary(fileName)); if (!lib->load()) { logger.qbsWarning() << Tr::tr("Pluginmanager: Cannot load plugin '%1': %2") .arg(QDir::toNativeSeparators(fileName), lib->errorString()); continue; } getScanners_f getScanners = reinterpret_cast(lib->resolve("getScanners")); if (!getScanners) { logger.qbsWarning() << Tr::tr("Pluginmanager: Cannot resolve " "symbol in '%1'.").arg(QDir::toNativeSeparators(fileName)); continue; } ScannerPlugin **plugins = getScanners(); if (plugins == 0) { logger.qbsWarning() << Tr::tr("pluginmanager: no scanners " "returned from '%1'.").arg(QDir::toNativeSeparators(fileName)); continue; } logger.qbsTrace() << QString::fromLocal8Bit("pluginmanager: scanner plugin '%1' " "loaded.").arg(QDir::toNativeSeparators(fileName)); for (int i = 0; plugins[i] != 0; ++i) m_scannerPlugins[FileTag(plugins[i]->fileTag)] += plugins[i]; m_libs.append(lib.take()); } } } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/scannerpluginmanager.h000066400000000000000000000042731266132464200235770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_PLUGINS_H #define QBS_PLUGINS_H #include #include #include #include QT_BEGIN_NAMESPACE class QLibrary; QT_END_NAMESPACE namespace qbs { namespace Internal { class Logger; class ScannerPluginManager { public: ~ScannerPluginManager(); static ScannerPluginManager *instance(); static QList scannersForFileTag(const FileTag &fileTag); void loadPlugins(const QStringList &paths, const Logger &logger); private: ScannerPluginManager(); private: QList m_libs; QHash > m_scannerPlugins; }; } // namespace Internal } // namespace qbs #endif qbs-src-1.4.5/src/lib/corelib/tools/scripttools.cpp000066400000000000000000000110401266132464200223020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "scripttools.h" #include #include #include QT_BEGIN_NAMESPACE QDataStream &operator<< (QDataStream &s, const QScriptProgram &script) { s << script.sourceCode() << script.fileName() << script.firstLineNumber(); return s; } QDataStream &operator>> (QDataStream &s, QScriptProgram &script) { QString fileName, sourceCode; int lineNumber; s >> sourceCode >> fileName >> lineNumber; script = QScriptProgram(sourceCode, fileName, lineNumber); return s; } QT_END_NAMESPACE namespace qbs { QString toJSLiteral(const bool b) { return b ? QLatin1String("true") : QLatin1String("false"); } QString toJSLiteral(const QString &str) { QString js = str; js.replace(QRegExp(QLatin1String("([\\\\\"])")), QLatin1String("\\\\1")); js.prepend(QLatin1Char('"')); js.append(QLatin1Char('"')); return js; } QString toJSLiteral(const QStringList &strs) { QString js = QLatin1String("["); for (int i = 0; i < strs.count(); ++i) { if (i != 0) js.append(QLatin1String(", ")); js.append(toJSLiteral(strs.at(i))); } js.append(QLatin1Char(']')); return js; } QString toJSLiteral(const QVariant &val) { if (!val.isValid()) return QLatin1String("undefined"); if (val.type() == QVariant::List || val.type() == QVariant::StringList) { QString res; foreach (const QVariant &child, val.toList()) { if (res.length()) res.append(QLatin1String(", ")); res.append(toJSLiteral(child)); } res.prepend(QLatin1Char('[')); res.append(QLatin1Char(']')); return res; } if (val.type() == QVariant::Map) { const QVariantMap &vm = val.toMap(); QString str = QLatin1String("{"); for (QVariantMap::const_iterator it = vm.begin(); it != vm.end(); ++it) { if (it != vm.begin()) str += QLatin1Char(','); str += toJSLiteral(it.key()) + QLatin1Char(':') + toJSLiteral(it.value()); } str += QLatin1Char('}'); return str; } if (val.type() == QVariant::Bool) return val.toBool() ? QLatin1String("true") : QLatin1String("false"); if (val.canConvert(QVariant::String)) return toJSLiteral(val.toString()); return QString::fromLatin1("Unconvertible type %1").arg(QLatin1String(val.typeName())); } namespace Internal { void setConfigProperty(QVariantMap &cfg, const QStringList &name, const QVariant &value) { if (name.length() == 1) { cfg.insert(name.first(), value); } else { QVariant &subCfg = cfg[name.first()]; QVariantMap subCfgMap = subCfg.toMap(); setConfigProperty(subCfgMap, name.mid(1), value); subCfg = subCfgMap; } } QVariant getConfigProperty(const QVariantMap &cfg, const QStringList &name) { if (name.length() == 1) return cfg.value(name.first()); else return getConfigProperty(cfg.value(name.first()).toMap(), name.mid(1)); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/scripttools.h000066400000000000000000000067351266132464200217660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_SCRIPTTOOLS_H #define QBS_SCRIPTTOOLS_H #include #include #include #include #include #include QT_BEGIN_NAMESPACE QDataStream &operator<< (QDataStream &s, const QScriptProgram &script); QDataStream &operator>> (QDataStream &s, QScriptProgram &script); QT_END_NAMESPACE namespace qbs { QBS_EXPORT QString toJSLiteral(const bool b); QBS_EXPORT QString toJSLiteral(const QString &str); QBS_EXPORT QString toJSLiteral(const QStringList &strs); QBS_EXPORT QString toJSLiteral(const QVariant &val); namespace Internal { template QScriptValue toScriptValue(QScriptEngine *scriptEngine, const C &container) { QScriptValue v = scriptEngine->newArray(container.count()); int i = 0; foreach (const typename C::value_type &item, container) v.setProperty(i++, scriptEngine->toScriptValue(item)); return v; } void setConfigProperty(QVariantMap &cfg, const QStringList &name, const QVariant &value); QVariant getConfigProperty(const QVariantMap &cfg, const QStringList &name); /** * @brief push/pop a scope on a QScriptContext the RAII way. */ class ScriptContextScopePusher { public: ScriptContextScopePusher(QScriptContext *scriptContext, const QScriptValue &value) : m_scriptContext(scriptContext) { m_scriptContext->pushScope(value); } ~ScriptContextScopePusher() { m_scriptContext->popScope(); } private: QScriptContext *m_scriptContext; }; template void attachPointerTo(QScriptValue &scriptValue, T *ptr) { QVariant v; v.setValue(reinterpret_cast(ptr)); scriptValue.setData(scriptValue.engine()->newVariant(v)); } template T *attachedPointer(const QScriptValue &scriptValue) { const quintptr ptr = scriptValue.data().toVariant().value(); return reinterpret_cast(ptr); } } // namespace Internal } // namespace qbs #endif // QBS_SCRIPTTOOLS_H qbs-src-1.4.5/src/lib/corelib/tools/settings.cpp000066400000000000000000000111611266132464200215610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "settings.h" #include "error.h" #include #include #include #include namespace qbs { using namespace Internal; static QSettings::Format format() { return HostOsInfo::isWindowsHost() ? QSettings::IniFormat : QSettings::NativeFormat; } static QSettings *createQSettings(const QString &baseDir) { return baseDir.isEmpty() ? new QSettings(format(), QSettings::UserScope, QLatin1String("QtProject"), QLatin1String("qbs")) : new QSettings(baseDir + QLatin1String("/qbs.conf"), format()); } Settings::Settings(const QString &baseDir) : m_settings(createQSettings(baseDir)), m_baseDir(baseDir) { // Actual qbs settings are stored transparently within a group, because QSettings // can see non-qbs fallback settings e.g. from QtProject that we're not interested in. m_settings->beginGroup(QLatin1String("org/qt-project/qbs")); } Settings::~Settings() { delete m_settings; } QVariant Settings::value(const QString &key, const QVariant &defaultValue) const { return m_settings->value(internalRepresentation(key), defaultValue); } QStringList Settings::allKeys() const { QStringList keys = m_settings->allKeys(); fixupKeys(keys); return keys; } QStringList Settings::directChildren(const QString &parentGroup) { m_settings->beginGroup(internalRepresentation(parentGroup)); QStringList children = m_settings->childGroups(); children << m_settings->childKeys(); m_settings->endGroup(); fixupKeys(children); return children; } QStringList Settings::allKeysWithPrefix(const QString &group) const { m_settings->beginGroup(internalRepresentation(group)); QStringList keys = m_settings->allKeys(); m_settings->endGroup(); fixupKeys(keys); return keys; } void Settings::setValue(const QString &key, const QVariant &value) { m_settings->setValue(internalRepresentation(key), value); } void Settings::remove(const QString &key) { m_settings->remove(internalRepresentation(key)); } void Settings::clear() { m_settings->clear(); } void Settings::sync() { m_settings->sync(); } QString Settings::defaultProfile() const { return value(QLatin1String("defaultProfile")).toString(); } QStringList Settings::profiles() const { m_settings->beginGroup(QLatin1String("profiles")); QStringList result = m_settings->childGroups(); m_settings->endGroup(); return result; } QString Settings::fileName() const { return m_settings->fileName(); } QString Settings::internalRepresentation(const QString &externalKey) const { QString internalKey = externalKey; return internalKey.replace(QLatin1Char('.'), QLatin1Char('/')); } QString Settings::externalRepresentation(const QString &internalKey) const { QString externalKey = internalKey; return externalKey.replace(QLatin1Char('/'), QLatin1Char('.')); } void Settings::fixupKeys(QStringList &keys) const { keys.sort(); keys.removeDuplicates(); for (QStringList::Iterator it = keys.begin(); it != keys.end(); ++it) *it = externalRepresentation(*it); } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/settings.h000066400000000000000000000052241266132464200212310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_SETTINGS_H #define QBS_SETTINGS_H #include "qbs_export.h" #include #include QT_BEGIN_NAMESPACE class QSettings; QT_END_NAMESPACE namespace qbs { class QBS_EXPORT Settings { public: Settings(const QString &baseDir); // Empty string means "system default" ~Settings(); QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const; QStringList allKeys() const; QStringList directChildren(const QString &parentGroup); // Keys and groups. QStringList allKeysWithPrefix(const QString &group) const; void setValue(const QString &key, const QVariant &value); void remove(const QString &key); void clear(); void sync(); QString defaultProfile() const; QStringList profiles() const; QString fileName() const; QString baseDirectoy() const { return m_baseDir; } private: QString internalRepresentation(const QString &externalKey) const; QString externalRepresentation(const QString &internalKey) const; void fixupKeys(QStringList &keys) const; QSettings * const m_settings; const QString m_baseDir; }; } // namespace qbs #endif // QBS_SETTINGS_H qbs-src-1.4.5/src/lib/corelib/tools/settingsmodel.cpp000066400000000000000000000273761266132464200226210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "settingsmodel.h" #include #include #ifdef QT_GUI_LIB #include #endif #include #include #include namespace qbs { namespace Internal { struct Node { Node() : parent(0), isFromSettings(true) {} ~Node() { qDeleteAll(children); } QString uniqueChildName() const; bool hasDirectChildWithName(const QString &name) const; QString name; QString value; Node *parent; QList children; bool isFromSettings; }; QString Node::uniqueChildName() const { QString newName = QLatin1String("newkey"); bool unique; do { unique = true; foreach (const Node *childNode, children) { if (childNode->name == newName) { unique = false; newName += QLatin1Char('_'); break; } } } while (!unique); return newName; } bool Node::hasDirectChildWithName(const QString &name) const { foreach (const Node * const child, children) { if (child->name == name) return true; } return false; } } // namespace Internal using Internal::Node; class SettingsModel::SettingsModelPrivate { public: SettingsModelPrivate() : dirty(false), editable(true) {} void readSettings(); void addNodeFromSettings(Node *parentNode, const QString &fullyQualifiedName); void addNode(Node *parentNode, const QString ¤tNamePart, const QStringList &restOfName, const QVariant &value); void doSave(const Node *node, const QString &prefix); Node *indexToNode(const QModelIndex &index); Node rootNode; QScopedPointer settings; QVariantMap additionalProperties; bool dirty; bool editable; }; SettingsModel::SettingsModel(const QString &settingsDir, QObject *parent) : QAbstractItemModel(parent), d(new SettingsModelPrivate) { d->settings.reset(new qbs::Settings(settingsDir)); d->readSettings(); } SettingsModel::~SettingsModel() { delete d; } void SettingsModel::reload() { beginResetModel(); d->readSettings(); endResetModel(); } void SettingsModel::save() { if (!d->dirty) return; d->settings->clear(); d->doSave(&d->rootNode, QString()); d->dirty = false; } void SettingsModel::addNewKey(const QModelIndex &parent) { Node *parentNode = d->indexToNode(parent); if (!parentNode) return; Node * const newNode = new Node; newNode->parent = parentNode; newNode->name = parentNode->uniqueChildName(); beginInsertRows(parent, parentNode->children.count(), parentNode->children.count()); parentNode->children << newNode; endInsertRows(); d->dirty = true; } void SettingsModel::removeKey(const QModelIndex &index) { Node * const node = d->indexToNode(index); if (!node || node == &d->rootNode) return; const int positionInParent = node->parent->children.indexOf(node); beginRemoveRows(parent(index), positionInParent, positionInParent); node->parent->children.removeAt(positionInParent); delete node; endRemoveRows(); d->dirty = true; } bool SettingsModel::hasUnsavedChanges() const { return d->dirty; } void SettingsModel::setEditable(bool isEditable) { d->editable = isEditable; } void SettingsModel::setAdditionalProperties(const QVariantMap &properties) { d->additionalProperties = properties; reload(); } Qt::ItemFlags SettingsModel::flags(const QModelIndex &index) const { if (!index.isValid()) return Qt::ItemFlags(); const Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; if (index.column() == keyColumn()) { if (d->editable) return flags | Qt::ItemIsEditable; return flags; } if (index.column() == valueColumn()) { const Node * const node = d->indexToNode(index); if (!node) return Qt::ItemFlags(); // Only leaf nodes have values. return d->editable && node->children.isEmpty() ? flags | Qt::ItemIsEditable : flags; } return Qt::ItemFlags(); } QVariant SettingsModel::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation != Qt::Horizontal) return QVariant(); if (role != Qt::DisplayRole) return QVariant(); if (section == keyColumn()) return tr("Key"); if (section == valueColumn()) return tr("Value"); return QVariant(); } int SettingsModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); return 2; } int SettingsModel::rowCount(const QModelIndex &parent) const { if (parent.column() > 0) return 0; const Node * const node = d->indexToNode(parent); Q_ASSERT(node); return node->children.count(); } QVariant SettingsModel::data(const QModelIndex &index, int role) const { if (role != Qt::DisplayRole && role != Qt::EditRole && role != Qt::ForegroundRole) return QVariant(); const Node * const node = d->indexToNode(index); if (!node) return QVariant(); if (role == Qt::ForegroundRole) { #ifdef QT_GUI_LIB if (index.column() == valueColumn() && !node->isFromSettings) return QBrush(Qt::red); #endif return QVariant(); } if (index.column() == keyColumn()) return node->name; if (index.column() == valueColumn() && node->children.isEmpty()) return node->value; return QVariant(); } bool SettingsModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!index.isValid() || role != Qt::EditRole) return false; Node * const node = d->indexToNode(index); if (!node) return false; const QString valueString = value.toString(); QString *toChange = 0; if (index.column() == keyColumn() && !valueString.isEmpty() && !node->parent->hasDirectChildWithName(valueString)) { toChange = &node->name; } else if (index.column() == valueColumn() && valueString != node->value) { toChange = &node->value; } if (toChange) { *toChange = valueString; emit dataChanged(index, index); d->dirty = true; } return toChange; } QModelIndex SettingsModel::index(int row, int column, const QModelIndex &parent) const { const Node * const parentNode = d->indexToNode(parent); Q_ASSERT(parentNode); if (parentNode->children.count() <= row) return QModelIndex(); return createIndex(row, column, parentNode->children.at(row)); } QModelIndex SettingsModel::parent(const QModelIndex &child) const { Node * const childNode = static_cast(child.internalPointer()); Q_ASSERT(childNode); Node * const parentNode = childNode->parent; if (parentNode == &d->rootNode) return QModelIndex(); const Node * const grandParentNode = parentNode->parent; Q_ASSERT(grandParentNode); return createIndex(grandParentNode->children.indexOf(parentNode), 0, parentNode); } void SettingsModel::SettingsModelPrivate::readSettings() { qDeleteAll(rootNode.children); rootNode.children.clear(); foreach (const QString &topLevelKey, settings->directChildren(QString())) addNodeFromSettings(&rootNode, topLevelKey); for (QVariantMap::ConstIterator it = additionalProperties.constBegin(); it != additionalProperties.constEnd(); ++it) { const QStringList nameAsList = it.key().split(QLatin1Char('.'), QString::SkipEmptyParts); addNode(&rootNode, nameAsList.first(), nameAsList.mid(1), it.value()); } dirty = false; } static Node *createNode(Node *parentNode, const QString &name) { Node * const node = new Node; node->name = name; node->parent = parentNode; parentNode->children << node; return node; } void SettingsModel::SettingsModelPrivate::addNodeFromSettings(Node *parentNode, const QString &fullyQualifiedName) { const QString &nodeName = fullyQualifiedName.mid(fullyQualifiedName.lastIndexOf(QLatin1Char('.')) + 1); Node * const node = createNode(parentNode, nodeName); node->value = settingsValueToRepresentation(settings->value(fullyQualifiedName)); foreach (const QString &childKey, settings->directChildren(fullyQualifiedName)) addNodeFromSettings(node, fullyQualifiedName + QLatin1Char('.') + childKey); dirty = true; } void SettingsModel::SettingsModelPrivate::addNode(qbs::Internal::Node *parentNode, const QString ¤tNamePart, const QStringList &restOfName, const QVariant &value) { Node *currentNode = 0; foreach (Node * const n, parentNode->children) { if (n->name == currentNamePart) { currentNode = n; break; } } if (!currentNode) currentNode = createNode(parentNode, currentNamePart); if (restOfName.isEmpty()) { currentNode->value = settingsValueToRepresentation(value); currentNode->isFromSettings = false; } else { addNode(currentNode, restOfName.first(), restOfName.mid(1), value); } } void SettingsModel::SettingsModelPrivate::doSave(const Node *node, const QString &prefix) { if (node->children.isEmpty()) { settings->setValue(prefix + node->name, representationToSettingsValue(node->value)); return; } const QString newPrefix = prefix + node->name + QLatin1Char('.'); foreach (const Node * const child, node->children) doSave(child, newPrefix); } Node *SettingsModel::SettingsModelPrivate::indexToNode(const QModelIndex &index) { return index.isValid() ? static_cast(index.internalPointer()) : &rootNode; } QString settingsValueToRepresentation(const QVariant &value) { return toJSLiteral(value); } static QVariant variantFromString(const QString &str) { // ### use Qt5's JSON reader at some point. QScriptEngine engine; QScriptValue sv = engine.evaluate(QLatin1String("(function(){return ") + str + QLatin1String(";})()")); if (sv.isError()) return QVariant(); return sv.toVariant(); } QVariant representationToSettingsValue(const QString &representation) { const QVariant variant = variantFromString(representation); if (variant.isValid()) return variant; // If it's not valid JavaScript, interpret the value as a string. return representation; } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/settingsmodel.h000066400000000000000000000057401266132464200222550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #include #include namespace qbs { class QBS_EXPORT SettingsModel : public QAbstractItemModel { Q_OBJECT public: SettingsModel(const QString &settingsDir, QObject *parent = 0); ~SettingsModel(); int keyColumn() const { return 0; } int valueColumn() const { return 1; } bool hasUnsavedChanges() const; void setEditable(bool isEditable); void setAdditionalProperties(const QVariantMap &properties); // Flat map. void reload(); void save(); void addNewKey(const QModelIndex &parent); void removeKey(const QModelIndex &index); Qt::ItemFlags flags(const QModelIndex &index) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; int rowCount(const QModelIndex &parent = QModelIndex()) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; QModelIndex parent(const QModelIndex &child) const; private: class SettingsModelPrivate; SettingsModelPrivate * const d; }; QBS_EXPORT QString settingsValueToRepresentation(const QVariant &value); QBS_EXPORT QVariant representationToSettingsValue(const QString &representation); } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/setupprojectparameters.cpp000066400000000000000000000435521266132464200245450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "setupprojectparameters.h" #include #include #include #include #include #include #include namespace qbs { namespace Internal { /*! * \class SetupProjectParameters * \brief The \c SetupProjectParameters class comprises data required to set up a qbs project. */ class SetupProjectParametersPrivate : public QSharedData { public: SetupProjectParametersPrivate() : ignoreDifferentProjectFilePath(false) , dryRun(false) , logElapsedTime(false) , restoreBehavior(SetupProjectParameters::RestoreAndTrackChanges) , propertyCheckingMode(SetupProjectParameters::PropertyCheckingRelaxed) , environment(QProcessEnvironment::systemEnvironment()) { } QString projectFilePath; QString topLevelProfile; QString buildVariant; QString buildRoot; QStringList searchPaths; QStringList pluginPaths; QString libexecPath; QString settingsBaseDir; QVariantMap overriddenValues; QVariantMap buildConfiguration; mutable QVariantMap buildConfigurationTree; mutable QVariantMap overriddenValuesTree; mutable QVariantMap finalBuildConfigTree; bool ignoreDifferentProjectFilePath; bool dryRun; bool logElapsedTime; SetupProjectParameters::RestoreBehavior restoreBehavior; SetupProjectParameters::PropertyCheckingMode propertyCheckingMode; QProcessEnvironment environment; }; } // namespace Internal SetupProjectParameters::SetupProjectParameters() : d(new Internal::SetupProjectParametersPrivate) { } SetupProjectParameters::SetupProjectParameters(const SetupProjectParameters &other) : d(other.d) { } SetupProjectParameters::~SetupProjectParameters() { } SetupProjectParameters &SetupProjectParameters::operator=(const SetupProjectParameters &other) { d = other.d; return *this; } /*! * \brief Returns the name of the top-level profile for building the project. */ QString SetupProjectParameters::topLevelProfile() const { return d->topLevelProfile; } /*! * \brief Sets the top-level profile for building the project. */ void SetupProjectParameters::setTopLevelProfile(const QString &profile) { d->buildConfigurationTree.clear(); d->finalBuildConfigTree.clear(); d->topLevelProfile = profile; } /*! * \brief Returns the build variant for building the project. */ QString SetupProjectParameters::buildVariant() const { return d->buildVariant; } /*! * \brief Sets the build variant for building the project. * \param buildVariant "debug" or "release" */ void SetupProjectParameters::setBuildVariant(const QString &buildVariant) { d->buildConfigurationTree.clear(); d->finalBuildConfigTree.clear(); d->buildVariant = buildVariant; } /*! * \brief Returns the absolute path to the qbs project file. * This file typically has a ".qbs" suffix. */ QString SetupProjectParameters::projectFilePath() const { return d->projectFilePath; } /*! * \brief Sets the path to the main project file. * \note The argument must be an absolute file path. */ void SetupProjectParameters::setProjectFilePath(const QString &projectFilePath) { d->projectFilePath = projectFilePath; const QString canonicalProjectFilePath = QFileInfo(d->projectFilePath).canonicalFilePath(); if (!canonicalProjectFilePath.isEmpty()) d->projectFilePath = projectFilePath; } /*! * \brief Returns the base path of where to put the build artifacts and store the build graph. */ QString SetupProjectParameters::buildRoot() const { return d->buildRoot; } /*! * \brief Sets the base path of where to put the build artifacts and store the build graph. * The same base path can be used for several build profiles of the same project without them * interfering with each other. * It might look as if this parameter would not be needed at the time of setting up the project, * but keep in mind that the project information could already exist on disk, in which case * loading it will be much faster than setting up the project from scratch. * \note The argument must be an absolute path to a directory. */ void SetupProjectParameters::setBuildRoot(const QString &buildRoot) { d->buildRoot = buildRoot; const QString canonicalBuildRoot = QFileInfo(d->buildRoot).canonicalFilePath(); if (!canonicalBuildRoot.isEmpty()) d->buildRoot = canonicalBuildRoot; } /*! * \brief Where to look for modules and items to import. */ QStringList SetupProjectParameters::searchPaths() const { return d->searchPaths; } /*! * \brief Sets the information about where to look for modules and items to import. * \note The elements of the list must be absolute paths to directories. */ void SetupProjectParameters::setSearchPaths(const QStringList &searchPaths) { d->searchPaths = searchPaths; } /*! * \brief Where to look for plugins. */ QStringList SetupProjectParameters::pluginPaths() const { return d->pluginPaths; } /*! * \brief Sets the information about where to look for plugins. * \note The elements of the list must be absolute paths to directories. */ void SetupProjectParameters::setPluginPaths(const QStringList &pluginPaths) { d->pluginPaths = pluginPaths; } /*! * \brief Where to look for internal binaries. */ QString SetupProjectParameters::libexecPath() const { return d->libexecPath; } /*! * \brief Sets the information about where to look for internal binaries. * \note \p libexecPath must be an absolute path. */ void SetupProjectParameters::setLibexecPath(const QString &libexecPath) { d->libexecPath = libexecPath; } /*! * \brief The base directory for qbs settings. * This value is used to locate profiles and preferences. */ QString SetupProjectParameters::settingsDirectory() const { return d->settingsBaseDir; } /*! * \brief Sets the base directory for qbs settings. * \param settingsBaseDir Will be used to locate profiles and preferences. */ void SetupProjectParameters::setSettingsDirectory(const QString &settingsBaseDir) { d->settingsBaseDir = settingsBaseDir; } /*! * Returns the overridden values of the build configuration. */ QVariantMap SetupProjectParameters::overriddenValues() const { return d->overriddenValues; } /*! * Set the overridden values of the build configuration. */ void SetupProjectParameters::setOverriddenValues(const QVariantMap &values) { // warn if somebody tries to set a build configuration tree: for (QVariantMap::const_iterator i = values.constBegin(); i != values.constEnd(); ++i) { QBS_ASSERT(i.value().type() != QVariant::Map, return); } d->overriddenValues = values; d->overriddenValuesTree.clear(); d->finalBuildConfigTree.clear(); } static void provideValuesTree(const QVariantMap &values, QVariantMap *valueTree) { if (!valueTree->isEmpty() || values.isEmpty()) return; valueTree->clear(); for (QVariantMap::const_iterator it = values.constBegin(); it != values.constEnd(); ++it) { const QString name = it.key(); int idx = name.lastIndexOf(QLatin1Char('.')); const QStringList nameElements = (idx == -1) ? QStringList() << name : QStringList() << name.left(idx) << name.mid(idx + 1); Internal::setConfigProperty(*valueTree, nameElements, it.value()); } } QVariantMap SetupProjectParameters::overriddenValuesTree() const { provideValuesTree(d->overriddenValues, &d->overriddenValuesTree); return d->overriddenValuesTree; } /*! * \brief Returns the build configuration. * Overridden values are not taken into account. */ QVariantMap SetupProjectParameters::buildConfiguration() const { return d->buildConfiguration; } /*! * \brief Returns the build configuration in tree form. * Overridden values are not taken into account. */ QVariantMap SetupProjectParameters::buildConfigurationTree() const { provideValuesTree(d->buildConfiguration, &d->buildConfigurationTree); return d->buildConfigurationTree; } static QVariantMap expandedBuildConfigurationInternal(const QString &settingsBaseDir, const QString &profileName, const QString &buildVariant) { Settings settings(settingsBaseDir); QVariantMap buildConfig; // (1) Values from profile, if given. if (!profileName.isEmpty()) { ErrorInfo err; const Profile profile(profileName, &settings); const QStringList profileKeys = profile.allKeys(Profile::KeySelectionRecursive, &err); if (err.hasError()) throw err; if (profileKeys.isEmpty()) throw ErrorInfo(Internal::Tr::tr("Unknown or empty profile '%1'.").arg(profileName)); foreach (const QString &profileKey, profileKeys) { buildConfig.insert(profileKey, profile.value(profileKey, QVariant(), &err)); if (err.hasError()) throw err; } } // (2) Build Variant. if (buildVariant.isEmpty()) throw ErrorInfo(Internal::Tr::tr("No build variant set.")); if (buildVariant != QLatin1String("debug") && buildVariant != QLatin1String("release")) { throw ErrorInfo(Internal::Tr::tr("Invalid build variant '%1'. Must be 'debug' or " "'release'.").arg(buildVariant)); } buildConfig.insert(QLatin1String("qbs.buildVariant"), buildVariant); return buildConfig; } QVariantMap SetupProjectParameters::expandedBuildConfiguration(const QString &settingsBaseDir, const QString &profileName, const QString &buildVariant, ErrorInfo *errorInfo) { try { return expandedBuildConfigurationInternal(settingsBaseDir, profileName, buildVariant); } catch (const ErrorInfo &err) { if (errorInfo) *errorInfo = err; return QVariantMap(); } } /*! * \brief Expands the build configuration. * * Expansion is the process by which the build configuration is completed based on the settings * in \c settingsDirectory(). E.g. the information configured in a profile is filled into the build * configuration by this step. * * This method returns an Error. The list of entries in this error will be empty is the * expansion was successful. */ ErrorInfo SetupProjectParameters::expandBuildConfiguration() { ErrorInfo err; QVariantMap expandedConfig = expandedBuildConfiguration(d->settingsBaseDir, topLevelProfile(), buildVariant(), &err); if (err.hasError()) return err; if (d->buildConfiguration != expandedConfig) { d->buildConfigurationTree.clear(); d->buildConfiguration = expandedConfig; } return err; } QVariantMap SetupProjectParameters::finalBuildConfigurationTree(const QVariantMap &buildConfig, const QVariantMap &overriddenValues, const QString &buildRoot, const QString &topLevelProfile) { QVariantMap flatBuildConfig = buildConfig; for (QVariantMap::ConstIterator it = overriddenValues.constBegin(); it != overriddenValues.constEnd(); ++it) { flatBuildConfig.insert(it.key(), it.value()); } const QString installRootKey = QLatin1String("qbs.installRoot"); QString installRoot = flatBuildConfig.value(installRootKey).toString(); if (installRoot.isEmpty()) { installRoot = buildRoot + QLatin1Char('/') + topLevelProfile + QLatin1Char('-') + flatBuildConfig.value(QLatin1String("qbs.buildVariant")).toString() + QLatin1Char('/') + InstallOptions::defaultInstallRoot(); flatBuildConfig.insert(installRootKey, installRoot); } QVariantMap buildConfigTree; provideValuesTree(flatBuildConfig, &buildConfigTree); return buildConfigTree; } /*! * \brief Returns the build configuration in tree form, with overridden values taken into account. */ QVariantMap SetupProjectParameters::finalBuildConfigurationTree() const { if (d->finalBuildConfigTree.isEmpty()) { d->finalBuildConfigTree = finalBuildConfigurationTree(buildConfiguration(), overriddenValues(), buildRoot(), topLevelProfile()); } return d->finalBuildConfigTree; } /*! * \variable SetupProjectParameters::ignoreDifferentProjectFilePath * \brief Returns true iff the saved build graph should be used even if its path to the * project file is different from \c SetupProjectParameters::projectFilePath() */ bool SetupProjectParameters::ignoreDifferentProjectFilePath() const { return d->ignoreDifferentProjectFilePath; } /*! * \brief Controls whether the path to the main project file may be different from the one * stored in a possible build graph file. * The default is false. */ void SetupProjectParameters::setIgnoreDifferentProjectFilePath(bool doIgnore) { d->ignoreDifferentProjectFilePath = doIgnore; } /*! * \brief if true, qbs will not store the build graph of the resolved project. */ bool SetupProjectParameters::dryRun() const { return d->dryRun; } /*! * \brief Controls whether the build graph will be stored. * If the argument is true, qbs will not store the build graph after resolving the project. * The default is false. */ void SetupProjectParameters::setDryRun(bool dryRun) { d->dryRun = dryRun; } /*! * \brief Returns true iff the time the operation takes should be logged */ bool SetupProjectParameters::logElapsedTime() const { return d->logElapsedTime; } /*! * Controls whether to log the time taken up for resolving the project. * The default is false. */ void SetupProjectParameters::setLogElapsedTime(bool logElapsedTime) { d->logElapsedTime = logElapsedTime; } /*! * \brief Gets the environment used while resolving the project. */ QProcessEnvironment SetupProjectParameters::environment() const { return d->environment; } /*! * \brief Sets the environment used while resolving the project. */ void SetupProjectParameters::setEnvironment(const QProcessEnvironment &env) { d->environment = env; } QProcessEnvironment SetupProjectParameters::adjustedEnvironment() const { QProcessEnvironment result = environment(); const QVariantMap environmentFromProfile = buildConfigurationTree().value(QLatin1String("buildEnvironment")).toMap(); for (QVariantMap::const_iterator it = environmentFromProfile.begin(); it != environmentFromProfile.end(); ++it) { result.insert(it.key(), it.value().toString()); } return result; } /*! * \enum SetupProjectParamaters::RestoreBehavior * This enum type specifies how to deal with existing on-disk build information. * \value RestoreOnly Indicates that a stored build graph is to be loaded and the information * therein assumed to be up to date. It is then considered an error if no * such build graph exists. * \value ResolveOnly Indicates that no attempt should be made to restore an existing build graph. * Instead, the project is to be resolved from scratch. * \value RestoreAndTrackChanges Indicates that the build graph should be restored from disk * if possible and otherwise set up from scratch. In the first case, * (parts of) the project might still be re-resolved if certain * parameters have changed (e.g. environment variables used in the * project files). */ /*! * Returns information about how restored build data will be handled. */ SetupProjectParameters::RestoreBehavior SetupProjectParameters::restoreBehavior() const { return d->restoreBehavior; } /*! * Controls how restored build data will be handled. */ void SetupProjectParameters::setRestoreBehavior(SetupProjectParameters::RestoreBehavior behavior) { d->restoreBehavior = behavior; } /*! * \enum SetupProjectParamaters::PropertyCheckingMode * This enum type specifies how \QBS should behave if it encounters unknown properties. * \value PropertyCheckingStrict Project resolving will stop with an error message. * \value PropertyCheckingRelaxed Project resolving will continue, and a warning will be printed. */ /*! * Indicates how to handle unknown properties. */ SetupProjectParameters::PropertyCheckingMode SetupProjectParameters::propertyCheckingMode() const { return d->propertyCheckingMode; } /*! * Controls how to handle unknown properties. * The default is \c PropertyCheckingRelaxed. */ void SetupProjectParameters::setPropertyCheckingMode(SetupProjectParameters::PropertyCheckingMode mode) { d->propertyCheckingMode = mode; } } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/setupprojectparameters.h000066400000000000000000000107301266132464200242020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_SETUPPROJECTPARAMETERS_H #define QBS_SETUPPROJECTPARAMETERS_H #include "qbs_export.h" #include #include #include #include #include namespace qbs { class Settings; namespace Internal { class SetupProjectParametersPrivate; } class QBS_EXPORT SetupProjectParameters { public: SetupProjectParameters(); SetupProjectParameters(const SetupProjectParameters &other); ~SetupProjectParameters(); SetupProjectParameters &operator=(const SetupProjectParameters &other); QString topLevelProfile() const; void setTopLevelProfile(const QString &profile); // TODO: It seems weird that we special-case the build variant. Can we get rid of this? QString buildVariant() const; void setBuildVariant(const QString &buildVariant); QString projectFilePath() const; void setProjectFilePath(const QString &projectFilePath); QString buildRoot() const; void setBuildRoot(const QString &buildRoot); QStringList searchPaths() const; void setSearchPaths(const QStringList &searchPaths); QStringList pluginPaths() const; void setPluginPaths(const QStringList &pluginPaths); QString libexecPath() const; void setLibexecPath(const QString &libexecPath); QString settingsDirectory() const; void setSettingsDirectory(const QString &settingsBaseDir); QVariantMap overriddenValues() const; void setOverriddenValues(const QVariantMap &values); QVariantMap overriddenValuesTree() const; static QVariantMap expandedBuildConfiguration(const QString &settingsBaseDir, const QString &profileName, const QString &buildVariant, ErrorInfo *errorInfo = 0); ErrorInfo expandBuildConfiguration(); QVariantMap buildConfiguration() const; QVariantMap buildConfigurationTree() const; static QVariantMap finalBuildConfigurationTree(const QVariantMap &buildConfig, const QVariantMap &overriddenValues, const QString &buildRoot, const QString &topLevelProfile); QVariantMap finalBuildConfigurationTree() const; bool ignoreDifferentProjectFilePath() const; void setIgnoreDifferentProjectFilePath(bool doIgnore); bool dryRun() const; void setDryRun(bool dryRun); bool logElapsedTime() const; void setLogElapsedTime(bool logElapsedTime); QProcessEnvironment environment() const; void setEnvironment(const QProcessEnvironment &env); QProcessEnvironment adjustedEnvironment() const; enum RestoreBehavior { RestoreOnly, ResolveOnly, RestoreAndTrackChanges }; RestoreBehavior restoreBehavior() const; void setRestoreBehavior(RestoreBehavior behavior); enum PropertyCheckingMode { PropertyCheckingStrict, PropertyCheckingRelaxed }; PropertyCheckingMode propertyCheckingMode() const; void setPropertyCheckingMode(PropertyCheckingMode mode); private: QSharedDataPointer d; }; } // namespace qbs #endif // Include guard qbs-src-1.4.5/src/lib/corelib/tools/shellutils.cpp000066400000000000000000000112711266132464200221130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "shellutils.h" #include #include #include namespace qbs { namespace Internal { QString shellInterpreter(const QString &filePath) { QFile file(filePath); if (file.open(QIODevice::ReadOnly)) { QTextStream ts(&file); const QString shebang = ts.readLine(); if (shebang.startsWith(QLatin1String("#!"))) { return (shebang.mid(2).split(QRegExp(QLatin1String("\\s")), QString::SkipEmptyParts) << QString()).first(); } } return QString(); } // hasSpecialChars, shellQuoteUnix, shellQuoteWin: all from qtbase/qmake/library/ioutils.cpp inline static bool hasSpecialChars(const QString &arg, const uchar (&iqm)[16]) { for (int x = arg.length() - 1; x >= 0; --x) { ushort c = arg.unicode()[x].unicode(); if ((c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)))) return true; } return false; } static QString shellQuoteUnix(const QString &arg) { // Chars that should be quoted (TM). This includes: static const uchar iqm[] = { 0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78 }; // 0-32 \'"$`<>|;&(){}*?#!~[] if (!arg.length()) return QString::fromLatin1("\"\""); QString ret(arg); if (hasSpecialChars(ret, iqm)) { ret.replace(QLatin1Char('\''), QLatin1String("'\\''")); ret.prepend(QLatin1Char('\'')); ret.append(QLatin1Char('\'')); } return ret; } static QString shellQuoteWin(const QString &arg) { // Chars that should be quoted (TM). This includes: // - control chars & space // - the shell meta chars "&()<>^| // - the potential separators ,;= static const uchar iqm[] = { 0xff, 0xff, 0xff, 0xff, 0x45, 0x13, 0x00, 0x78, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10 }; if (!arg.length()) return QString::fromLatin1("\"\""); QString ret(arg); if (hasSpecialChars(ret, iqm)) { // Quotes are escaped and their preceding backslashes are doubled. // It's impossible to escape anything inside a quoted string on cmd // level, so the outer quoting must be "suspended". ret.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\"\\1\\1\\^\"\"")); // The argument must not end with a \ since this would be interpreted // as escaping the quote -- rather put the \ behind the quote: e.g. // rather use "foo"\ than "foo\" int i = ret.length(); while (i > 0 && ret.at(i - 1) == QLatin1Char('\\')) --i; ret.insert(i, QLatin1Char('"')); ret.prepend(QLatin1Char('"')); } return ret; } QString shellQuote(const QString &arg, HostOsInfo::HostOs os) { return os == HostOsInfo::HostOsWindows ? shellQuoteWin(arg) : shellQuoteUnix(arg); } QString shellQuote(const QString &program, const QStringList &args, HostOsInfo::HostOs os) { QString result = shellQuote(program, os); foreach (const QString &arg, args) { result += QLatin1Char(' ') + shellQuote(arg, os); } return result; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/shellutils.h000066400000000000000000000041031266132464200215540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Copyright (C) 2015 Petroules Corporation. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_SHELLUTILS_H #define QBS_SHELLUTILS_H #include "qbs_export.h" #include "hostosinfo.h" #include namespace qbs { namespace Internal { QBS_EXPORT QString shellInterpreter(const QString &filePath); QBS_EXPORT QString shellQuote(const QString &arg, HostOsInfo::HostOs os = HostOsInfo::hostOs()); QBS_EXPORT QString shellQuote(const QString &program, const QStringList &args, HostOsInfo::HostOs os = HostOsInfo::hostOs()); } // namespace Internal } // namespace qbs #endif // QBS_SHELLUTILS_H qbs-src-1.4.5/src/lib/corelib/tools/tools.pri000066400000000000000000000052731266132464200211000ustar00rootroot00000000000000include(../../../install_prefix.pri) INCLUDEPATH += $$PWD/../.. # for plugins HEADERS += \ $$PWD/architectures.h \ $$PWD/buildgraphlocker.h \ $$PWD/codelocation.h \ $$PWD/commandechomode.h \ $$PWD/error.h \ $$PWD/executablefinder.h \ $$PWD/fileinfo.h \ $$PWD/filetime.h \ $$PWD/generateoptions.h \ $$PWD/id.h \ $$PWD/persistence.h \ $$PWD/scannerpluginmanager.h \ $$PWD/scripttools.h \ $$PWD/settings.h \ $$PWD/settingsmodel.h \ $$PWD/preferences.h \ $$PWD/profile.h \ $$PWD/processresult.h \ $$PWD/processresult_p.h \ $$PWD/processutils.h \ $$PWD/progressobserver.h \ $$PWD/projectgeneratormanager.h \ $$PWD/propertyfinder.h \ $$PWD/shellutils.h \ $$PWD/hostosinfo.h \ $$PWD/buildoptions.h \ $$PWD/installoptions.h \ $$PWD/cleanoptions.h \ $$PWD/setupprojectparameters.h \ $$PWD/persistentobject.h \ $$PWD/weakpointer.h \ $$PWD/qbs_export.h \ $$PWD/qbsassert.h \ $$PWD/qttools.h \ $$PWD/version.h SOURCES += \ $$PWD/architectures.cpp \ $$PWD/buildgraphlocker.cpp \ $$PWD/codelocation.cpp \ $$PWD/commandechomode.cpp \ $$PWD/error.cpp \ $$PWD/executablefinder.cpp \ $$PWD/fileinfo.cpp \ $$PWD/generateoptions.cpp \ $$PWD/id.cpp \ $$PWD/persistence.cpp \ $$PWD/scannerpluginmanager.cpp \ $$PWD/scripttools.cpp \ $$PWD/settings.cpp \ $$PWD/settingsmodel.cpp \ $$PWD/preferences.cpp \ $$PWD/processresult.cpp \ $$PWD/processutils.cpp \ $$PWD/profile.cpp \ $$PWD/progressobserver.cpp \ $$PWD/projectgeneratormanager.cpp \ $$PWD/propertyfinder.cpp \ $$PWD/shellutils.cpp \ $$PWD/buildoptions.cpp \ $$PWD/installoptions.cpp \ $$PWD/cleanoptions.cpp \ $$PWD/setupprojectparameters.cpp \ $$PWD/qbsassert.cpp \ $$PWD/qttools.cpp \ $$PWD/version.cpp win32 { SOURCES += $$PWD/filetime_win.cpp } unix { SOURCES += $$PWD/filetime_unix.cpp } qbs_enable_unit_tests { HEADERS += $$PWD/tst_tools.h SOURCES += $$PWD/tst_tools.cpp } !qbs_no_dev_install { tools_headers.files = \ $$PWD/architectures.h \ $$PWD/cleanoptions.h \ $$PWD/codelocation.h \ $$PWD/commandechomode.h \ $$PWD/error.h \ $$PWD/settings.h \ $$PWD/settingsmodel.h \ $$PWD/preferences.h \ $$PWD/profile.h \ $$PWD/processresult.h \ $$PWD/qbs_export.h \ $$PWD/buildoptions.h \ $$PWD/generateoptions.h \ $$PWD/generatorpluginmanager.h \ $$PWD/installoptions.h \ $$PWD/setupprojectparameters.h tools_headers.path = $${QBS_INSTALL_PREFIX}/include/qbs/tools INSTALLS += tools_headers } qbs-src-1.4.5/src/lib/corelib/tools/tst_tools.cpp000066400000000000000000000172741266132464200217660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #undef QT_NO_CAST_FROM_ASCII // I am qmake, and I approve this hack. #include "tst_tools.h" #include "buildoptions.h" #include "error.h" #include "fileinfo.h" #include "hostosinfo.h" #include "processutils.h" #include "profile.h" #include "settings.h" #include "setupprojectparameters.h" #include #include #include namespace qbs { namespace Internal { TestTools::TestTools(Settings *settings) : m_settings(settings) { } void TestTools::testFileInfo() { QCOMPARE(FileInfo::fileName("C:/waffl/copter.exe"), QString("copter.exe")); QCOMPARE(FileInfo::baseName("C:/waffl/copter.exe.lib"), QString("copter")); QCOMPARE(FileInfo::completeBaseName("C:/waffl/copter.exe.lib"), QString("copter.exe")); QCOMPARE(FileInfo::path("abc"), QString(".")); QCOMPARE(FileInfo::path("/abc/lol"), QString("/abc")); QCOMPARE(FileInfo::path("/fileInRoot"), QString(QLatin1Char('/'))); if (HostOsInfo::isWindowsHost()) QCOMPARE(FileInfo::path("C:/fileInDriveRoot"), QString("C:/")); QVERIFY(!FileInfo::isAbsolute("bla/lol")); QVERIFY(FileInfo::isAbsolute("/bla/lol")); if (HostOsInfo::isWindowsHost()) QVERIFY(FileInfo::isAbsolute("C:\\bla\\lol")); QCOMPARE(FileInfo::resolvePath("/abc/lol", "waffl"), QString("/abc/lol/waffl")); QCOMPARE(FileInfo::resolvePath("/abc/def/ghi/jkl/", "../foo/bar"), QString("/abc/def/ghi/foo/bar")); QCOMPARE(FileInfo::resolvePath("/abc/def/ghi/jkl/", "../../foo/bar"), QString("/abc/def/foo/bar")); QCOMPARE(FileInfo::resolvePath("/abc", "../../../foo/bar"), QString("/foo/bar")); QCOMPARE(FileInfo("/does/not/exist").lastModified(), FileTime()); } void TestTools::fileCaseCheck() { QTemporaryFile tempFile(QLatin1String("CamelCase")); QVERIFY(tempFile.open()); QFileInfo tempFileInfo(tempFile.fileName()); const QString lowerFilePath = tempFileInfo.absolutePath() + QLatin1Char('/') + tempFileInfo.fileName().toLower(); const QString upperFilePath = tempFileInfo.absolutePath() + QLatin1Char('/') + tempFileInfo.fileName().toUpper(); QVERIFY(FileInfo::isFileCaseCorrect(tempFileInfo.absoluteFilePath())); if (QFile::exists(lowerFilePath)) QVERIFY(!FileInfo::isFileCaseCorrect(lowerFilePath)); if (QFile::exists(upperFilePath)) QVERIFY(!FileInfo::isFileCaseCorrect(upperFilePath)); } void TestTools::testProfiles() { TemporaryProfile tpp("parent", m_settings); Profile parentProfile = tpp.p; TemporaryProfile tpc("child", m_settings); Profile childProfile = tpc.p; parentProfile.removeBaseProfile(); parentProfile.remove("testKey"); QCOMPARE(parentProfile.value("testKey", "none").toString(), QLatin1String("none")); parentProfile.setValue("testKey", "testValue"); QCOMPARE(parentProfile.value("testKey").toString(), QLatin1String("testValue")); childProfile.remove("testKey"); childProfile.removeBaseProfile(); QCOMPARE(childProfile.value("testKey", "none").toString(), QLatin1String("none")); childProfile.setBaseProfile("parent"); QCOMPARE(childProfile.value("testKey").toString(), QLatin1String("testValue")); // Change base profile and check if the inherited value also changes. TemporaryProfile tpf("foo", m_settings); Profile fooProfile = tpf.p; fooProfile.setValue("testKey", "gnampf"); childProfile.setBaseProfile("foo"); QCOMPARE(childProfile.value("testKey", "none").toString(), QLatin1String("gnampf")); ErrorInfo errorInfo; childProfile.setBaseProfile("SmurfAlongWithMe"); childProfile.value("blubb", QString(), &errorInfo); QVERIFY(errorInfo.hasError()); errorInfo.clear(); childProfile.setBaseProfile("parent"); parentProfile.setBaseProfile("child"); QVERIFY(!childProfile.value("blubb", QString(), &errorInfo).isValid()); QVERIFY(errorInfo.hasError()); QVERIFY(!childProfile.allKeys(Profile::KeySelectionNonRecursive).isEmpty()); errorInfo.clear(); QVERIFY(childProfile.allKeys(Profile::KeySelectionRecursive, &errorInfo).isEmpty()); QVERIFY(errorInfo.hasError()); } void TestTools::testBuildConfigMerging() { Settings settings((QString())); TemporaryProfile tp(QLatin1String("tst_tools_profile"), &settings); Profile profile = tp.p; profile.setValue(QLatin1String("topLevelKey"), QLatin1String("topLevelValue")); profile.setValue(QLatin1String("qbs.toolchain"), QLatin1String("gcc")); profile.setValue(QLatin1String("qbs.architecture"), QLatin1String("Jean-Claude Pillemann")); profile.setValue(QLatin1String("cpp.treatWarningsAsErrors"), true); QVariantMap overrideMap; overrideMap.insert(QLatin1String("qbs.toolchain"), QLatin1String("clang")); overrideMap.insert(QLatin1String("qbs.installRoot"), QLatin1String("/blubb")); SetupProjectParameters params; params.setTopLevelProfile(profile.name()); params.setBuildVariant(QLatin1String("debug")); params.setOverriddenValues(overrideMap); const ErrorInfo error = params.expandBuildConfiguration(); QVERIFY2(!error.hasError(), qPrintable(error.toString())); const QVariantMap finalMap = params.finalBuildConfigurationTree(); QCOMPARE(finalMap.count(), 3); QCOMPARE(finalMap.value(QLatin1String("topLevelKey")).toString(), QString::fromLatin1("topLevelValue")); const QVariantMap finalQbsMap = finalMap.value(QLatin1String("qbs")).toMap(); QCOMPARE(finalQbsMap.count(), 4); QCOMPARE(finalQbsMap.value(QLatin1String("toolchain")).toString(), QString::fromLatin1("clang")); QCOMPARE(finalQbsMap.value(QLatin1String("buildVariant")).toString(), QString::fromLatin1("debug")); QCOMPARE(finalQbsMap.value(QLatin1String("architecture")).toString(), QString::fromLatin1("Jean-Claude Pillemann")); QCOMPARE(finalQbsMap.value(QLatin1String("installRoot")).toString(), QLatin1String("/blubb")); const QVariantMap finalCppMap = finalMap.value(QLatin1String("cpp")).toMap(); QCOMPARE(finalCppMap.count(), 1); QCOMPARE(finalCppMap.value(QLatin1String("treatWarningsAsErrors")).toBool(), true); } void TestTools::testProcessNameByPid() { QCOMPARE(qAppName(), processNameByPid(QCoreApplication::applicationPid())); } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/tst_tools.h000066400000000000000000000036721266132464200214300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "qbs_export.h" #include namespace qbs { class Settings; namespace Internal { class QBS_EXPORT TestTools : public QObject { Q_OBJECT public: TestTools(Settings *settings); private slots: void fileCaseCheck(); void testBuildConfigMerging(); void testFileInfo(); void testProcessNameByPid(); void testProfiles(); private: Settings * const m_settings; }; } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/version.cpp000066400000000000000000000077631266132464200214230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "version.h" #include #include namespace qbs { namespace Internal { Version::Version(int major, int minor, int patch, int buildNr) : m_major(major), m_minor(minor), m_patch(patch), m_build(buildNr) { } int Version::majorVersion() const { return m_major; } void Version::setMajorVersion(int major) { m_major = major; } int Version::minorVersion() const { return m_minor; } void Version::setMinorVersion(int minor) { m_minor = minor; } int Version::patchLevel() const { return m_patch; } void Version::setPatchLevel(int patch) { m_patch = patch; } int Version::buildNumber() const { return m_build; } void Version::setBuildNumber(int nr) { m_build = nr; } Version Version::fromString(const QString &versionString, bool buildNumberAllowed) { QString pattern = QLatin1String("(\\d+)"); // At least one number. for (int i = 0; i < 2; ++i) pattern += QLatin1String("(?:\\.(\\d+))?"); // Followed by a dot and a number up to two times. if (buildNumberAllowed) pattern += QLatin1String("(?:-(\\d+))?"); // And possibly a dash followed by the build number. QRegExp rex(pattern); if (!rex.exactMatch(versionString)) return Version(); const int majorNr = rex.cap(1).toInt(); const int minorNr = rex.captureCount() >= 2 ? rex.cap(2).toInt() : 0; const int patchNr = rex.captureCount() >= 3 ? rex.cap(3).toInt() : 0; const int buildNr = rex.captureCount() >= 4 ? rex.cap(4).toInt() : 0; return Version(majorNr, minorNr, patchNr, buildNr); } QString Version::toString() const { QString s; if (m_build) s.sprintf("%d.%d.%d-%d", m_major, m_minor, m_patch, m_build); else s.sprintf("%d.%d.%d", m_major, m_minor, m_patch); return s; } const Version &Version::qbsVersion() { static const Version v = fromString(QLatin1String(QBS_VERSION)); return v; } int compare(const Version &lhs, const Version &rhs) { if (lhs.majorVersion() < rhs.majorVersion()) return -1; if (lhs.majorVersion() > rhs.majorVersion()) return 1; if (lhs.minorVersion() < rhs.minorVersion()) return -1; if (lhs.minorVersion() > rhs.minorVersion()) return 1; if (lhs.patchLevel() < rhs.patchLevel()) return -1; if (lhs.patchLevel() > rhs.patchLevel()) return 1; if (lhs.buildNumber() < rhs.buildNumber()) return -1; if (lhs.buildNumber() > rhs.buildNumber()) return 1; return 0; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/corelib/tools/version.h000066400000000000000000000061251266132464200210570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_VERSION_H #define QBS_VERSION_H #include "qbs_export.h" QT_BEGIN_NAMESPACE class QString; QT_END_NAMESPACE namespace qbs { namespace Internal { class QBS_EXPORT Version { public: explicit Version(int majorVersion = 0, int minorVersion = 0, int patchLevel = 0, int buildNr = 0); bool isValid() const { return m_major || m_minor || m_patch || m_build; } int majorVersion() const; void setMajorVersion(int majorVersion); int minorVersion() const; void setMinorVersion(int minorVersion); int patchLevel() const; void setPatchLevel(int patchLevel); int buildNumber() const; void setBuildNumber(int nr); static Version fromString(const QString &versionString, bool buildNumberAllowed = false); QString toString() const; static const Version &qbsVersion(); private: int m_major; int m_minor; int m_patch; int m_build; }; QBS_EXPORT int compare(const Version &lhs, const Version &rhs); inline bool operator==(const Version &lhs, const Version &rhs) { return compare(lhs, rhs) == 0; } inline bool operator!=(const Version &lhs, const Version &rhs) { return !operator==(lhs, rhs); } inline bool operator<(const Version &lhs, const Version &rhs) { return compare(lhs, rhs) < 0; } inline bool operator>(const Version &lhs, const Version &rhs) { return compare(lhs, rhs) > 0; } inline bool operator<=(const Version &lhs, const Version &rhs) { return !operator>(lhs, rhs); } inline bool operator>=(const Version &lhs, const Version &rhs) { return !operator<(lhs, rhs); } } // namespace Internal } // namespace qbs #endif // QBS_VERSION_H qbs-src-1.4.5/src/lib/corelib/tools/weakpointer.h000066400000000000000000000044551266132464200217260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_WEAKPOINTER_H #define QBS_WEAKPOINTER_H #include namespace qbs { namespace Internal { template class WeakPointer : public QWeakPointer { public: WeakPointer() : QWeakPointer() {} WeakPointer(const QSharedPointer &sharedPointer) : QWeakPointer(sharedPointer) {} template WeakPointer(const QSharedPointer &sp) : QWeakPointer(sp) { } operator T*() const { return checkedData(); } T *operator->() const { return checkedData(); } T operator*() const { return *checkedData(); } private: T *checkedData() const { T * const d = QWeakPointer::data(); Q_ASSERT(d); // Calling code is not expecting this situation. return d; } }; } // namespace Internal } // namespace qbs #endif // QBS_WEAKPOINTER_H qbs-src-1.4.5/src/lib/corelib/use_corelib.pri000066400000000000000000000021321266132464200210620ustar00rootroot00000000000000include(../../../qbs_version.pri) include(../../library_dirname.pri) isEmpty(QBSLIBDIR) { QBSLIBDIR = $$OUT_PWD/../../../$${QBS_LIBRARY_DIRNAME} } QT += script xml unix { LIBS += -L$$QBSLIBDIR -lqbscore } !qbs_disable_rpath { linux-*:QMAKE_LFLAGS += -Wl,-z,origin \'-Wl,-rpath,\$\$ORIGIN/../$${QBS_LIBRARY_DIRNAME}\' macx:QMAKE_LFLAGS += -Wl,-rpath,@loader_path/../$${QBS_LIBRARY_DIRNAME} } !CONFIG(static, static|shared) { QBSCORELIBSUFFIX = $$QBS_VERSION_MAJ } win32 { CONFIG(debug, debug|release) { QBSCORELIB = qbscored$$QBSCORELIBSUFFIX } CONFIG(release, debug|release) { QBSCORELIB = qbscore$$QBSCORELIBSUFFIX } win32-msvc* { LIBS += /LIBPATH:$$QBSLIBDIR QBSCORELIB = $${QBSCORELIB}.lib LIBS += Shell32.lib } else { LIBS += -L$${QBSLIBDIR} QBSCORELIB = lib$${QBSCORELIB} } LIBS += $$QBSCORELIB } INCLUDEPATH += \ $$PWD CONFIG += depend_includepath CONFIG(static, static|shared) { DEFINES += QBS_STATIC_LIB } qbs_enable_project_file_updates:DEFINES += QBS_ENABLE_PROJECT_FILE_UPDATES qbs-src-1.4.5/src/lib/corelib/use_installed_corelib.pri000066400000000000000000000015371266132464200231310ustar00rootroot00000000000000include(qbs_version.pri) QT += script xml QBSLIBDIR=$${PWD}/../../lib unix { LIBS += -L$$QBSLIBDIR -lqbscore } !qbs_disable_rpath:unix:QMAKE_LFLAGS += -Wl,-rpath,$${QBSLIBDIR} !CONFIG(static, static|shared) { QBSCORELIBSUFFIX = $$QBS_VERSION_MAJ } win32 { CONFIG(debug, debug|release) { QBSCORELIB = qbscored$$QBSCORELIBSUFFIX } CONFIG(release, debug|release) { QBSCORELIB = qbscore$$QBSCORELIBSUFFIX } win32-msvc* { LIBS += /LIBPATH:$$QBSLIBDIR QBSCORELIB = $${QBSCORELIB}.lib LIBS += Shell32.lib } else { LIBS += -L$${QBSLIBDIR} QBSCORELIB = lib$${QBSCORELIB} } LIBS += $$QBSCORELIB } INCLUDEPATH += $${PWD} $${PWD}/.. CONFIG(static, static|shared) { DEFINES += QBS_STATIC_LIB } qbs_enable_project_file_updates:DEFINES += QBS_ENABLE_PROJECT_FILE_UPDATES qbs-src-1.4.5/src/lib/library.pri000066400000000000000000000021661266132464200166230ustar00rootroot00000000000000include(../library_dirname.pri) include(../install_prefix.pri) TEMPLATE = lib QT = core !isEmpty(QBS_DLLDESTDIR):DLLDESTDIR = $${QBS_DLLDESTDIR} else:DLLDESTDIR = ../../../bin !isEmpty(QBS_DESTDIR):DESTDIR = $${QBS_DESTDIR} else:DESTDIR = ../../../$${QBS_LIBRARY_DIRNAME} CONFIG(static, static|shared) { DEFINES += QBS_STATIC_LIB } else { DEFINES += QBS_LIBRARY } DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_PROCESS_COMBINED_ARGUMENT_START INCLUDEPATH += $${PWD}/../ contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols win32:CONFIG(debug, debug|release):TARGET = $${TARGET}d CONFIG += c++11 qbs_disable_rpath { osx:QMAKE_LFLAGS_SONAME = -Wl,-install_name,$$QBS_INSTALL_PREFIX/$$QBS_LIBRARY_DIRNAME/ } else { osx:QMAKE_LFLAGS_SONAME = -Wl,-install_name,@rpath/ } include(../../qbs_version.pri) VERSION = $${QBS_VERSION} win32 { dlltarget.path = $${QBS_INSTALL_PREFIX}/bin INSTALLS += dlltarget } !win32|!qbs_no_dev_install { !isEmpty(QBS_LIB_INSTALL_DIR): \ target.path = $${QBS_LIB_INSTALL_DIR} else: \ target.path = $${QBS_INSTALL_PREFIX}/$${QBS_LIBRARY_DIRNAME} INSTALLS += target } qbs-src-1.4.5/src/lib/libs.qbs000066400000000000000000000001741266132464200161000ustar00rootroot00000000000000import qbs Project { references: [ "corelib/corelib.qbs", "qtprofilesetup/qtprofilesetup.qbs", ] } qbs-src-1.4.5/src/lib/qtprofilesetup/000077500000000000000000000000001266132464200175245ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/qtprofilesetup/qtenvironment.h000066400000000000000000000047261266132464200226170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_QTENVIRONMENT_H #define QBS_QTENVIRONMENT_H #include #include namespace qbs { class QBS_EXPORT QtEnvironment { public: QtEnvironment() : staticBuild(false), frameworkBuild(false) { } QString installPrefixPath; QString libraryPath; QString includePath; QString binaryPath; QString qmlPath; QString qmlImportPath; QString documentationPath; QString dataPath; QString pluginPath; QString qtLibInfix; QString qtNameSpace; QString mkspecPath; QString mkspecName; QString mkspecBasePath; QStringList entryPointLibsDebug; QStringList entryPointLibsRelease; QStringList buildVariant; QStringList configItems; QStringList qtConfigItems; QString architecture; QString qtVersion; int qtMajorVersion; int qtMinorVersion; int qtPatchVersion; bool staticBuild; bool frameworkBuild; }; } // namespace qbs #endif // Include guard. qbs-src-1.4.5/src/lib/qtprofilesetup/qtmoduleinfo.cpp000066400000000000000000000763171266132464200227540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "qtmoduleinfo.h" #include "qtenvironment.h" #include #include #include #include #include #include namespace qbs { namespace Internal { typedef QHash NamePathHash; static void replaceQtLibNamesWithFilePath(const NamePathHash &namePathHash, QStringList *libList) { for (int i = 0; i < libList->count(); ++i) { QString &lib = (*libList)[i]; const NamePathHash::ConstIterator it = namePathHash.find(lib); if (it != namePathHash.constEnd()) lib = it.value(); } } static void replaceQtLibNamesWithFilePath(QList *modules, const QtEnvironment &qtEnv) { // We don't want to add the libraries for Qt modules via "-l", because of the // danger that a wrong one will be picked up, e.g. from /usr/lib. Instead, // we pull them in using the full file path. typedef QHash NamePathHash; NamePathHash linkerNamesToFilePathsDebug; NamePathHash linkerNamesToFilePathsRelease; foreach (const QtModuleInfo &m, *modules) { linkerNamesToFilePathsDebug.insert(m.libNameForLinker(qtEnv, true), m.libFilePathDebug); linkerNamesToFilePathsRelease.insert(m.libNameForLinker(qtEnv, false), m.libFilePathRelease); } for (int i = 0; i < modules->count(); ++i) { QtModuleInfo &module = (*modules)[i]; replaceQtLibNamesWithFilePath(linkerNamesToFilePathsDebug, &module.dynamicLibrariesDebug); replaceQtLibNamesWithFilePath(linkerNamesToFilePathsDebug, &module.staticLibrariesDebug); replaceQtLibNamesWithFilePath(linkerNamesToFilePathsRelease, &module.dynamicLibrariesRelease); replaceQtLibNamesWithFilePath(linkerNamesToFilePathsRelease, &module.staticLibrariesRelease); } } QtModuleInfo::QtModuleInfo() : isPrivate(false), hasLibrary(true), isStaticLibrary(false), isPlugin(false), mustExist(true) { } QtModuleInfo::QtModuleInfo(const QString &name, const QString &qbsName, const QStringList &deps) : name(name), qbsName(qbsName), dependencies(deps), isPrivate(qbsName.endsWith(QLatin1String("-private"))), hasLibrary(!isPrivate), isStaticLibrary(false), isPlugin(false), mustExist(true) { const QString coreModule = QLatin1String("core"); if (qbsName != coreModule && !dependencies.contains(coreModule)) dependencies.prepend(coreModule); } QString QtModuleInfo::moduleNameWithoutPrefix() const { if (modulePrefix.isEmpty() && name.startsWith(QLatin1String("Qt"))) return name.mid(2); // Strip off "Qt". if (name.startsWith(modulePrefix)) return name.mid(modulePrefix.length()); return name; } QString QtModuleInfo::frameworkHeadersPath(const QtEnvironment &qtEnvironment) const { return qtEnvironment.libraryPath + QLatin1Char('/') + name + QLatin1String(".framework/Headers"); } QStringList QtModuleInfo::qt4ModuleIncludePaths(const QtEnvironment &qtEnvironment) const { QStringList paths; if (isFramework(qtEnvironment)) { paths << frameworkHeadersPath(qtEnvironment); } else { paths << qtEnvironment.includePath << qtEnvironment.includePath + QLatin1Char('/') + name; } return paths; } QString QtModuleInfo::libraryBaseName(const QtEnvironment &qtEnvironment, bool debugBuild) const { if (isPlugin) return libBaseName(name, debugBuild, qtEnvironment); // Some modules use a different naming scheme, so it doesn't get boring. const bool libNameBroken = name == QLatin1String("Enginio") || name == QLatin1String("DataVisualization"); QString libName = modulePrefix.isEmpty() && !libNameBroken ? QLatin1String("Qt") : modulePrefix; if (qtEnvironment.qtMajorVersion >= 5 && !isFramework(qtEnvironment) && !libNameBroken) libName += QString::number(qtEnvironment.qtMajorVersion); libName += moduleNameWithoutPrefix(); libName += qtEnvironment.qtLibInfix; return libBaseName(libName, debugBuild, qtEnvironment); } QString QtModuleInfo::libNameForLinker(const QtEnvironment &qtEnvironment, bool debugBuild) const { if (!hasLibrary) return QString(); QString libName = libraryBaseName(qtEnvironment, debugBuild); if (qtEnvironment.mkspecName.contains(QLatin1String("msvc"))) libName += QLatin1String(".lib"); return libName; } void QtModuleInfo::setupLibraries(const QtEnvironment &qtEnv, QSet *nonExistingPrlFiles) { setupLibraries(qtEnv, true, nonExistingPrlFiles); setupLibraries(qtEnv, false, nonExistingPrlFiles); } static QStringList makeList(const QByteArray &s) { return QString::fromLatin1(s).split(QLatin1Char(' '), QString::SkipEmptyParts); } void QtModuleInfo::setupLibraries(const QtEnvironment &qtEnv, bool debugBuild, QSet *nonExistingPrlFiles) { if (!hasLibrary) return; // Can happen for Qt4 convenience modules, like "widgets". if (debugBuild) { if (!qtEnv.buildVariant.contains(QLatin1String("debug"))) return; const QStringList modulesNeverBuiltAsDebug = QStringList() << QLatin1String("bootstrap") << QLatin1String("qmldevtools"); foreach (const QString &m, modulesNeverBuiltAsDebug) { if (qbsName == m || qbsName == m + QLatin1String("-private")) return; } } else if (!qtEnv.buildVariant.contains(QLatin1String("release"))) { return; } QStringList &libs = isStaticLibrary ? (debugBuild ? staticLibrariesDebug : staticLibrariesRelease) : (debugBuild ? dynamicLibrariesDebug : dynamicLibrariesRelease); QStringList &frameworks = debugBuild ? frameworksDebug : frameworksRelease; QStringList &frameworkPaths = debugBuild ? frameworkPathsDebug : frameworkPathsRelease; QStringList &flags = debugBuild ? linkerFlagsDebug : linkerFlagsRelease; QString &libFilePath = debugBuild ? libFilePathDebug : libFilePathRelease; if (qtEnv.mkspecName.contains(QLatin1String("ios")) && isStaticLibrary) { const QtModuleInfo platformSupportModule(QLatin1String("QtPlatformSupport"), QLatin1String("platformsupport")); libs << QLatin1String("z") << QLatin1String("m") << platformSupportModule.libNameForLinker(qtEnv, debugBuild); flags << QLatin1String("-force_load") << qtEnv.pluginPath + QLatin1String("/platforms/") + libBaseName(QLatin1String("libqios"), debugBuild, qtEnv) + QLatin1String(".a"); } QString prlFilePath = isPlugin ? qtEnv.pluginPath + QLatin1Char('/') + pluginData.type : qtEnv.libraryPath; prlFilePath += QLatin1Char('/'); if (isFramework(qtEnv)) prlFilePath.append(libraryBaseName(qtEnv, false)).append(QLatin1String(".framework/")); const QString libDir = prlFilePath; if (!qtEnv.mkspecName.startsWith(QLatin1String("win")) && !isFramework(qtEnv)) prlFilePath += QLatin1String("lib"); prlFilePath.append(libraryBaseName(qtEnv, debugBuild)); const bool isNonStaticQt4OnWindows = qtEnv.mkspecName.startsWith(QLatin1String("win")) && !isStaticLibrary && qtEnv.qtMajorVersion < 5; if (isNonStaticQt4OnWindows) prlFilePath.chop(1); // The prl file base name does *not* contain the version number... prlFilePath.append(QLatin1String(".prl")); if (nonExistingPrlFiles->contains(prlFilePath)) return; QFile prlFile(prlFilePath); if (!prlFile.open(QIODevice::ReadOnly)) { // We can't error out here, as some modules in a self-built Qt don't have the expected // file names. Real-life example: "libQt0Feedback.prl". This is just too stupid // to work around, so let's ignore it. if (mustExist) { qDebug("Skipping prl file '%s', because it cannot be opened (%s).", qPrintable(prlFilePath), qPrintable(prlFile.errorString())); } nonExistingPrlFiles->insert(prlFilePath); return; } const QList prlLines = prlFile.readAll().split('\n'); foreach (const QByteArray &line, prlLines) { const QByteArray simplifiedLine = line.simplified(); const int equalsOffset = simplifiedLine.indexOf('='); if (equalsOffset == -1) continue; if (simplifiedLine.startsWith("QMAKE_PRL_TARGET")) { const bool isMingw = qtEnv.mkspecName.startsWith(QLatin1String("win")) && qtEnv.mkspecName.contains(QLatin1String("g++")); libFilePath = libDir; // QMAKE_PRL_TARGET has a "lib" prefix, except for mingw. // Of course, the exception has an exception too: For static libs, mingw *does* // have the "lib" prefix. TODO: Shoot the people responsible for this. if (isMingw && !isStaticLibrary) libFilePath += QLatin1String("lib"); libFilePath += QString::fromLatin1(simplifiedLine.mid(equalsOffset + 1).trimmed()); if (isNonStaticQt4OnWindows) libFilePath += QString::number(4); // This is *not* part of QMAKE_PRL_TARGET... if (qtEnv.qtMajorVersion < 5 || (qtEnv.qtMajorVersion == 5 && qtEnv.qtMinorVersion < 6)) { if (qtEnv.mkspecName.contains(QLatin1String("msvc"))) libFilePath += QLatin1String(".lib"); else if (isMingw) libFilePath += QLatin1String(".a"); } continue; } if (!simplifiedLine.startsWith("QMAKE_PRL_LIBS")) continue; // Assuming lib names and directories without spaces here. QStringList parts = QString::fromLatin1(simplifiedLine.mid(equalsOffset + 1).trimmed()) .split(QLatin1Char(' '), QString::SkipEmptyParts); for (int i = 0; i < parts.count(); ++i) { QString part = parts.at(i); part.replace(QLatin1String("$$[QT_INSTALL_LIBS]"), qtEnv.libraryPath); if (part.startsWith(QLatin1String("-l"))) { libs << part.mid(2); } else if (part.startsWith(QLatin1String("-L"))) { libraryPaths << part.mid(2); } else if (part.startsWith(QLatin1String("-F"))) { frameworkPaths << part.mid(2); } else if (part == QLatin1String("-framework")) { if (++i < parts.count()) frameworks << parts.at(i); } else if (part.startsWith(QLatin1Char('-'))) { // Some other option, e.g. "-pthread". flags << part; } else if (part.startsWith(QLatin1String("/LIBPATH:"))) { libraryPaths << part.mid(9).replace(QLatin1String("\\\\"), QLatin1String("/")); } else { // Assume it's a file path/name. libs << part.replace(QLatin1String("\\\\"), QLatin1String("/")); } } return; } } bool QtModuleInfo::isFramework(const QtEnvironment &qtEnv) const { if (!qtEnv.frameworkBuild || isStaticLibrary) return false; const QStringList modulesNeverBuiltAsFrameworks = QStringList() << QLatin1String("bootstrap") << QLatin1String("openglextensions") << QLatin1String("platformsupport") << QLatin1String("qmldevtools") << QLatin1String("uitools") << QLatin1String("harfbuzzng"); return !modulesNeverBuiltAsFrameworks.contains(qbsName); } // We erroneously called the "testlib" module "test" for quite a while. Let's not punish users // for that. static void addTestModule(QList &modules) { QtModuleInfo testModule(QLatin1String("QtTest"), QLatin1String("test"), QStringList() << QLatin1String("testlib")); testModule.hasLibrary = false; modules << testModule; } // See above. static void addDesignerComponentsModule(QList &modules) { QtModuleInfo module(QLatin1String("QtDesignerComponents"), QLatin1String("designercomponents"), QStringList() << QLatin1String("designercomponents-private")); module.hasLibrary = false; modules << module; } QList allQt4Modules(const QtEnvironment &qtEnvironment) { // as per http://doc.qt.io/qt-4.8/modules.html + private stuff. QList modules; QtModuleInfo core(QLatin1String("QtCore"), QLatin1String("core")); core.compilerDefines << QLatin1String("QT_CORE_LIB"); if (!qtEnvironment.qtNameSpace.isEmpty()) core.compilerDefines << QLatin1String("QT_NAMESPACE=") + qtEnvironment.qtNameSpace; modules = QList() << core << QtModuleInfo(QLatin1String("QtCore"), QLatin1String("core-private"), QStringList() << QLatin1String("core")) << QtModuleInfo(QLatin1String("QtGui"), QLatin1String("gui")) << QtModuleInfo(QLatin1String("QtGui"), QLatin1String("gui-private"), QStringList() << QLatin1String("gui")) << QtModuleInfo(QLatin1String("QtMultimedia"), QLatin1String("multimedia"), QStringList() << QLatin1String("gui") << QLatin1String("network")) << QtModuleInfo(QLatin1String("QtMultimedia"), QLatin1String("multimedia-private"), QStringList() << QLatin1String("multimedia")) << QtModuleInfo(QLatin1String("QtNetwork"), QLatin1String("network")) << QtModuleInfo(QLatin1String("QtNetwork"), QLatin1String("network-private"), QStringList() << QLatin1String("network")) << QtModuleInfo(QLatin1String("QtOpenGL"), QLatin1String("opengl"), QStringList() << QLatin1String("gui")) << QtModuleInfo(QLatin1String("QtOpenGL"), QLatin1String("opengl-private"), QStringList() << QLatin1String("opengl")) << QtModuleInfo(QLatin1String("QtOpenVG"), QLatin1String("openvg"), QStringList() << QLatin1String("gui")) << QtModuleInfo(QLatin1String("QtScript"), QLatin1String("script")) << QtModuleInfo(QLatin1String("QtScript"), QLatin1String("script-private"), QStringList() << QLatin1String("script")) << QtModuleInfo(QLatin1String("QtScriptTools"), QLatin1String("scripttols"), QStringList() << QLatin1String("script") << QLatin1String("gui")) << QtModuleInfo(QLatin1String("QtScriptTools"), QLatin1String("scripttols-private"), QStringList() << QLatin1String("scripttols")) << QtModuleInfo(QLatin1String("QtSql"), QLatin1String("sql")) << QtModuleInfo(QLatin1String("QtSql"), QLatin1String("sql-private"), QStringList() << QLatin1String("sql")) << QtModuleInfo(QLatin1String("QtSvg"), QLatin1String("svg"), QStringList() << QLatin1String("gui")) << QtModuleInfo(QLatin1String("QtSvg"), QLatin1String("svg-private"), QStringList() << QLatin1String("svg")) << QtModuleInfo(QLatin1String("QtWebKit"), QLatin1String("webkit"), QStringList() << QLatin1String("gui") << QLatin1String("network")) << QtModuleInfo(QLatin1String("QtWebKit"), QLatin1String("webkit-private"), QStringList() << QLatin1String("webkit")) << QtModuleInfo(QLatin1String("QtXml"), QLatin1String("xml")) << QtModuleInfo(QLatin1String("QtXml"), QLatin1String("xml-private"), QStringList() << QLatin1String("xml")) << QtModuleInfo(QLatin1String("QtXmlPatterns"), QLatin1String("xmlpatterns"), QStringList() << QLatin1String("network")) << QtModuleInfo(QLatin1String("QtXmlPatterns"), QLatin1String("xmlpatterns-private"), QStringList() << QLatin1String("xmlpatterns")) << QtModuleInfo(QLatin1String("QtDeclarative"), QLatin1String("declarative"), QStringList() << QLatin1String("gui") << QLatin1String("script")) << QtModuleInfo(QLatin1String("QtDeclarative"), QLatin1String("declarative-private"), QStringList() << QLatin1String("declarative")) << QtModuleInfo(QLatin1String("QtDesigner"), QLatin1String("designer"), QStringList() << QLatin1String("gui") << QLatin1String("xml")) << QtModuleInfo(QLatin1String("QtDesigner"), QLatin1String("designer-private"), QStringList() << QLatin1String("designer")) << QtModuleInfo(QLatin1String("QtUiTools"), QLatin1String("uitools")) << QtModuleInfo(QLatin1String("QtUiTools"), QLatin1String("uitools-private"), QStringList() << QLatin1String("uitools")) << QtModuleInfo(QLatin1String("QtHelp"), QLatin1String("help"), QStringList() << QLatin1String("network") << QLatin1String("sql")) << QtModuleInfo(QLatin1String("QtHelp"), QLatin1String("help-private"), QStringList() << QLatin1String("help")) << QtModuleInfo(QLatin1String("QtTest"), QLatin1String("testlib")) << QtModuleInfo(QLatin1String("QtTest"), QLatin1String("testlib-private"), QStringList() << QLatin1String("testlib")); if (qtEnvironment.mkspecName.startsWith(QLatin1String("win"))) { QtModuleInfo axcontainer(QLatin1String("QAxContainer"), QLatin1String("axcontainer")); axcontainer.modulePrefix = QLatin1String("Q"); axcontainer.isStaticLibrary = true; axcontainer.includePaths << qtEnvironment.includePath + QLatin1String("/ActiveQt"); modules << axcontainer; QtModuleInfo axserver = axcontainer; axserver.name = QLatin1String("QAxServer"); axserver.qbsName = QLatin1String("axserver"); axserver.compilerDefines = QStringList() << QLatin1String("QAXSERVER"); modules << axserver; } else { modules << QtModuleInfo(QLatin1String("QtDBus"), QLatin1String("dbus")) << QtModuleInfo(QLatin1String("QtDBus"), QLatin1String("dbus-private"), QStringList() << QLatin1String("dbus")); } QtModuleInfo designerComponentsPrivate(QLatin1String("QtDesignerComponents"), QLatin1String("designercomponents-private"), QStringList() << QLatin1String("gui-private") << QLatin1String("designer-private")); designerComponentsPrivate.hasLibrary = true; modules << designerComponentsPrivate; QtModuleInfo phonon(QLatin1String("Phonon"), QLatin1String("phonon")); phonon.includePaths = phonon.qt4ModuleIncludePaths(qtEnvironment); modules << phonon; // Set up include paths that haven't been set up before this point. for (QList::iterator it = modules.begin(); it != modules.end(); ++it) { QtModuleInfo &module = *it; if (!module.includePaths.isEmpty()) continue; module.includePaths = module.qt4ModuleIncludePaths(qtEnvironment); } // Set up compiler defines haven't been set up before this point. for (QList::iterator it = modules.begin(); it != modules.end(); ++it) { QtModuleInfo &module = *it; if (!module.compilerDefines.isEmpty()) continue; module.compilerDefines << QLatin1String("QT_") + module.qbsName.toUpper() + QLatin1String("_LIB"); } // These are for the convenience of project file authors. It allows them // to add a dependency to e.g. "Qt.widgets" without a version check. QtModuleInfo virtualModule; virtualModule.hasLibrary = false; virtualModule.qbsName = QLatin1String("widgets"); virtualModule.dependencies = QStringList() << QLatin1String("core") << QLatin1String("gui"); modules << virtualModule; virtualModule.qbsName = QLatin1String("quick"); virtualModule.dependencies = QStringList() << QLatin1String("declarative"); modules << virtualModule; virtualModule.qbsName = QLatin1String("concurrent"); virtualModule.dependencies = QStringList() << QLatin1String("core"); modules << virtualModule; virtualModule.qbsName = QLatin1String("printsupport"); virtualModule.dependencies = QStringList() << QLatin1String("core") << QLatin1String("gui"); modules << virtualModule; addTestModule(modules); addDesignerComponentsModule(modules); const QStringList modulesThatCanBeDisabled = QStringList() << QLatin1String("xmlpatterns") << QLatin1String("multimedia") << QLatin1String("phonon") << QLatin1String("svg") << QLatin1String("webkit") << QLatin1String("script") << QLatin1String("scripttools") << QLatin1String("declarative") << QLatin1String("gui") << QLatin1String("dbus") << QLatin1String("opengl") << QLatin1String("openvg"); for (int i = 0; i < modules.count(); ++i) { QString name = modules[i].qbsName; name.remove(QLatin1String("-private")); if (modulesThatCanBeDisabled.contains(name)) modules[i].mustExist = false; } QSet nonExistingPrlFiles; for (int i = 0; i < modules.count(); ++i) { QtModuleInfo &module = modules[i]; if (qtEnvironment.staticBuild) module.isStaticLibrary = true; module.setupLibraries(qtEnvironment, &nonExistingPrlFiles); } replaceQtLibNamesWithFilePath(&modules, qtEnvironment); return modules; } static QList getPriFileContentsRecursively(const Profile &profile, const QString &priFilePath) { QFile priFile(priFilePath); if (!priFile.open(QIODevice::ReadOnly)) { throw ErrorInfo(Tr::tr("Setting up Qt profile '%1' failed: Cannot open " "file '%2' (%3).").arg(profile.name(), priFile.fileName(), priFile.errorString())); } QList lines = priFile.readAll().split('\n'); for (int i = 0; i < lines.count(); ++i) { const QByteArray includeString = "include("; const QByteArray &line = lines.at(i).trimmed(); if (!line.startsWith(includeString)) continue; const int offset = includeString.count(); const int closingParenPos = line.indexOf(')', offset); if (closingParenPos == -1) { qDebug("Warning: Invalid include statement in '%s'", qPrintable(priFilePath)); continue; } const QString includedFilePath = QString::fromLocal8Bit(line.mid(offset, closingParenPos - offset)); const QList &includedContents = getPriFileContentsRecursively(profile, includedFilePath); int j = i; foreach (const QByteArray &includedLine, includedContents) lines.insert(++j, includedLine); lines.removeAt(i--); } return lines; } QList allQt5Modules(const Profile &profile, const QtEnvironment &qtEnvironment) { QSet nonExistingPrlFiles; QList modules; QDirIterator dit(qtEnvironment.mkspecBasePath + QLatin1String("/modules")); while (dit.hasNext()) { const QString moduleFileNamePrefix = QLatin1String("qt_lib_"); const QString pluginFileNamePrefix = QLatin1String("qt_plugin_"); const QString moduleFileNameSuffix = QLatin1String(".pri"); dit.next(); const bool fileHasPluginPrefix = dit.fileName().startsWith(pluginFileNamePrefix); if ((!fileHasPluginPrefix && !dit.fileName().startsWith(moduleFileNamePrefix)) || !dit.fileName().endsWith(moduleFileNameSuffix)) { continue; } QtModuleInfo moduleInfo; moduleInfo.isPlugin = fileHasPluginPrefix; const QString fileNamePrefix = moduleInfo.isPlugin ? pluginFileNamePrefix : moduleFileNamePrefix; moduleInfo.qbsName = dit.fileName().mid(fileNamePrefix.count(), dit.fileName().count() - fileNamePrefix.count() - moduleFileNameSuffix.count()); if (moduleInfo.isPlugin) { moduleInfo.name = moduleInfo.qbsName; moduleInfo.isStaticLibrary = true; } const QByteArray moduleKeyPrefix = QByteArray(moduleInfo.isPlugin ? "QT_PLUGIN" : "QT") + '.' + moduleInfo.qbsName.toLatin1() + '.'; moduleInfo.qbsName.replace(QLatin1String("_private"), QLatin1String("-private")); bool hasV2 = false; bool hasModuleEntry = false; foreach (const QByteArray &line, getPriFileContentsRecursively(profile, dit.filePath())) { const QByteArray simplifiedLine = line.simplified(); const int firstEqualsOffset = simplifiedLine.indexOf('='); if (firstEqualsOffset == -1) continue; const QByteArray key = simplifiedLine.left(firstEqualsOffset).trimmed(); const QByteArray value = simplifiedLine.mid(firstEqualsOffset + 1).trimmed(); if (!key.startsWith(moduleKeyPrefix) || value.isEmpty()) continue; if (key.endsWith(".name")) { moduleInfo.name = QString::fromLocal8Bit(value); } else if (key.endsWith(".module")) { hasModuleEntry = true; } else if (key.endsWith(".depends")) { moduleInfo.dependencies = QString::fromLocal8Bit(value).split(QLatin1Char(' ')); for (int i = 0; i < moduleInfo.dependencies.count(); ++i) { moduleInfo.dependencies[i].replace(QLatin1String("_private"), QLatin1String("-private")); } } else if (key.endsWith(".module_config")) { foreach (const QByteArray &elem, value.split(' ')) { if (elem == "no_link") moduleInfo.hasLibrary = false; else if (elem == "staticlib") moduleInfo.isStaticLibrary = true; else if (elem == "internal_module") moduleInfo.isPrivate = true; else if (elem == "v2") hasV2 = true; } } else if (key.endsWith(".includes")) { moduleInfo.includePaths = QString::fromLocal8Bit(value).split(QLatin1Char(' ')); for (int i = 0; i < moduleInfo.includePaths.count(); ++i) { moduleInfo.includePaths[i].replace( QLatin1String("$$QT_MODULE_INCLUDE_BASE"), qtEnvironment.includePath); } } else if (key.endsWith(".DEFINES")) { moduleInfo.compilerDefines = QString::fromLocal8Bit(value) .split(QLatin1Char(' '), QString::SkipEmptyParts); } else if (key.endsWith(".VERSION")) { moduleInfo.version = QString::fromLocal8Bit(value); } else if (key.endsWith(".plugin_types")) { moduleInfo.supportedPluginTypes = makeList(value); } else if (key.endsWith(".TYPE")) { moduleInfo.pluginData.type = QString::fromLatin1(value); } else if (key.endsWith(".EXTENDS")) { moduleInfo.pluginData.extends = QString::fromLatin1(value); } else if (key.endsWith(".CLASS_NAME")) { moduleInfo.pluginData.className = QString::fromLatin1(value); } } if (hasV2 && !hasModuleEntry) moduleInfo.hasLibrary = false; // Fix include paths for OS X and iOS frameworks. // The qt_lib_XXX.pri files contain wrong values. if (moduleInfo.isFramework(qtEnvironment)) { moduleInfo.includePaths.clear(); QString baseIncDir = moduleInfo.frameworkHeadersPath(qtEnvironment); if (moduleInfo.isPrivate) { baseIncDir += QLatin1Char('/') + moduleInfo.version; moduleInfo.includePaths << baseIncDir << baseIncDir + QLatin1Char('/') + moduleInfo.name; } else { moduleInfo.includePaths << baseIncDir; } } moduleInfo.setupLibraries(qtEnvironment, &nonExistingPrlFiles); modules << moduleInfo; if (moduleInfo.qbsName == QLatin1String("testlib")) addTestModule(modules); if (moduleInfo.qbsName == QLatin1String("designercomponents-private")) addDesignerComponentsModule(modules); } replaceQtLibNamesWithFilePath(&modules, qtEnvironment); return modules; } QString QtModuleInfo::libBaseName(const QString &libName, bool debugBuild, const QtEnvironment &qtEnvironment) const { QString name = libName; if (qtEnvironment.mkspecName.startsWith(QLatin1String("win"))) { if (debugBuild) name += QLatin1Char('d'); if (!isStaticLibrary && qtEnvironment.qtMajorVersion < 5) name += QString::number(qtEnvironment.qtMajorVersion); } if (qtEnvironment.mkspecName.contains(QLatin1String("macx")) || qtEnvironment.mkspecName.contains(QLatin1String("ios")) || qtEnvironment.mkspecName.contains(QLatin1String("darwin"))) { if (!isFramework(qtEnvironment) && qtEnvironment.buildVariant.contains(QLatin1String("debug")) && (!qtEnvironment.buildVariant.contains(QLatin1String("release")) || debugBuild)) { name += QLatin1String("_debug"); } } return name; } } // namespace Internal } // namespace qbs qbs-src-1.4.5/src/lib/qtprofilesetup/qtmoduleinfo.h000066400000000000000000000075731266132464200224170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_QTMODULEINFO_H #define QBS_QTMODULEINFO_H #include #include namespace qbs { class QtEnvironment; class Profile; namespace Internal { class QtModuleInfo { public: QtModuleInfo(); QtModuleInfo(const QString &name, const QString &qbsName, const QStringList &deps = QStringList()); QString moduleNameWithoutPrefix() const; QString frameworkHeadersPath(const QtEnvironment &qtEnvironment) const; QStringList qt4ModuleIncludePaths(const QtEnvironment &qtEnvironment) const; QString libraryBaseName(const QtEnvironment &qtEnvironment, bool debugBuild) const; QString libBaseName(const QString &libName, bool debugBuild, const QtEnvironment &qtEnvironment) const; QString libNameForLinker(const QtEnvironment &qtEnvironment, bool debugBuild) const; void setupLibraries(const QtEnvironment &qtEnv, QSet *nonExistingPrlFiles); bool isFramework(const QtEnvironment &qtEnv) const; QString modulePrefix; // default is empty and means "Qt". QString name; // As in the path to the headers and ".name" in the pri files. QString qbsName; // Lower-case version without "qt" prefix. QString version; QStringList dependencies; // qbs names. QStringList includePaths; QStringList compilerDefines; QStringList staticLibrariesDebug; QStringList staticLibrariesRelease; QStringList dynamicLibrariesDebug; QStringList dynamicLibrariesRelease; QStringList linkerFlagsDebug; QStringList linkerFlagsRelease; QString libFilePathDebug; QString libFilePathRelease; QStringList frameworksDebug; QStringList frameworksRelease; QStringList frameworkPathsDebug; QStringList frameworkPathsRelease; QStringList libraryPaths; bool isPrivate; bool hasLibrary; bool isStaticLibrary; bool isPlugin; bool mustExist; QStringList supportedPluginTypes; struct PluginData { QString type; QString extends; QString className; } pluginData; private: void setupLibraries(const QtEnvironment &qtEnv, bool debugBuild, QSet *nonExistingPrlFiles); }; QList allQt4Modules(const QtEnvironment &qtEnvironment); QList allQt5Modules(const Profile &profile, const QtEnvironment &qtEnvironment); } // namespace Internal } // namespace qbs #endif // Include guard. qbs-src-1.4.5/src/lib/qtprofilesetup/qtprofilesetup.cpp000066400000000000000000000456751266132464200233370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "qtprofilesetup.h" #include "qtmoduleinfo.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace qbs { using namespace Internal; template QByteArray utf8JSLiteral(T t) { return toJSLiteral(t).toUtf8(); } static QString pathToJSLiteral(const QString &path) { return toJSLiteral(QDir::fromNativeSeparators(path)); } static QString defaultQpaPlugin(const Profile &profile, const QtModuleInfo &module, const QtEnvironment &qtEnv) { if (qtEnv.qtMajorVersion < 5) return QString(); QFile qConfigPri(qtEnv.mkspecBasePath + QLatin1String("/qconfig.pri")); if (!qConfigPri.open(QIODevice::ReadOnly)) { throw ErrorInfo(Tr::tr("Setting up Qt profile '%1' failed: Cannot open " "file '%2' (%3).") .arg(profile.name(), qConfigPri.fileName(), qConfigPri.errorString())); } const QList lines = qConfigPri.readAll().split('\n'); const QByteArray magicString = "QT_DEFAULT_QPA_PLUGIN ="; foreach (const QByteArray &line, lines) { const QByteArray simplifiedLine = line.simplified(); if (simplifiedLine.startsWith(magicString)) return QString::fromLatin1(simplifiedLine.mid(magicString.count()).trimmed()); } if (module.isStaticLibrary) qDebug("Warning: Could not determine default QPA plugin for static Qt."); return QString(); } static void replaceSpecialValues(QByteArray *content, const Profile &profile, const QtModuleInfo &module, const QtEnvironment &qtEnvironment) { content->replace("@name@", utf8JSLiteral(module.moduleNameWithoutPrefix())); content->replace("@has_library@", utf8JSLiteral(module.hasLibrary)); content->replace("@dependencies@", utf8JSLiteral(module.dependencies)); content->replace("@includes@", utf8JSLiteral(module.includePaths)); content->replace("@staticLibsDebug@", utf8JSLiteral(module.staticLibrariesDebug)); content->replace("@staticLibsRelease@", utf8JSLiteral(module.staticLibrariesRelease)); content->replace("@dynamicLibsDebug@", utf8JSLiteral(module.dynamicLibrariesDebug)); content->replace("@dynamicLibsRelease@", utf8JSLiteral(module.dynamicLibrariesRelease)); content->replace("@linkerFlagsDebug@", utf8JSLiteral(module.linkerFlagsDebug)); content->replace("@linkerFlagsRelease@", utf8JSLiteral(module.linkerFlagsRelease)); content->replace("@libraryPaths@", utf8JSLiteral(module.libraryPaths)); content->replace("@frameworkPathsDebug@", utf8JSLiteral(module.frameworkPathsDebug)); content->replace("@frameworkPathsRelease@", utf8JSLiteral(module.frameworkPathsRelease)); content->replace("@frameworksDebug@", utf8JSLiteral(module.frameworksDebug)); content->replace("@frameworksRelease@", utf8JSLiteral(module.frameworksRelease)); content->replace("@libFilePathDebug@", utf8JSLiteral(module.libFilePathDebug)); content->replace("@libFilePathRelease@", utf8JSLiteral(module.libFilePathRelease)); content->replace("@libNameForLinkerDebug@", utf8JSLiteral(module.libNameForLinker(qtEnvironment, true))); content->replace("@libNameForLinkerRelease@", utf8JSLiteral(module.libNameForLinker(qtEnvironment, false))); content->replace("@entryPointLibsDebug@", utf8JSLiteral(qtEnvironment.entryPointLibsDebug)); content->replace("@entryPointLibsRelease@", utf8JSLiteral(qtEnvironment.entryPointLibsRelease)); QByteArray propertiesString; QByteArray compilerDefines = utf8JSLiteral(module.compilerDefines); if (module.qbsName == QLatin1String("declarative") || module.qbsName == QLatin1String("quick")) { const QByteArray debugMacro = module.qbsName == QLatin1String("declarative") || qtEnvironment.qtMajorVersion < 5 ? "QT_DECLARATIVE_DEBUG" : "QT_QML_DEBUG"; const QString indent = QLatin1String(" "); QTextStream s(&propertiesString); s << "property bool qmlDebugging: false" << endl; s << indent << "property string qmlPath"; if (qtEnvironment.qmlPath.isEmpty()) s << endl; else s << ": " << pathToJSLiteral(qtEnvironment.qmlPath) << endl; s << indent << "property string qmlImportsPath: " << pathToJSLiteral(qtEnvironment.qmlImportPath); const QByteArray baIndent(4, ' '); compilerDefines = "{\n" + baIndent + baIndent + "var result = " + compilerDefines + ";\n" + baIndent + baIndent + "if (qmlDebugging)\n" + baIndent + baIndent + baIndent + "result.push(\"" + debugMacro + "\");\n" + baIndent + baIndent + "return result;\n" + baIndent + "}"; } content->replace("@defines@", compilerDefines); if (module.qbsName == QLatin1String("gui")) { content->replace("@defaultQpaPlugin@", utf8JSLiteral(defaultQpaPlugin(profile, module, qtEnvironment))); } if (module.isStaticLibrary) { if (!propertiesString.isEmpty()) propertiesString += "\n "; propertiesString += "isStaticLibrary: true"; } if (module.isPlugin) content->replace("@className@", utf8JSLiteral(module.pluginData.className)); content->replace("@special_properties@", propertiesString); } static void copyTemplateFile(const QString &fileName, const QString &targetDirectory, const Profile &profile, const QtEnvironment &qtEnv, QStringList *allFiles, const QtModuleInfo *module = 0) { if (!QDir::root().mkpath(targetDirectory)) { throw ErrorInfo(Internal::Tr::tr("Setting up Qt profile '%1' failed: " "Cannot create directory '%2'.") .arg(profile.name(), targetDirectory)); } QFile sourceFile(QLatin1String(":/templates/") + fileName); if (!sourceFile.open(QIODevice::ReadOnly)) { throw ErrorInfo(Internal::Tr::tr("Setting up Qt profile '%1' failed: " "Cannot open '%1' (%2).").arg(sourceFile.fileName(), sourceFile.errorString())); } QByteArray newContent = sourceFile.readAll(); if (module) replaceSpecialValues(&newContent, profile, *module, qtEnv); sourceFile.close(); const QString targetPath = targetDirectory + QLatin1Char('/') + fileName; allFiles->append(QFileInfo(targetPath).absoluteFilePath()); QFile targetFile(targetPath); if (targetFile.open(QIODevice::ReadOnly)) { if (newContent == targetFile.readAll()) // No need to overwrite anything in this case. return; targetFile.close(); } if (!targetFile.open(QIODevice::WriteOnly)) { throw ErrorInfo(Internal::Tr::tr("Setting up Qt profile '%1' failed: " "Cannot open '%1' (%2).").arg(targetFile.fileName(), targetFile.errorString())); } targetFile.resize(0); targetFile.write(newContent); } static void createModules(Profile &profile, Settings *settings, const QtEnvironment &qtEnvironment) { const QList modules = qtEnvironment.qtMajorVersion < 5 ? allQt4Modules(qtEnvironment) : allQt5Modules(profile, qtEnvironment); const QString profileBaseDir = QString::fromLocal8Bit("%1/qbs/profiles/%2") .arg(QFileInfo(settings->fileName()).dir().absolutePath(), profile.name()); const QString qbsQtModuleBaseDir = profileBaseDir + QLatin1String("/modules/Qt"); QStringList allFiles; copyTemplateFile(QLatin1String("QtModule.qbs"), qbsQtModuleBaseDir, profile, qtEnvironment, &allFiles); copyTemplateFile(QLatin1String("QtPlugin.qbs"), qbsQtModuleBaseDir, profile, qtEnvironment, &allFiles); foreach (const QtModuleInfo &module, modules) { const QString qbsQtModuleDir = qbsQtModuleBaseDir + QLatin1Char('/') + module.qbsName; QString moduleTemplateFileName; if (module.qbsName == QLatin1String("core")) { moduleTemplateFileName = QLatin1String("core.qbs"); copyTemplateFile(QLatin1String("moc.js"), qbsQtModuleDir, profile, qtEnvironment, &allFiles); } else if (module.qbsName == QLatin1String("gui")) { moduleTemplateFileName = QLatin1String("gui.qbs"); } else if (module.qbsName == QLatin1String("phonon")) { moduleTemplateFileName = QLatin1String("phonon.qbs"); } else if (module.isPlugin) { moduleTemplateFileName = QLatin1String("plugin.qbs"); } else { moduleTemplateFileName = QLatin1String("module.qbs"); } copyTemplateFile(moduleTemplateFileName, qbsQtModuleDir, profile, qtEnvironment, &allFiles, &module); } QDirIterator dit(qbsQtModuleBaseDir, QDirIterator::Subdirectories); while (dit.hasNext()) { dit.next(); const QFileInfo &fi = dit.fileInfo(); if (!fi.isFile()) continue; const QString filePath = fi.absoluteFilePath(); if (!allFiles.contains(filePath) && !QFile::remove(filePath)) qDebug("Warning: Failed to remove outdated file '%s'.", qPrintable(filePath)); } profile.setValue(QLatin1String("preferences.qbsSearchPaths"), profileBaseDir); } static QString guessMinimumWindowsVersion(const QtEnvironment &qt) { if (qt.mkspecName.startsWith(QLatin1String("winrt-"))) return QLatin1String("6.2"); if (!qt.mkspecName.startsWith(QLatin1String("win32-"))) return QString(); if (qt.architecture == QLatin1String("x86_64") || qt.architecture == QLatin1String("ia64")) { return QLatin1String("5.2"); } QRegExp rex(QLatin1String("^win32-msvc(\\d+)$")); if (rex.exactMatch(qt.mkspecName)) { int msvcVersion = rex.cap(1).toInt(); if (msvcVersion < 2012) return QLatin1String("5.0"); else return QLatin1String("5.1"); } return qt.qtMajorVersion < 5 ? QLatin1String("5.0") : QLatin1String("5.1"); } static bool checkForStaticBuild(const QtEnvironment &qt) { if (qt.qtMajorVersion >= 5) return qt.qtConfigItems.contains(QLatin1String("static")); if (qt.frameworkBuild) return false; // there are no Qt4 static frameworks const bool isWin = qt.mkspecName.startsWith(QLatin1String("win")); const QDir libdir(isWin ? qt.binaryPath : qt.libraryPath); const QStringList coreLibFiles = libdir.entryList(QStringList(QLatin1String("*Core*")), QDir::Files); if (coreLibFiles.isEmpty()) throw ErrorInfo(Internal::Tr::tr("Could not determine whether Qt is a static build.")); foreach (const QString &fileName, coreLibFiles) { if (QLibrary::isLibrary(fileName)) return false; } return true; } static QStringList fillEntryPointLibs(const QtEnvironment &qtEnvironment, const Version &qtVersion, bool debug) { QStringList result; QString qtmain = qtEnvironment.libraryPath + QLatin1Char('/'); const bool isMinGW = qtEnvironment.mkspecName.startsWith(QLatin1String("win32-g++")); if (isMinGW) qtmain += QLatin1String("lib"); qtmain += QLatin1String("qtmain") + qtEnvironment.qtLibInfix; if (debug) qtmain += QLatin1Char('d'); if (isMinGW) { qtmain += QLatin1String(".a"); } else { qtmain += QLatin1String(".lib"); if (qtVersion >= Version(5, 4, 0)) result << QLatin1String("Shell32.lib"); } result << qtmain; return result; } void doSetupQtProfile(const QString &profileName, Settings *settings, const QtEnvironment &_qtEnvironment) { QtEnvironment qtEnvironment = _qtEnvironment; qtEnvironment.staticBuild = checkForStaticBuild(qtEnvironment); // determine whether user apps require C++11 if (qtEnvironment.qtConfigItems.contains(QLatin1String("c++11")) && qtEnvironment.staticBuild) qtEnvironment.configItems.append(QLatin1String("c++11")); Profile profile(profileName, settings); profile.removeProfile(); const QString settingsTemplate(QLatin1String("Qt.core.%1")); profile.setValue(settingsTemplate.arg(QLatin1String("config")), qtEnvironment.configItems); profile.setValue(settingsTemplate.arg(QLatin1String("qtConfig")), qtEnvironment.qtConfigItems); profile.setValue(settingsTemplate.arg(QLatin1String("binPath")), qtEnvironment.binaryPath); profile.setValue(settingsTemplate.arg(QLatin1String("libPath")), qtEnvironment.libraryPath); profile.setValue(settingsTemplate.arg(QLatin1String("pluginPath")), qtEnvironment.pluginPath); profile.setValue(settingsTemplate.arg(QLatin1String("incPath")), qtEnvironment.includePath); profile.setValue(settingsTemplate.arg(QLatin1String("mkspecPath")), qtEnvironment.mkspecPath); profile.setValue(settingsTemplate.arg(QLatin1String("docPath")), qtEnvironment.documentationPath); profile.setValue(settingsTemplate.arg(QLatin1String("version")), qtEnvironment.qtVersion); profile.setValue(settingsTemplate.arg(QLatin1String("libInfix")), qtEnvironment.qtLibInfix); profile.setValue(settingsTemplate.arg(QLatin1String("buildVariant")), qtEnvironment.buildVariant); // TODO: Remove in 1.5 profile.setValue(settingsTemplate.arg(QLatin1String("availableBuildVariants")), qtEnvironment.buildVariant); profile.setValue(settingsTemplate.arg(QLatin1String("staticBuild")), qtEnvironment.staticBuild); // Set the minimum operating system versions appropriate for this Qt version const QString windowsVersion = guessMinimumWindowsVersion(qtEnvironment); QString osxVersion, iosVersion, androidVersion; if (!windowsVersion.isEmpty()) { // Is target OS Windows? const Version qtVersion = Version(qtEnvironment.qtMajorVersion, qtEnvironment.qtMinorVersion, qtEnvironment.qtPatchVersion); qtEnvironment.entryPointLibsDebug = fillEntryPointLibs(qtEnvironment, qtVersion, true); qtEnvironment.entryPointLibsRelease = fillEntryPointLibs(qtEnvironment, qtVersion, false); } else if (qtEnvironment.mkspecPath.contains(QLatin1String("macx"))) { profile.setValue(settingsTemplate.arg(QLatin1String("frameworkBuild")), qtEnvironment.frameworkBuild); if (qtEnvironment.qtMajorVersion >= 5) { osxVersion = QLatin1String("10.6"); } else if (qtEnvironment.qtMajorVersion == 4 && qtEnvironment.qtMinorVersion >= 6) { QDir qconfigDir; if (qtEnvironment.frameworkBuild) { qconfigDir.setPath(qtEnvironment.libraryPath); qconfigDir.cd(QLatin1String("QtCore.framework/Headers")); } else { qconfigDir.setPath(qtEnvironment.includePath); qconfigDir.cd(QLatin1String("Qt")); } QFile qconfig(qconfigDir.absoluteFilePath(QLatin1String("qconfig.h"))); if (qconfig.open(QIODevice::ReadOnly)) { bool qtCocoaBuild = false; QTextStream ts(&qconfig); QString line; do { line = ts.readLine(); if (QRegExp(QLatin1String("\\s*#define\\s+QT_MAC_USE_COCOA\\s+1\\s*"), Qt::CaseSensitive).exactMatch(line)) { qtCocoaBuild = true; break; } } while (!line.isNull()); if (ts.status() == QTextStream::Ok) osxVersion = qtCocoaBuild ? QLatin1String("10.5") : QLatin1String("10.4"); } if (osxVersion.isEmpty()) { throw ErrorInfo(Internal::Tr::tr("Error reading qconfig.h; could not determine " "whether Qt is using Cocoa or Carbon")); } } if (qtEnvironment.qtConfigItems.contains(QLatin1String("c++11"))) osxVersion = QLatin1String("10.7"); } if (qtEnvironment.mkspecPath.contains(QLatin1String("ios")) && qtEnvironment.qtMajorVersion >= 5) iosVersion = QLatin1String("5.0"); if (qtEnvironment.mkspecPath.contains(QLatin1String("android"))) { if (qtEnvironment.qtMajorVersion >= 5) androidVersion = QLatin1String("2.3"); else if (qtEnvironment.qtMajorVersion == 4 && qtEnvironment.qtMinorVersion >= 8) androidVersion = QLatin1String("1.6"); // Necessitas } // ### TODO: wince, winphone, blackberry if (!windowsVersion.isEmpty()) profile.setValue(QLatin1String("cpp.minimumWindowsVersion"), windowsVersion); if (!osxVersion.isEmpty()) profile.setValue(QLatin1String("cpp.minimumOsxVersion"), osxVersion); if (!iosVersion.isEmpty()) profile.setValue(QLatin1String("cpp.minimumIosVersion"), iosVersion); if (!androidVersion.isEmpty()) profile.setValue(QLatin1String("cpp.minimumAndroidVersion"), androidVersion); createModules(profile, settings, qtEnvironment); } ErrorInfo setupQtProfile(const QString &profileName, Settings *settings, const QtEnvironment &qtEnvironment) { try { doSetupQtProfile(profileName, settings, qtEnvironment); return ErrorInfo(); } catch (const ErrorInfo &e) { return e; } } } // namespace qbs qbs-src-1.4.5/src/lib/qtprofilesetup/qtprofilesetup.h000066400000000000000000000036001266132464200227620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_SETUPQTPROFILE_H #define QBS_SETUPQTPROFILE_H #include "qtenvironment.h" #include #include namespace qbs { class ErrorInfo; class Settings; QBS_EXPORT ErrorInfo setupQtProfile(const QString &profileName, Settings *settings, const QtEnvironment &qtEnvironment); } // namespace qbs #endif // Include guard. qbs-src-1.4.5/src/lib/qtprofilesetup/qtprofilesetup.pro000066400000000000000000000010171266132464200233330ustar00rootroot00000000000000TARGET = qbsqtprofilesetup include(../library.pri) include(../corelib/use_corelib.pri) HEADERS = \ qtenvironment.h \ qtmoduleinfo.h \ qtprofilesetup.h SOURCES = \ qtmoduleinfo.cpp \ qtprofilesetup.cpp RESOURCES = templates.qrc !qbs_no_dev_install { header.files = qtenvironment.h qtprofilesetup.h header.path = $${QBS_INSTALL_PREFIX}/include/qbs use_pri.files = use_installed_qtprofilesetup.pri use_pri.path = $${header.path} INSTALLS += header use_pri } OTHER_FILES += templates/* qbs-src-1.4.5/src/lib/qtprofilesetup/qtprofilesetup.qbs000066400000000000000000000011031266132464200233140ustar00rootroot00000000000000import qbs QbsLibrary { name: "qbsqtprofilesetup" Depends { name: "qbscore" } Group { name: "Public API headers" files: [ "qtenvironment.h", "qtprofilesetup.h", "use_installed_qtprofilesetup.pri", ] qbs.install: project.installApiHeaders qbs.installDir: headerInstallPrefix } files: [ "qtprofilesetup.cpp", "qtmoduleinfo.cpp", "qtmoduleinfo.h", "templates.qrc", "templates/*" ] Export { Depends { name: "qbscore" } } } qbs-src-1.4.5/src/lib/qtprofilesetup/templates.qrc000066400000000000000000000006041266132464200222310ustar00rootroot00000000000000 templates/core.qbs templates/gui.qbs templates/phonon.qbs templates/module.qbs templates/QtModule.qbs templates/moc.js templates/plugin.qbs templates/QtPlugin.qbs qbs-src-1.4.5/src/lib/qtprofilesetup/templates/000077500000000000000000000000001266132464200215225ustar00rootroot00000000000000qbs-src-1.4.5/src/lib/qtprofilesetup/templates/QtModule.qbs000066400000000000000000000047261266132464200237740ustar00rootroot00000000000000import qbs 1.0 import qbs.FileInfo Module { Depends { name: "cpp" } Depends { name: "Qt.core" } property string qtModuleName property path binPath: Qt.core.binPath property path incPath: Qt.core.incPath property path libPath: Qt.core.libPath property string qtLibInfix: Qt.core.libInfix property string libNameForLinkerDebug property string libNameForLinkerRelease property string libNameForLinker: Qt.core.qtBuildVariant === "debug" ? libNameForLinkerDebug : libNameForLinkerRelease property string libFilePathDebug property string libFilePathRelease property string libFilePath: Qt.core.qtBuildVariant === "debug" ? libFilePathDebug : libFilePathRelease property string qtVersion: Qt.core.version property bool hasLibrary: true property bool isStaticLibrary: false property bool isPlugin: false property stringList staticLibsDebug property stringList staticLibsRelease property stringList dynamicLibsDebug property stringList dynamicLibsRelease property stringList linkerFlagsDebug property stringList linkerFlagsRelease property stringList staticLibs: Qt.core.qtBuildVariant === "debug" ? staticLibsDebug : staticLibsRelease property stringList dynamicLibs: Qt.core.qtBuildVariant === "debug" ? dynamicLibsDebug : dynamicLibsRelease property stringList frameworksDebug property stringList frameworksRelease property stringList frameworkPathsDebug property stringList frameworkPathsRelease property stringList mFrameworks: Qt.core.qtBuildVariant === "debug" ? frameworksDebug : frameworksRelease property stringList mFrameworkPaths: Qt.core.qtBuildVariant === "debug" ? frameworkPathsDebug: frameworkPathsRelease cpp.linkerFlags: Qt.core.qtBuildVariant === "debug" ? linkerFlagsDebug : linkerFlagsRelease Properties { condition: qtModuleName != undefined && hasLibrary cpp.staticLibraries: (isStaticLibrary ? [libFilePath] : []).concat(staticLibs) cpp.dynamicLibraries: (!isStaticLibrary && !Qt.core.frameworkBuild ? [libFilePath] : []).concat(dynamicLibs) cpp.frameworks: mFrameworks.concat(!isStaticLibrary && Qt.core.frameworkBuild ? [libNameForLinker] : []) cpp.frameworkPaths: mFrameworkPaths } } qbs-src-1.4.5/src/lib/qtprofilesetup/templates/QtPlugin.qbs000066400000000000000000000017211266132464200237750ustar00rootroot00000000000000import qbs 1.0 import qbs.FileInfo import qbs.TextFile QtModule { isPlugin: true property string className Transformer { condition: isStaticLibrary Artifact { filePath: product.targetName + "_qt_plugin_import_" + parent.parent.qtModuleName + ".cpp" fileTags: "cpp" } prepare: { var cmd = new JavaScriptCommand(); var pluginName = product.moduleProperty(product.moduleName, "qtModuleName"); cmd.description = "Creating static import for plugin '" + pluginName + "'."; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); var className = product.moduleProperty(product.moduleName, "className"); f.writeLine("#include \n\nQ_IMPORT_PLUGIN(" + className + ")"); f.close(); }; return cmd; } } } qbs-src-1.4.5/src/lib/qtprofilesetup/templates/core.qbs000066400000000000000000000332661266132464200231730ustar00rootroot00000000000000import qbs 1.0 import qbs.FileInfo import qbs.ModUtils import "moc.js" as Moc Module { id: qtcore Depends { name: "cpp" } property string libInfix: "" property stringList config property stringList qtConfig property path binPath property path incPath property path libPath property path pluginPath property path mkspecPath property string mocName: "moc" property string lreleaseName: "lrelease" property string qdocName: versionMajor >= 5 ? "qdoc" : "qdoc3" property stringList qdocEnvironment property string qdocQhpFileName property path docPath property stringList helpGeneratorArgs: versionMajor >= 5 ? ["-platform", "minimal"] : [] property string version property var versionParts: version ? version.split('.').map(function(item) { return parseInt(item, 10); }) : [] property int versionMajor: versionParts[0] property int versionMinor: versionParts[1] property int versionPatch: versionParts[2] property bool frameworkBuild property bool staticBuild property stringList availableBuildVariants property stringList buildVariant // TODO: Remove in 1.5 property string qtBuildVariant: { if (availableBuildVariants.contains(qbs.buildVariant)) return qbs.buildVariant; return availableBuildVariants.length > 0 ? availableBuildVariants[0] : ""; } property stringList staticLibsDebug: @staticLibsDebug@ property stringList staticLibsRelease: @staticLibsRelease@ property stringList dynamicLibsDebug: @dynamicLibsDebug@ property stringList dynamicLibsRelease: @dynamicLibsRelease@ property stringList staticLibs: qtBuildVariant === "debug" ? staticLibsDebug : staticLibsRelease property stringList dynamicLibs: qtBuildVariant === "debug" ? dynamicLibsDebug : dynamicLibsRelease property stringList linkerFlagsDebug: @linkerFlagsDebug@ property stringList linkerFlagsRelease: @linkerFlagsRelease@ property stringList coreLinkerFlags: qtBuildVariant === "debug" ? linkerFlagsDebug : linkerFlagsRelease property stringList frameworksDebug: @frameworksDebug@ property stringList frameworksRelease: @frameworksRelease@ property stringList coreFrameworks: qtBuildVariant === "debug" ? frameworksDebug : frameworksRelease property stringList frameworkPathsDebug: @frameworkPathsDebug@ property stringList frameworkPathsRelease: @frameworkPathsRelease@ property stringList coreFrameworkPaths: qtBuildVariant === "debug" ? frameworkPathsDebug : frameworkPathsRelease property string libNameForLinkerDebug: @libNameForLinkerDebug@ property string libNameForLinkerRelease: @libNameForLinkerRelease@ property string libNameForLinker: qtBuildVariant === "debug" ? libNameForLinkerDebug : libNameForLinkerRelease property string libFilePathDebug: @libFilePathDebug@ property string libFilePathRelease: @libFilePathRelease@ property string libFilePath: qtBuildVariant === "debug" ? libFilePathDebug : libFilePathRelease coreLibPaths: @libraryPaths@ // These are deliberately not path types // We don't want to resolve them against the source directory property string generatedFilesDir: product.buildDirectory + "/GeneratedFiles" property string qmFilesDir: product.destinationDirectory cpp.defines: { var defines = @defines@; // ### QT_NO_DEBUG must be added if the current build variant is derived // from the build variant "release" if (!qbs.debugInformation) defines.push("QT_NO_DEBUG"); if (qbs.targetOS.contains("ios")) defines = defines.concat(["DARWIN_NO_CARBON", "QT_NO_CORESERVICES", "QT_NO_PRINTER", "QT_NO_PRINTDIALOG", "main=qtmn"]); return defines; } cpp.includePaths: { var paths = @includes@; paths.push(mkspecPath, generatedFilesDir); return paths; } cpp.libraryPaths: { var libPaths = [libPath]; if (staticBuild && pluginPath) libPaths.push(pluginPath + "/platforms"); libPaths = libPaths.concat(coreLibPaths); return libPaths; } cpp.staticLibraries: { var libs = []; if (staticBuild) libs.push(libFilePath); if (qbs.targetOS.contains('windows') && !product.consoleApplication) { libs = libs.concat(qtBuildVariant === "debug" ? @entryPointLibsDebug@ : @entryPointLibsRelease@); } libs = libs.concat(staticLibs); return libs; } cpp.dynamicLibraries: { var libs = []; if (!staticBuild && !frameworkBuild) libs.push(libFilePath); libs = libs.concat(dynamicLibs); return libs; } cpp.linkerFlags: coreLinkerFlags cpp.frameworkPaths: coreFrameworkPaths.concat(frameworkBuild ? [libPath] : []) cpp.frameworks: { var frameworks = coreFrameworks if (frameworkBuild) frameworks.push(libNameForLinker); if (qbs.targetOS.contains('ios') && staticBuild) frameworks = frameworks.concat(["Foundation", "CoreFoundation"]); if (frameworks.length === 0) return undefined; return frameworks; } cpp.rpaths: qbs.targetOS.contains('linux') ? [libPath] : undefined cpp.positionIndependentCode: versionMajor >= 5 ? true : undefined cpp.cxxFlags: { var flags = []; if (qbs.toolchain.contains('msvc')) { flags.push('/Zm200'); if (versionMajor < 5) flags.push('/Zc:wchar_t-'); } return flags; } cpp.cxxStandardLibrary: { if (qbs.targetOS.contains('darwin') && qbs.toolchain.contains('clang') && config.contains('c++11')) return "libc++"; return original; } additionalProductTypes: ["qm"] validate: { var validator = new ModUtils.PropertyValidator("Qt.core"); validator.setRequiredProperty("binPath", binPath); validator.setRequiredProperty("incPath", incPath); validator.setRequiredProperty("libPath", libPath); validator.setRequiredProperty("mkspecPath", mkspecPath); validator.setRequiredProperty("version", version); validator.setRequiredProperty("config", config); validator.setRequiredProperty("qtConfig", qtConfig); validator.setRequiredProperty("versionMajor", versionMajor); validator.setRequiredProperty("versionMinor", versionMinor); validator.setRequiredProperty("versionPatch", versionPatch); if (!staticBuild) validator.setRequiredProperty("pluginPath", pluginPath); // Allow custom version suffix since some distributions might want to do this, // but otherwise the version must start with a valid 3-component string validator.addVersionValidator("version", version, 3, 3, true); validator.addRangeValidator("versionMajor", versionMajor, 1); validator.addRangeValidator("versionMinor", versionMinor, 0); validator.addRangeValidator("versionPatch", versionPatch, 0); validator.addCustomValidator("availableBuildVariants", availableBuildVariants, function (v) { return v.length > 0; }, "the Qt installation supports no build variants"); validator.addCustomValidator("qtBuildVariant", qtBuildVariant, function (variant) { return availableBuildVariants.contains(variant); }, "'" + qtBuildVariant + "' is not supported by this Qt installation"); validator.addCustomValidator("qtBuildVariant", qtBuildVariant, function (variant) { return variant === qbs.buildVariant || !qbs.toolchain.contains("msvc"); }, " is '" + qtBuildVariant + "', but qbs.buildVariant is '" + qbs.buildVariant + "', which is not allowed when using MSVC"); validator.validate(); } setupRunEnvironment: { var env; if (qbs.targetOS.contains('windows')) { env = new ModUtils.EnvironmentVariable("PATH", qbs.pathListSeparator, true); env.append(binPath); env.set(); } else if (qbs.targetOS.contains("darwin")) { env = new ModUtils.EnvironmentVariable("DYLD_FRAMEWORK_PATH", qbs.pathListSeparator); env.append(libPath); env.set(); env = new ModUtils.EnvironmentVariable("DYLD_LIBRARY_PATH", qbs.pathListSeparator); env.append(libPath); env.set(); } } FileTagger { patterns: ["*.qrc"] fileTags: ["qrc"] } FileTagger { patterns: ["*.ts"] fileTags: ["ts"] } FileTagger { patterns: ["*.qdoc"] fileTags: ["qdoc"] } FileTagger { patterns: ["*.qdocconf"] fileTags: ["qdocconf"] } FileTagger { patterns: ["*.qhp"] fileTags: ["qhp"] } Rule { name: "QtCoreMocRule" inputs: ["objcpp", "cpp", "hpp"] auxiliaryInputs: ["qt_plugin_metadata"] excludedAuxiliaryInputs: ["unmocable"] outputFileTags: ["hpp", "cpp", "unmocable"] outputArtifacts: { var mocinfo = QtMocScanner.apply(input); if (!mocinfo.hasQObjectMacro) return []; var artifact = { fileTags: ["unmocable"] }; if (input.fileTags.contains("hpp")) { artifact.filePath = ModUtils.moduleProperty(product, "generatedFilesDir") + "/moc_" + input.completeBaseName + ".cpp"; } else { artifact.filePath = ModUtils.moduleProperty(product, "generatedFilesDir") + '/' + input.completeBaseName + ".moc"; } artifact.fileTags.push(mocinfo.mustCompile ? "cpp" : "hpp"); if (mocinfo.hasPluginMetaDataMacro) artifact.explicitlyDependsOn = ["qt_plugin_metadata"]; return [artifact]; } prepare: { var cmd = new Command(Moc.fullPath(product), Moc.args(product, input, output.filePath)); cmd.description = 'moc ' + input.fileName; cmd.highlight = 'codegen'; return cmd; } } Rule { inputs: ["qrc"] Artifact { filePath: ModUtils.moduleProperty(product, "generatedFilesDir") + "/qrc_" + input.completeBaseName + ".cpp"; fileTags: ["cpp"] } prepare: { var cmd = new Command(ModUtils.moduleProperty(product, "binPath") + '/rcc', [input.filePath, '-name', FileInfo.completeBaseName(input.filePath), '-o', output.filePath]); cmd.description = 'rcc ' + input.fileName; cmd.highlight = 'codegen'; return cmd; } } Rule { inputs: ["ts"] Artifact { filePath: FileInfo.joinPaths(ModUtils.moduleProperty(product, "qmFilesDir"), input.completeBaseName + ".qm") fileTags: ["qm"] } prepare: { var cmd = new Command(ModUtils.moduleProperty(product, "binPath") + '/' + ModUtils.moduleProperty(product, "lreleaseName"), ['-silent', input.filePath, '-qm', output.filePath]); cmd.description = 'lrelease ' + input.fileName; cmd.highlight = 'filegen'; return cmd; } } Rule { inputs: "qdocconf-main" explicitlyDependsOn: ["qdoc", "qdocconf"] Artifact { filePath: ModUtils.moduleProperty(product, "generatedFilesDir") + "/html" fileTags: ["qdoc-html"] } Artifact { filePath: ModUtils.moduleProperty(product, "generatedFilesDir") + "/html/" + ModUtils.moduleProperty(product, "qdocQhpFileName") fileTags: ["qhp"] } prepare: { var outputDir = outputs["qdoc-html"][0].filePath; var args = [input.filePath]; var qtVersion = ModUtils.moduleProperty(product, "versionMajor"); if (qtVersion >= 5) { args.push("-outputdir"); args.push(outputDir); } var cmd = new Command(ModUtils.moduleProperty(product, "binPath") + '/' + ModUtils.moduleProperty(product, "qdocName"), args); cmd.description = 'qdoc ' + input.fileName; cmd.highlight = 'filegen'; cmd.environment = ModUtils.moduleProperty(product, "qdocEnvironment"); cmd.environment.push("OUTDIR=" + outputDir); // Qt 4 replacement for -outputdir return cmd; } } Rule { inputs: "qhp" Artifact { filePath: ModUtils.moduleProperty(product, "generatedFilesDir") + '/' + input.completeBaseName + ".qch" fileTags: ["qch"] } prepare: { var args = [input.filePath]; args = args.concat(ModUtils.moduleProperty(product, "helpGeneratorArgs")); args.push("-o"); args.push(output.filePath); var cmd = new Command(ModUtils.moduleProperty(product, "binPath") + "/qhelpgenerator", args); cmd.description = 'qhelpgenerator ' + input.fileName; cmd.highlight = 'filegen'; cmd.stdoutFilterFunction = function(output) { return ""; }; return cmd; } } } qbs-src-1.4.5/src/lib/qtprofilesetup/templates/gui.qbs000066400000000000000000000035441266132464200230230ustar00rootroot00000000000000import qbs 1.0 import qbs.FileInfo import qbs.ModUtils import '../QtModule.qbs' as QtModule QtModule { qtModuleName: "Gui" property string uicName: "uic" FileTagger { patterns: ["*.ui"] fileTags: ["ui"] } Rule { inputs: ["ui"] Artifact { filePath: 'GeneratedFiles/ui_' + input.completeBaseName + '.h' fileTags: ["hpp"] } prepare: { var cmd = new Command(ModUtils.moduleProperty(product, "binPath") + '/' + ModUtils.moduleProperty(product, "uicName"), [input.filePath, '-o', output.filePath]) cmd.description = 'uic ' + input.fileName; cmd.highlight = 'codegen'; return cmd; } } property string defaultQpaPlugin: @defaultQpaPlugin@ staticLibsDebug: @staticLibsDebug@ staticLibsRelease: @staticLibsRelease@ dynamicLibsDebug: @dynamicLibsDebug@ dynamicLibsRelease: @dynamicLibsRelease@ linkerFlagsDebug: @linkerFlagsDebug@ linkerFlagsRelease: @linkerFlagsRelease@ frameworksDebug: @frameworksDebug@ frameworksRelease: @frameworksRelease@ frameworkPathsDebug: @frameworkPathsDebug@ frameworkPathsRelease: @frameworkPathsRelease@ libNameForLinkerDebug: @libNameForLinkerDebug@ libNameForLinkerRelease: @libNameForLinkerRelease@ libFilePathDebug: @libFilePathDebug@ libFilePathRelease: @libFilePathRelease@ cpp.defines: @defines@ cpp.includePaths: @includes@ cpp.libraryPaths: @libraryPaths@ Properties { condition: Qt.core.staticBuild && qbs.targetOS.contains("ios") cpp.frameworks: base.concat(["UIKit", "QuartzCore", "CoreText", "CoreGraphics", "Foundation", "CoreFoundation"]) } cpp.frameworks: base @special_properties@ } qbs-src-1.4.5/src/lib/qtprofilesetup/templates/moc.js000066400000000000000000000054231266132464200226420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ function args(product, input, outputFileName) { var defines = product.moduleProperty("cpp", "compilerDefines"); defines = defines.uniqueConcat(product.moduleProperty("cpp", "platformDefines")); defines = defines.uniqueConcat( ModUtils.modulePropertiesFromArtifacts(product, [input], 'cpp', 'defines')); var includePaths = ModUtils.modulePropertiesFromArtifacts(product, [input], 'cpp', 'includePaths'); includePaths = includePaths.uniqueConcat(ModUtils.modulePropertiesFromArtifacts( product, [input], 'cpp', 'systemIncludePaths')); var frameworkPaths = product.moduleProperties("cpp", "frameworkPaths"); frameworkPaths = frameworkPaths.uniqueConcat( product.moduleProperties("cpp", "systemFrameworkPaths")); var args = []; args = args.concat( defines.map(function(item) { return '-D' + item; }), includePaths.map(function(item) { return '-I' + item; }), frameworkPaths.map(function(item) { return '-F' + item; }), '-o', outputFileName, input.filePath); return args; } function fullPath(product) { return ModUtils.moduleProperty(product, "binPath") + '/' + ModUtils.moduleProperty(product, "mocName"); } qbs-src-1.4.5/src/lib/qtprofilesetup/templates/module.qbs000066400000000000000000000016341266132464200235220ustar00rootroot00000000000000import qbs 1.0 import '../QtModule.qbs' as QtModule QtModule { qtModuleName: @name@ Depends { name: "Qt"; submodules: @dependencies@} hasLibrary: @has_library@ staticLibsDebug: @staticLibsDebug@ staticLibsRelease: @staticLibsRelease@ dynamicLibsDebug: @dynamicLibsDebug@ dynamicLibsRelease: @dynamicLibsRelease@ linkerFlagsDebug: @linkerFlagsDebug@ linkerFlagsRelease: @linkerFlagsRelease@ frameworksDebug: @frameworksDebug@ frameworksRelease: @frameworksRelease@ frameworkPathsDebug: @frameworkPathsDebug@ frameworkPathsRelease: @frameworkPathsRelease@ libNameForLinkerDebug: @libNameForLinkerDebug@ libNameForLinkerRelease: @libNameForLinkerRelease@ libFilePathDebug: @libFilePathDebug@ libFilePathRelease: @libFilePathRelease@ cpp.defines: @defines@ cpp.includePaths: @includes@ cpp.libraryPaths: @libraryPaths@ @special_properties@ } qbs-src-1.4.5/src/lib/qtprofilesetup/templates/phonon.qbs000066400000000000000000000003121266132464200235260ustar00rootroot00000000000000import qbs 1.0 import '../QtModule.qbs' as QtModule QtModule { qtModuleName: "phonon" Depends { name: "Qt"; submodules: ['core'] } cpp.defines: @defines@ cpp.includePaths: @includes@ } qbs-src-1.4.5/src/lib/qtprofilesetup/templates/plugin.qbs000066400000000000000000000015351266132464200235330ustar00rootroot00000000000000import qbs 1.0 import '../QtPlugin.qbs' as QtPlugin QtPlugin { qtModuleName: @name@ Depends { name: "Qt"; submodules: @dependencies@} className: @className@ staticLibsDebug: @staticLibsDebug@ staticLibsRelease: @staticLibsRelease@ dynamicLibsDebug: @dynamicLibsDebug@ dynamicLibsRelease: @dynamicLibsRelease@ linkerFlagsDebug: @linkerFlagsDebug@ linkerFlagsRelease: @linkerFlagsRelease@ frameworksDebug: @frameworksDebug@ frameworksRelease: @frameworksRelease@ frameworkPathsDebug: @frameworkPathsDebug@ frameworkPathsRelease: @frameworkPathsRelease@ libNameForLinkerDebug: @libNameForLinkerDebug@ libNameForLinkerRelease: @libNameForLinkerRelease@ libFilePathDebug: @libFilePathDebug@ libFilePathRelease: @libFilePathRelease@ cpp.libraryPaths: @libraryPaths@ @special_properties@ } qbs-src-1.4.5/src/lib/qtprofilesetup/use_installed_qtprofilesetup.pri000066400000000000000000000007261266132464200262460ustar00rootroot00000000000000include(use_installed_corelib.pri) LIBNAME=qbsqtprofilesetup unix:LIBS += -l$${LIBNAME} win32 { CONFIG(debug, debug|release) { QBSQTPROFILELIB = $${LIBNAME}d$${QBSCORELIBSUFFIX} } CONFIG(release, debug|release) { QBSQTPROFILELIB = $${LIBNAME}$${QBSCORELIBSUFFIX} } win32-msvc* { QBSQTPROFILELIB = $${QBSQTPROFILELIB}.lib } else { QBSQTPROFILELIB = lib$${QBSQTPROFILELIB} } LIBS += $${QBSQTPROFILELIB} } qbs-src-1.4.5/src/lib/qtprofilesetup/use_qtprofilesetup.pri000066400000000000000000000021421266132464200242010ustar00rootroot00000000000000include(../../../qbs_version.pri) include(../../library_dirname.pri) isEmpty(QBSLIBDIR) { QBSLIBDIR = $${OUT_PWD}/../../../$${QBS_LIBRARY_DIRNAME} } LIBNAME=qbsqtprofilesetup unix { LIBS += -L$${QBSLIBDIR} -l$${LIBNAME} } !qbs_disable_rpath { linux-*:QMAKE_LFLAGS += -Wl,-z,origin \'-Wl,-rpath,\$\$ORIGIN/../$${QBS_LIBRARY_DIRNAME}\' macx:QMAKE_LFLAGS += -Wl,-rpath,@loader_path/../$${QBS_LIBRARY_DIRNAME} } !CONFIG(static, static|shared) { QBSQTPROFILELIBSUFFIX = $${QBS_VERSION_MAJ} } win32 { CONFIG(debug, debug|release) { QBSQTPROFILELIB = $${LIBNAME}d$${QBSQTPROFILELIBSUFFIX} } CONFIG(release, debug|release) { QBSQTPROFILELIB = $${LIBNAME}$${QBSQTPROFILELIBSUFFIX} } win32-msvc* { LIBS += /LIBPATH:$$QBSLIBDIR QBSQTPROFILELIB = $${QBSQTPROFILELIB}.lib LIBS += Shell32.lib } else { LIBS += -L$${QBSLIBDIR} QBSQTPROFILELIB = lib$${QBSQTPROFILELIB} } LIBS += $${QBSQTPROFILELIB} } INCLUDEPATH += \ $$PWD CONFIG += depend_includepath CONFIG(static, static|shared) { DEFINES += QBS_STATIC_LIB } qbs-src-1.4.5/src/libexec/000077500000000000000000000000001266132464200153035ustar00rootroot00000000000000qbs-src-1.4.5/src/libexec/libexec.pri000066400000000000000000000004301266132464200174270ustar00rootroot00000000000000include(../install_prefix.pri) !isEmpty(QBS_LIBEXEC_DESTDIR):DESTDIR=$${QBS_LIBEXEC_DESTDIR} else:DESTDIR = ../../../libexec/qbs !isEmpty(QBS_LIBEXEC_INSTALL_DIR):target.path = $${QBS_LIBEXEC_INSTALL_DIR} else:target.path = $${QBS_INSTALL_PREFIX}/libexec/qbs INSTALLS += target qbs-src-1.4.5/src/libexec/libexec.pro000066400000000000000000000000231266132464200174330ustar00rootroot00000000000000TEMPLATE = subdirs qbs-src-1.4.5/src/libexec/libexec.qbs000066400000000000000000000000601266132464200174210ustar00rootroot00000000000000import qbs Project { references: [ ] } qbs-src-1.4.5/src/library_dirname.pri000066400000000000000000000000671266132464200175520ustar00rootroot00000000000000isEmpty(QBS_LIBRARY_DIRNAME):QBS_LIBRARY_DIRNAME = lib qbs-src-1.4.5/src/plugins/000077500000000000000000000000001266132464200153515ustar00rootroot00000000000000qbs-src-1.4.5/src/plugins/plugins.pri000066400000000000000000000010741266132464200175500ustar00rootroot00000000000000include(../library_dirname.pri) include(../install_prefix.pri) !isEmpty(QBS_PLUGINS_BUILD_DIR) { destdirPrefix = $${QBS_PLUGINS_BUILD_DIR} } else { destdirPrefix = $$shadowed($$PWD)/../../$${QBS_LIBRARY_DIRNAME} } DESTDIR = $${destdirPrefix}/qbs/plugins TEMPLATE = lib CONFIG += depend_includepath CONFIG += shared unix: CONFIG += plugin !isEmpty(QBS_PLUGINS_INSTALL_DIR): \ installPrefix = $${QBS_PLUGINS_INSTALL_DIR} else: \ installPrefix = $${QBS_INSTALL_PREFIX}/$${QBS_LIBRARY_DIRNAME} target.path = $${installPrefix}/qbs/plugins INSTALLS += target qbs-src-1.4.5/src/plugins/plugins.pro000066400000000000000000000000451266132464200175530ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS = scanner qbs-src-1.4.5/src/plugins/plugins.qbs000066400000000000000000000002031266132464200175340ustar00rootroot00000000000000import qbs Project { name: "qbs plugins" references: [ "scanner/cpp/cpp.qbs", "scanner/qt/qt.qbs" ] } qbs-src-1.4.5/src/plugins/scanner/000077500000000000000000000000001266132464200170025ustar00rootroot00000000000000qbs-src-1.4.5/src/plugins/scanner/cpp/000077500000000000000000000000001266132464200175645ustar00rootroot00000000000000qbs-src-1.4.5/src/plugins/scanner/cpp/CPlusPlusForwardDeclarations.h000066400000000000000000000105341266132464200255100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ // Copyright (c) 2008 Roberto Raggi // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #ifndef CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H #define CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H #include #include #ifndef CPLUSPLUS_WITHOUT_QT # include //# if defined(CPLUSPLUS_BUILD_LIB) //# define CPLUSPLUS_EXPORT Q_DECL_EXPORT //# elif defined(CPLUSPLUS_BUILD_STATIC_LIB) //# define CPLUSPLUS_EXPORT //# else //# define CPLUSPLUS_EXPORT Q_DECL_IMPORT //# endif //#else # define CPLUSPLUS_EXPORT #endif namespace CPlusPlus { class TranslationUnit; class Control; class MemoryPool; class DiagnosticClient; class Identifier; class Literal; class StringLiteral; class NumericLiteral; class SymbolTable; // names class NameVisitor; class Name; class Identifier; class TemplateNameId; class DestructorNameId; class OperatorNameId; class ConversionNameId; class QualifiedNameId; class SelectorNameId; // types class TypeMatcher; class FullySpecifiedType; class TypeVisitor; class Type; class UndefinedType; class VoidType; class IntegerType; class FloatType; class PointerToMemberType; class PointerType; class ReferenceType; class ArrayType; class NamedType; // symbols class SymbolVisitor; class Symbol; class Scope; class UsingNamespaceDirective; class UsingDeclaration; class Declaration; class Argument; class TypenameArgument; class Function; class Namespace; class NamespaceAlias; class Template; class BaseClass; class Block; class Class; class Enum; class ForwardClassDeclaration; class Token; // Objective-C symbols class ObjCBaseClass; class ObjCBaseProtocol; class ObjCClass; class ObjCForwardClassDeclaration; class ObjCProtocol; class ObjCForwardProtocolDeclaration; class ObjCMethod; class ObjCPropertyDeclaration; } // end of namespace CPlusPlus #endif // CPLUSPLUS_CPLUSPLUSFORWARDDECLARATIONS_H qbs-src-1.4.5/src/plugins/scanner/cpp/Lexer.cpp000066400000000000000000000421671266132464200213610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ // Copyright (c) 2008 Roberto Raggi // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "Lexer.h" #include using namespace CPlusPlus; Lexer::Lexer(const char *firstChar, const char *lastChar) : _state(State_Default), _flags(0), _currentLine(1) { setSource(firstChar, lastChar); } Lexer::~Lexer() { } void Lexer::setSource(const char *firstChar, const char *lastChar) { _firstChar = firstChar; _lastChar = lastChar; _currentChar = _firstChar - 1; _tokenStart = _currentChar; _yychar = '\n'; } void Lexer::setStartWithNewline(bool enabled) { if (enabled) _yychar = '\n'; else _yychar = ' '; } int Lexer::state() const { return _state; } void Lexer::setState(int state) { _state = state; } bool Lexer::qtMocRunEnabled() const { return f._qtMocRunEnabled; } void Lexer::setQtMocRunEnabled(bool onoff) { f._qtMocRunEnabled = onoff; } bool Lexer::cxx0xEnabled() const { return f._cxx0xEnabled; } void Lexer::setCxxOxEnabled(bool onoff) { f._cxx0xEnabled = onoff; } bool Lexer::objCEnabled() const { return f._objCEnabled; } void Lexer::setObjCEnabled(bool onoff) { f._objCEnabled = onoff; } bool Lexer::isIncremental() const { return f._isIncremental; } void Lexer::setIncremental(bool isIncremental) { f._isIncremental = isIncremental; } bool Lexer::scanCommentTokens() const { return f._scanCommentTokens; } void Lexer::setScanCommentTokens(bool onoff) { f._scanCommentTokens = onoff; } void Lexer::setScanAngleStringLiteralTokens(bool onoff) { f._scanAngleStringLiteralTokens = onoff; } void Lexer::pushLineStartOffset() { ++_currentLine; } unsigned Lexer::tokenOffset() const { return _tokenStart - _firstChar; } unsigned Lexer::tokenLength() const { return _currentChar - _tokenStart; } const char *Lexer::tokenBegin() const { return _tokenStart; } const char *Lexer::tokenEnd() const { return _currentChar; } unsigned Lexer::currentLine() const { return _currentLine; } void Lexer::scan(Token *tok) { tok->reset(); scan_helper(tok); tok->f.length = _currentChar - _tokenStart; } void Lexer::scan_helper(Token *tok) { _Lagain: while (_yychar && std::isspace(_yychar)) { if (_yychar == '\n') { tok->f.joined = false; tok->f.newline = true; } else { tok->f.whitespace = true; } yyinp(); } tok->lineno = _currentLine; _tokenStart = _currentChar; tok->offset = _currentChar - _firstChar; if (_state == State_MultiLineComment || _state == State_MultiLineDoxyComment) { const int originalState = _state; if (! _yychar) { tok->f.kind = T_EOF_SYMBOL; return; } while (_yychar) { if (_yychar != '*') yyinp(); else { yyinp(); if (_yychar == '/') { yyinp(); _state = State_Default; break; } } } if (! f._scanCommentTokens) goto _Lagain; else if (originalState == State_MultiLineComment) tok->f.kind = T_COMMENT; else tok->f.kind = T_DOXY_COMMENT; return; // done } if (! _yychar) { tok->f.kind = T_EOF_SYMBOL; return; } unsigned char ch = _yychar; yyinp(); switch (ch) { case '\\': while (_yychar != '\n' && std::isspace(_yychar)) yyinp(); // ### assert(! _yychar || _yychar == '\n'); if (_yychar == '\n') { tok->f.joined = true; tok->f.newline = false; yyinp(); } goto _Lagain; case '"': case '\'': { const char quote = ch; tok->f.kind = quote == '"' ? T_STRING_LITERAL : T_CHAR_LITERAL; while (_yychar && _yychar != quote) { if (_yychar == '\n') break; else if (_yychar != '\\') yyinp(); else { yyinp(); // skip `\\' if (_yychar) yyinp(); } } // assert(_yychar == quote); if (_yychar == quote) yyinp(); } break; case '{': tok->f.kind = T_LBRACE; break; case '}': tok->f.kind = T_RBRACE; break; case '[': tok->f.kind = T_LBRACKET; break; case ']': tok->f.kind = T_RBRACKET; break; case '#': if (_yychar == '#') { tok->f.kind = T_POUND_POUND; yyinp(); } else { tok->f.kind = T_POUND; } break; case '(': tok->f.kind = T_LPAREN; break; case ')': tok->f.kind = T_RPAREN; break; case ';': tok->f.kind = T_SEMICOLON; break; case ':': if (_yychar == ':') { yyinp(); tok->f.kind = T_COLON_COLON; } else { tok->f.kind = T_COLON; } break; case '.': if (_yychar == '*') { yyinp(); tok->f.kind = T_DOT_STAR; } else if (_yychar == '.') { yyinp(); // ### assert(_yychar); if (_yychar == '.') { yyinp(); tok->f.kind = T_DOT_DOT_DOT; } else { tok->f.kind = T_ERROR; } } else if (std::isdigit(_yychar)) { do { if (_yychar == 'e' || _yychar == 'E') { yyinp(); if (_yychar == '-' || _yychar == '+') { yyinp(); // ### assert(std::isdigit(_yychar)); } } else if (std::isalnum(_yychar) || _yychar == '.') { yyinp(); } else { break; } } while (_yychar); tok->f.kind = T_NUMERIC_LITERAL; } else { tok->f.kind = T_DOT; } break; case '?': tok->f.kind = T_QUESTION; break; case '+': if (_yychar == '+') { yyinp(); tok->f.kind = T_PLUS_PLUS; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_PLUS_EQUAL; } else { tok->f.kind = T_PLUS; } break; case '-': if (_yychar == '-') { yyinp(); tok->f.kind = T_MINUS_MINUS; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_MINUS_EQUAL; } else if (_yychar == '>') { yyinp(); if (_yychar == '*') { yyinp(); tok->f.kind = T_ARROW_STAR; } else { tok->f.kind = T_ARROW; } } else { tok->f.kind = T_MINUS; } break; case '*': if (_yychar == '=') { yyinp(); tok->f.kind = T_STAR_EQUAL; } else { tok->f.kind = T_STAR; } break; case '/': if (_yychar == '/') { yyinp(); bool doxy = false; if (_yychar == '/' || _yychar == '!') { yyinp(); if (_yychar == '<') yyinp(); if (_yychar != '\n' && std::isspace(_yychar)) doxy = true; } while (_yychar && _yychar != '\n') yyinp(); if (! f._scanCommentTokens) goto _Lagain; tok->f.kind = doxy ? T_CPP_DOXY_COMMENT : T_CPP_COMMENT; } else if (_yychar == '*') { yyinp(); bool doxy = false; if (_yychar == '*' || _yychar == '!') { const char ch = _yychar; yyinp(); if (ch == '*' && _yychar == '/') goto _Ldone; if (_yychar == '<') yyinp(); if (! _yychar || std::isspace(_yychar)) doxy = true; } while (_yychar) { if (_yychar != '*') { yyinp(); } else { yyinp(); if (_yychar == '/') break; } } _Ldone: if (_yychar) yyinp(); else _state = doxy ? State_MultiLineDoxyComment : State_MultiLineComment; if (! f._scanCommentTokens) goto _Lagain; tok->f.kind = doxy ? T_DOXY_COMMENT : T_COMMENT; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_SLASH_EQUAL; } else { tok->f.kind = T_SLASH; } break; case '%': if (_yychar == '=') { yyinp(); tok->f.kind = T_PERCENT_EQUAL; } else { tok->f.kind = T_PERCENT; } break; case '^': if (_yychar == '=') { yyinp(); tok->f.kind = T_CARET_EQUAL; } else { tok->f.kind = T_CARET; } break; case '&': if (_yychar == '&') { yyinp(); tok->f.kind = T_AMPER_AMPER; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_AMPER_EQUAL; } else { tok->f.kind = T_AMPER; } break; case '|': if (_yychar == '|') { yyinp(); tok->f.kind = T_PIPE_PIPE; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_PIPE_EQUAL; } else { tok->f.kind = T_PIPE; } break; case '~': if (_yychar == '=') { yyinp(); tok->f.kind = T_TILDE_EQUAL; } else { tok->f.kind = T_TILDE; } break; case '!': if (_yychar == '=') { yyinp(); tok->f.kind = T_EXCLAIM_EQUAL; } else { tok->f.kind = T_EXCLAIM; } break; case '=': if (_yychar == '=') { yyinp(); tok->f.kind = T_EQUAL_EQUAL; } else { tok->f.kind = T_EQUAL; } break; case '<': if (f._scanAngleStringLiteralTokens) { //const char *yytext = _currentChar; while (_yychar && _yychar != '>') yyinp(); //int yylen = _currentChar - yytext; // ### assert(_yychar == '>'); if (_yychar == '>') yyinp(); tok->f.kind = T_ANGLE_STRING_LITERAL; } else if (_yychar == '<') { yyinp(); if (_yychar == '=') { yyinp(); tok->f.kind = T_LESS_LESS_EQUAL; } else tok->f.kind = T_LESS_LESS; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_LESS_EQUAL; } else { tok->f.kind = T_LESS; } break; case '>': if (_yychar == '>') { yyinp(); if (_yychar == '=') { yyinp(); tok->f.kind = T_GREATER_GREATER_EQUAL; } else tok->f.kind = T_LESS_LESS; tok->f.kind = T_GREATER_GREATER; } else if (_yychar == '=') { yyinp(); tok->f.kind = T_GREATER_EQUAL; } else { tok->f.kind = T_GREATER; } break; case ',': tok->f.kind = T_COMMA; break; default: { if (f._objCEnabled) { if (ch == '@' && _yychar >= 'a' && _yychar <= 'z') { //const char *yytext = _currentChar; do { yyinp(); if (! (isalnum(_yychar) || _yychar == '_' || _yychar == '$')) break; } while (_yychar); // const int yylen = _currentChar - yytext; //tok->f.kind = classifyObjCAtKeyword(yytext, yylen); /// ### FIXME break; } else if (ch == '@' && _yychar == '"') { // objc @string literals ch = _yychar; yyinp(); tok->f.kind = T_AT_STRING_LITERAL; //const char *yytext = _currentChar; while (_yychar && _yychar != '"') { if (_yychar != '\\') yyinp(); else { yyinp(); // skip `\\' if (_yychar) yyinp(); } } // assert(_yychar == '"'); //int yylen = _currentChar - yytext; if (_yychar == '"') yyinp(); break; } } if (ch == 'L' && (_yychar == '"' || _yychar == '\'')) { // wide char/string literals ch = _yychar; yyinp(); const char quote = ch; tok->f.kind = quote == '"' ? T_WIDE_STRING_LITERAL : T_WIDE_CHAR_LITERAL; //const char *yytext = _currentChar; while (_yychar && _yychar != quote) { if (_yychar != '\\') yyinp(); else { yyinp(); // skip `\\' if (_yychar) yyinp(); } } // assert(_yychar == quote); //int yylen = _currentChar - yytext; if (_yychar == quote) yyinp(); } else if (std::isalpha(ch) || ch == '_' || ch == '$') { //const char *yytext = _currentChar - 1; while (std::isalnum(_yychar) || _yychar == '_' || _yychar == '$') yyinp(); //int yylen = _currentChar - yytext; tok->f.kind = T_IDENTIFIER; break; } else if (std::isdigit(ch)) { //const char *yytext = _currentChar - 1; while (_yychar) { if (_yychar == 'e' || _yychar == 'E') { yyinp(); if (_yychar == '-' || _yychar == '+') { yyinp(); // ### assert(std::isdigit(_yychar)); } } else if (std::isalnum(_yychar) || _yychar == '.') { yyinp(); } else { break; } } //int yylen = _currentChar - yytext; tok->f.kind = T_NUMERIC_LITERAL; break; } else { tok->f.kind = T_ERROR; break; } } // default } // switch } qbs-src-1.4.5/src/plugins/scanner/cpp/Lexer.h000066400000000000000000000117501266132464200210200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ // Copyright (c) 2008 Roberto Raggi // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #ifndef CPLUSPLUS_LEXER_H #define CPLUSPLUS_LEXER_H #include "CPlusPlusForwardDeclarations.h" #include "Token.h" namespace CPlusPlus { class CPLUSPLUS_EXPORT Lexer { Lexer(const Lexer &other); void operator =(const Lexer &other); public: enum State { State_Default, State_MultiLineComment, State_MultiLineDoxyComment }; Lexer(const char *firstChar, const char *lastChar); ~Lexer(); bool qtMocRunEnabled() const; void setQtMocRunEnabled(bool onoff); bool cxx0xEnabled() const; void setCxxOxEnabled(bool onoff); bool objCEnabled() const; void setObjCEnabled(bool onoff); void scan(Token *tok); inline void operator()(Token *tok) { scan(tok); } unsigned tokenOffset() const; unsigned tokenLength() const; const char *tokenBegin() const; const char *tokenEnd() const; unsigned currentLine() const; bool scanCommentTokens() const; void setScanCommentTokens(bool onoff); bool scanAngleStringLiteralTokens() const; void setScanAngleStringLiteralTokens(bool onoff); void setStartWithNewline(bool enabled); int state() const; void setState(int state); bool isIncremental() const; void setIncremental(bool isIncremental); private: void scan_helper(Token *tok); void setSource(const char *firstChar, const char *lastChar); static int classify(const char *string, int length, bool q, bool cxx0x); static int classifyObjCAtKeyword(const char *s, int n); static int classifyOperator(const char *string, int length); inline void yyinp() { if (++_currentChar == _lastChar) _yychar = 0; else { _yychar = *_currentChar; if (_yychar == '\n') pushLineStartOffset(); } } void pushLineStartOffset(); private: struct Flags { unsigned _isIncremental: 1; unsigned _scanCommentTokens: 1; unsigned _scanAngleStringLiteralTokens: 1; unsigned _qtMocRunEnabled: 1; unsigned _cxx0xEnabled: 1; unsigned _objCEnabled: 1; }; const char *_firstChar; const char *_currentChar; const char *_lastChar; const char *_tokenStart; unsigned char _yychar; int _state; union { unsigned _flags; Flags f; }; unsigned _currentLine; }; } // end of namespace CPlusPlus #endif // CPLUSPLUS_LEXER_H qbs-src-1.4.5/src/plugins/scanner/cpp/Token.cpp000066400000000000000000000131711266132464200213530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ // Copyright (c) 2008 Roberto Raggi // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #include "Token.h" #ifndef CPLUSPLUS_NO_PARSER # include "Literals.h" #endif using namespace CPlusPlus; static const char *token_names[] = { (""), (""), (""), (""), (""), (""), (""), (""), (""), (""), (""), (""), ("<@string literal>"), (""), ("&"), ("&&"), ("&="), ("->"), ("->*"), ("^"), ("^="), (":"), ("::"), (","), ("/"), ("/="), ("."), ("..."), (".*"), ("="), ("=="), ("!"), ("!="), (">"), (">="), (">>"), (">>="), ("{"), ("["), ("<"), ("<="), ("<<"), ("<<="), ("("), ("-"), ("-="), ("--"), ("%"), ("%="), ("|"), ("|="), ("||"), ("+"), ("+="), ("++"), ("#"), ("##"), ("?"), ("}"), ("]"), (")"), (";"), ("*"), ("*="), ("~"), ("~="), ("asm"), ("auto"), ("bool"), ("break"), ("case"), ("catch"), ("char"), ("class"), ("const"), ("const_cast"), ("continue"), ("default"), ("delete"), ("do"), ("double"), ("dynamic_cast"), ("else"), ("enum"), ("explicit"), ("export"), ("extern"), ("false"), ("float"), ("for"), ("friend"), ("goto"), ("if"), ("inline"), ("int"), ("long"), ("mutable"), ("namespace"), ("new"), ("operator"), ("private"), ("protected"), ("public"), ("register"), ("reinterpret_cast"), ("return"), ("short"), ("signed"), ("sizeof"), ("static"), ("static_cast"), ("struct"), ("switch"), ("template"), ("this"), ("throw"), ("true"), ("try"), ("typedef"), ("typeid"), ("typename"), ("union"), ("unsigned"), ("using"), ("virtual"), ("void"), ("volatile"), ("wchar_t"), ("while"), // gnu ("__attribute__"), ("__typeof__"), // objc @keywords ("@catch"), ("@class"), ("@compatibility_alias"), ("@defs"), ("@dynamic"), ("@encode"), ("@end"), ("@finally"), ("@implementation"), ("@interface"), ("@not_keyword"), ("@optional"), ("@package"), ("@private"), ("@property"), ("@protected"), ("@protocol"), ("@public"), ("@required"), ("@selector"), ("@synchronized"), ("@synthesize"), ("@throw"), ("@try"), // Qt keywords ("SIGNAL"), ("SLOT"), ("Q_SIGNAL"), ("Q_SLOT"), ("signals"), ("slots"), ("Q_FOREACH"), ("Q_D"), ("Q_Q"), ("Q_INVOKABLE"), ("Q_PROPERTY"), ("Q_INTERFACES"), ("Q_ENUMS"), ("Q_FLAGS"), ("Q_PRIVATE_SLOT"), ("Q_DECLARE_INTERFACE"), ("Q_OBJECT"), ("Q_GADGET"), }; Token::Token() : flags(0), offset(0), ptr(0) { } Token::~Token() { } void Token::reset() { flags = 0; offset = 0; ptr = 0; } const char *Token::name(int kind) { return token_names[kind]; } #ifndef CPLUSPLUS_NO_PARSER const char *Token::spell() const { switch (f.kind) { case T_IDENTIFIER: return identifier->chars(); case T_NUMERIC_LITERAL: case T_CHAR_LITERAL: case T_STRING_LITERAL: case T_AT_STRING_LITERAL: case T_ANGLE_STRING_LITERAL: case T_WIDE_CHAR_LITERAL: case T_WIDE_STRING_LITERAL: return literal->chars(); default: return token_names[f.kind]; } // switch } #endif qbs-src-1.4.5/src/plugins/scanner/cpp/Token.h000066400000000000000000000212061266132464200210160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ // Copyright (c) 2008 Roberto Raggi // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #ifndef CPLUSPLUS_TOKEN_H #define CPLUSPLUS_TOKEN_H #include "CPlusPlusForwardDeclarations.h" namespace CPlusPlus { enum Kind { T_EOF_SYMBOL = 0, T_ERROR, T_CPP_COMMENT, T_CPP_DOXY_COMMENT, T_COMMENT, T_DOXY_COMMENT, T_IDENTIFIER, T_FIRST_LITERAL, T_NUMERIC_LITERAL = T_FIRST_LITERAL, T_CHAR_LITERAL, T_WIDE_CHAR_LITERAL, T_STRING_LITERAL, T_WIDE_STRING_LITERAL, T_AT_STRING_LITERAL, T_ANGLE_STRING_LITERAL, T_LAST_LITERAL = T_ANGLE_STRING_LITERAL, T_FIRST_OPERATOR, T_AMPER = T_FIRST_OPERATOR, T_AMPER_AMPER, T_AMPER_EQUAL, T_ARROW, T_ARROW_STAR, T_CARET, T_CARET_EQUAL, T_COLON, T_COLON_COLON, T_COMMA, T_SLASH, T_SLASH_EQUAL, T_DOT, T_DOT_DOT_DOT, T_DOT_STAR, T_EQUAL, T_EQUAL_EQUAL, T_EXCLAIM, T_EXCLAIM_EQUAL, T_GREATER, T_GREATER_EQUAL, T_GREATER_GREATER, T_GREATER_GREATER_EQUAL, T_LBRACE, T_LBRACKET, T_LESS, T_LESS_EQUAL, T_LESS_LESS, T_LESS_LESS_EQUAL, T_LPAREN, T_MINUS, T_MINUS_EQUAL, T_MINUS_MINUS, T_PERCENT, T_PERCENT_EQUAL, T_PIPE, T_PIPE_EQUAL, T_PIPE_PIPE, T_PLUS, T_PLUS_EQUAL, T_PLUS_PLUS, T_POUND, T_POUND_POUND, T_QUESTION, T_RBRACE, T_RBRACKET, T_RPAREN, T_SEMICOLON, T_STAR, T_STAR_EQUAL, T_TILDE, T_TILDE_EQUAL, T_LAST_OPERATOR = T_TILDE_EQUAL, T_FIRST_KEYWORD, T_ASM = T_FIRST_KEYWORD, T_AUTO, T_BOOL, T_BREAK, T_CASE, T_CATCH, T_CHAR, T_CLASS, T_CONST, T_CONST_CAST, T_CONTINUE, T_DEFAULT, T_DELETE, T_DO, T_DOUBLE, T_DYNAMIC_CAST, T_ELSE, T_ENUM, T_EXPLICIT, T_EXPORT, T_EXTERN, T_FALSE, T_FLOAT, T_FOR, T_FRIEND, T_GOTO, T_IF, T_INLINE, T_INT, T_LONG, T_MUTABLE, T_NAMESPACE, T_NEW, T_OPERATOR, T_PRIVATE, T_PROTECTED, T_PUBLIC, T_REGISTER, T_REINTERPRET_CAST, T_RETURN, T_SHORT, T_SIGNED, T_SIZEOF, T_STATIC, T_STATIC_CAST, T_STRUCT, T_SWITCH, T_TEMPLATE, T_THIS, T_THROW, T_TRUE, T_TRY, T_TYPEDEF, T_TYPEID, T_TYPENAME, T_UNION, T_UNSIGNED, T_USING, T_VIRTUAL, T_VOID, T_VOLATILE, T_WCHAR_T, T_WHILE, T___ATTRIBUTE__, T___TYPEOF__, // obj c++ @ keywords T_FIRST_OBJC_AT_KEYWORD, T_AT_CATCH = T_FIRST_OBJC_AT_KEYWORD, T_AT_CLASS, T_AT_COMPATIBILITY_ALIAS, T_AT_DEFS, T_AT_DYNAMIC, T_AT_ENCODE, T_AT_END, T_AT_FINALLY, T_AT_IMPLEMENTATION, T_AT_INTERFACE, T_AT_NOT_KEYWORD, T_AT_OPTIONAL, T_AT_PACKAGE, T_AT_PRIVATE, T_AT_PROPERTY, T_AT_PROTECTED, T_AT_PROTOCOL, T_AT_PUBLIC, T_AT_REQUIRED, T_AT_SELECTOR, T_AT_SYNCHRONIZED, T_AT_SYNTHESIZE, T_AT_THROW, T_AT_TRY, T_LAST_OBJC_AT_KEYWORD = T_AT_TRY, T_FIRST_QT_KEYWORD, // Qt keywords T_SIGNAL = T_FIRST_QT_KEYWORD, T_SLOT, T_Q_SIGNAL, T_Q_SLOT, T_Q_SIGNALS, T_Q_SLOTS, T_Q_FOREACH, T_Q_D, T_Q_Q, T_Q_INVOKABLE, T_Q_PROPERTY, T_Q_INTERFACES, T_Q_ENUMS, T_Q_FLAGS, T_Q_PRIVATE_SLOT, T_Q_DECLARE_INTERFACE, T_Q_OBJECT, T_Q_GADGET, T_LAST_KEYWORD = T_Q_GADGET, // aliases T_OR = T_PIPE_PIPE, T_AND = T_AMPER_AMPER, T_NOT = T_EXCLAIM, T_XOR = T_CARET, T_BITOR = T_PIPE, T_COMPL = T_TILDE, T_OR_EQ = T_PIPE_EQUAL, T_AND_EQ = T_AMPER_EQUAL, T_BITAND = T_AMPER, T_NOT_EQ = T_EXCLAIM_EQUAL, T_XOR_EQ = T_CARET_EQUAL, T___ASM = T_ASM, T___ASM__ = T_ASM, T_TYPEOF = T___TYPEOF__, T___TYPEOF = T___TYPEOF__, T___INLINE = T_INLINE, T___INLINE__ = T_INLINE, T___CONST = T_CONST, T___CONST__ = T_CONST, T___VOLATILE = T_VOLATILE, T___VOLATILE__ = T_VOLATILE, T___ATTRIBUTE = T___ATTRIBUTE__ }; class CPLUSPLUS_EXPORT Token { public: Token(); ~Token(); inline bool is(unsigned k) const { return f.kind == k; } inline bool isNot(unsigned k) const { return f.kind != k; } #ifndef CPLUSPLUS_NO_PARSER const char *spell() const; #endif void reset(); inline unsigned kind() const { return f.kind; } inline bool newline() const { return f.newline; } inline bool whitespace() const { return f.whitespace; } inline bool joined() const { return f.joined; } inline bool expanded() const { return f.expanded; } inline bool generated() const { return f.generated; } inline unsigned length() const { return f.length; } inline unsigned begin() const { return offset; } inline unsigned end() const { return offset + f.length; } inline bool isLiteral() const { return f.kind >= T_FIRST_LITERAL && f.kind <= T_LAST_LITERAL; } inline bool isOperator() const { return f.kind >= T_FIRST_OPERATOR && f.kind <= T_LAST_OPERATOR; } inline bool isKeyword() const { return f.kind >= T_FIRST_KEYWORD && f.kind < T_FIRST_QT_KEYWORD; } inline bool isComment() const { return f.kind == T_COMMENT || f.kind == T_DOXY_COMMENT || f.kind == T_CPP_COMMENT || f.kind == T_CPP_DOXY_COMMENT; } inline bool isObjCAtKeyword() const { return f.kind >= T_FIRST_OBJC_AT_KEYWORD && f.kind <= T_LAST_OBJC_AT_KEYWORD; } static const char *name(int kind); public: struct Flags { unsigned kind : 8; unsigned newline : 1; unsigned whitespace : 1; unsigned joined : 1; unsigned expanded : 1; unsigned generated : 1; unsigned pad : 3; unsigned length : 16; }; union { unsigned flags; Flags f; }; unsigned offset; union { void *ptr; #ifndef CPLUSPLUS_NO_PARSER const Literal *literal; const NumericLiteral *number; const StringLiteral *string; const Identifier *identifier; #endif unsigned close_brace; unsigned lineno; }; }; } // end of namespace CPlusPlus #endif // CPLUSPLUS_TOKEN_H qbs-src-1.4.5/src/plugins/scanner/cpp/cpp.pro000066400000000000000000000003651266132464200210740ustar00rootroot00000000000000include(../../plugins.pri) DEFINES += CPLUSPLUS_NO_PARSER TARGET = qbs_cpp_scanner QT = core HEADERS += CPlusPlusForwardDeclarations.h Lexer.h Token.h ../scanner.h \ cpp_global.h SOURCES += Lexer.cpp Token.cpp \ cppscanner.cpp qbs-src-1.4.5/src/plugins/scanner/cpp/cpp.qbs000066400000000000000000000005551266132464200210620ustar00rootroot00000000000000import qbs 1.0 import "../scannerplugin.qbs" as ScannerPlugin ScannerPlugin { cpp.defines: ["CPLUSPLUS_NO_PARSER"] name: "qbs_cpp_scanner" files: [ "../scanner.h", "CPlusPlusForwardDeclarations.h", "Lexer.cpp", "Lexer.h", "Token.cpp", "Token.h", "cpp_global.h", "cppscanner.cpp" ] } qbs-src-1.4.5/src/plugins/scanner/cpp/cpp_global.h000066400000000000000000000032661266132464200220460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef CPP_GLOBAL_H #define CPP_GLOBAL_H #if defined(WIN32) || defined(_WIN32) #define CPPSCANNER_EXPORT __declspec(dllexport) #else #define CPPSCANNER_EXPORT #endif #endif // CPP_GLOBAL_H qbs-src-1.4.5/src/plugins/scanner/cpp/cppscanner.cpp000066400000000000000000000232341266132464200224300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "../scanner.h" #include "cpp_global.h" #include "Lexer.h" using namespace CPlusPlus; #ifdef Q_OS_UNIX #include #include #include #include #include #else #include #endif #include #include #include #include #include struct ScanResult { char *fileName; unsigned int size; int flags; }; struct Opaq { enum FileType { FT_UNKNOWN, FT_HPP, FT_CPP, FT_C, FT_OBJC, FT_OBJCPP, FT_RC }; Opaq() : #ifdef Q_OS_UNIX fd(0), mapl(0), #endif fileContent(0), fileType(FT_UNKNOWN), hasQObjectMacro(false), hasPluginMetaDataMacro(false), currentResultIndex(0) {} ~Opaq() { #ifdef Q_OS_UNIX if (fileContent) munmap(fileContent, mapl); if (fd) close(fd); #endif } #ifdef Q_OS_WIN QFile file; #endif #ifdef Q_OS_UNIX int fd; size_t mapl; #endif QString fileName; char *fileContent; FileType fileType; QList includedFiles; bool hasQObjectMacro; bool hasPluginMetaDataMacro; int currentResultIndex; }; class TokenComparator { const char * const m_fileContent; public: TokenComparator(const char *fileContent) : m_fileContent(fileContent) { } bool equals(const Token &tk, const QLatin1Literal &literal) const { return static_cast(tk.length()) == literal.size() && memcmp(m_fileContent + tk.begin(), literal.data(), literal.size()) == 0; } }; static void scanCppFile(void *opaq, Lexer &yylex, bool scanForFileTags, bool scanForDependencies) { const QLatin1Literal includeLiteral("include"); const QLatin1Literal importLiteral("import"); const QLatin1Literal defineLiteral("define"); const QLatin1Literal qobjectLiteral("Q_OBJECT"); const QLatin1Literal qgadgetLiteral("Q_GADGET"); const QLatin1Literal pluginMetaDataLiteral("Q_PLUGIN_METADATA"); Opaq *opaque = static_cast(opaq); const TokenComparator tc(opaque->fileContent); Token tk; Token oldTk; ScanResult scanResult; yylex(&tk); while (tk.isNot(T_EOF_SYMBOL)) { if (tk.newline() && tk.is(T_POUND)) { yylex(&tk); if (scanForDependencies && !tk.newline() && tk.is(T_IDENTIFIER)) { if (tc.equals(tk, includeLiteral) || tc.equals(tk, importLiteral)) { yylex.setScanAngleStringLiteralTokens(true); yylex(&tk); yylex.setScanAngleStringLiteralTokens(false); if (!tk.newline() && (tk.is(T_STRING_LITERAL) || tk.is(T_ANGLE_STRING_LITERAL))) { scanResult.size = tk.length() - 2; if (tk.is(T_STRING_LITERAL)) scanResult.flags = SC_LOCAL_INCLUDE_FLAG; else scanResult.flags = SC_GLOBAL_INCLUDE_FLAG; scanResult.fileName = opaque->fileContent + tk.begin() + 1; opaque->includedFiles.append(scanResult); } } } } else if (tk.is(T_IDENTIFIER)) { if (scanForFileTags) { if (oldTk.is(T_IDENTIFIER) && tc.equals(oldTk, defineLiteral)) { // Someone was clever and redefined Q_OBJECT or Q_PLUGIN_METADATA. // Example: iplugin.h in Qt Creator. } else { if (tc.equals(tk, qobjectLiteral) || tc.equals(tk, qgadgetLiteral)) { opaque->hasQObjectMacro = true; } else if (opaque->fileType == Opaq::FT_HPP && tc.equals(tk, pluginMetaDataLiteral)) { opaque->hasPluginMetaDataMacro = true; } if (!scanForDependencies && opaque->hasQObjectMacro && (opaque->fileType == Opaq::FT_CPP || opaque->hasPluginMetaDataMacro)) break; } } } oldTk = tk; yylex(&tk); } } static Opaq *openScanner(const unsigned short *filePath, Opaq::FileType fileType, int flags) { QScopedPointer opaque(new Opaq); opaque->fileName = QString::fromUtf16(filePath); opaque->fileType = fileType; size_t mapl = 0; #ifdef Q_OS_UNIX QString filePathS = opaque->fileName; opaque->fd = open(qPrintable(filePathS), O_RDONLY); if (opaque->fd == -1) { opaque->fd = 0; return 0; } struct stat s; int r = fstat(opaque->fd, &s); if (r != 0) return 0; mapl = s.st_size; opaque->mapl = mapl; void *vmap = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, opaque->fd, 0); if (vmap == MAP_FAILED) return 0; #else opaque->file.setFileName(opaque->fileName); if (!opaque->file.open(QFile::ReadOnly)) return 0; uchar *vmap = opaque->file.map(0, opaque->file.size()); mapl = opaque->file.size(); #endif if (!vmap) return 0; opaque->fileContent = reinterpret_cast(vmap); Lexer lex(opaque->fileContent, opaque->fileContent + mapl); scanCppFile(opaque.data(), lex, flags & ScanForFileTagsFlag, flags & ScanForDependenciesFlag); return opaque.take(); } template static void *openScannerT(const unsigned short *filePath, int flags) { return openScanner(filePath, t, flags); } static void closeScanner(void *ptr) { Opaq *opaque = static_cast(ptr); delete opaque; } static const char *next(void *opaq, int *size, int *flags) { Opaq *opaque = static_cast(opaq); if (opaque->currentResultIndex < opaque->includedFiles.count()) { const ScanResult &result = opaque->includedFiles.at(opaque->currentResultIndex); ++opaque->currentResultIndex; *size = result.size; *flags = result.flags; return result.fileName; } *size = 0; *flags = 0; return 0; } static const char **additionalFileTags(void *opaq, int *size) { static const char *thMocCpp[] = { "moc_cpp" }; static const char *thMocHpp[] = { "moc_hpp" }; static const char *thMocPluginHpp[] = { "moc_hpp_plugin" }; Opaq *opaque = static_cast(opaq); if (opaque->hasQObjectMacro) { *size = 1; switch (opaque->fileType) { case Opaq::FT_CPP: return thMocCpp; case Opaq::FT_HPP: return opaque->hasPluginMetaDataMacro ? thMocPluginHpp : thMocHpp; default: break; } } *size = 0; return 0; } extern "C" { ScannerPlugin hppScanner = { "include_scanner", "hpp", openScannerT, closeScanner, next, additionalFileTags, ScannerUsesCppIncludePaths | ScannerRecursiveDependencies }; ScannerPlugin cppScanner = { "include_scanner", "cpp", openScannerT, closeScanner, next, additionalFileTags, ScannerUsesCppIncludePaths | ScannerRecursiveDependencies }; ScannerPlugin cScanner = { "include_scanner", "c", openScannerT, closeScanner, next, 0, ScannerUsesCppIncludePaths | ScannerRecursiveDependencies }; ScannerPlugin objcppScanner = { "include_scanner", "objcpp", openScannerT, closeScanner, next, additionalFileTags, ScannerUsesCppIncludePaths | ScannerRecursiveDependencies }; ScannerPlugin objcScanner = { "include_scanner", "objc", openScannerT, closeScanner, next, additionalFileTags, ScannerUsesCppIncludePaths | ScannerRecursiveDependencies }; ScannerPlugin rcScanner = { "include_scanner", "rc", openScannerT, closeScanner, next, 0, ScannerUsesCppIncludePaths | ScannerRecursiveDependencies }; ScannerPlugin *theScanners[] = {&hppScanner, &cppScanner, &cScanner, &objcppScanner, &objcScanner, &rcScanner, NULL}; CPPSCANNER_EXPORT ScannerPlugin **getScanners() { return theScanners; } } // extern "C" qbs-src-1.4.5/src/plugins/scanner/qt/000077500000000000000000000000001266132464200174265ustar00rootroot00000000000000qbs-src-1.4.5/src/plugins/scanner/qt/qt.pro000066400000000000000000000001671266132464200206000ustar00rootroot00000000000000include(../../plugins.pri) TARGET = qbs_qt_scanner QT = core HEADERS += ../scanner.h SOURCES += \ qtscanner.cpp qbs-src-1.4.5/src/plugins/scanner/qt/qt.qbs000066400000000000000000000002601266132464200205570ustar00rootroot00000000000000import qbs 1.0 import "../scannerplugin.qbs" as ScannerPlugin ScannerPlugin { name: "qbs_qt_scanner" files: [ "../scanner.h", "qtscanner.cpp" ] } qbs-src-1.4.5/src/plugins/scanner/qt/qtscanner.cpp000066400000000000000000000110021266132464200221220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #if defined(WIN32) || defined(_WIN32) #define SCANNER_EXPORT __declspec(dllexport) #else #define SCANNER_EXPORT #endif #include "../scanner.h" #include #ifdef Q_OS_UNIX #include #include #include #include #include #else #include #endif #include #include #include struct Opaq { #ifdef Q_OS_UNIX int fd; int mapl; #else QFile *file; #endif char *map; QXmlStreamReader *xml; QByteArray current; Opaq() #ifdef Q_OS_UNIX : fd (0), #else : file(0), #endif map(0), xml(0) {} ~Opaq() { #ifdef Q_OS_UNIX if (map) munmap (map, mapl); if (fd) close (fd); #else delete file; #endif delete xml; } }; static void *openScanner(const unsigned short *filePath, int flags) { Q_UNUSED(flags); QScopedPointer opaque(new Opaq); #ifdef Q_OS_UNIX QString filePathS = QString::fromUtf16(filePath); opaque->fd = open(qPrintable(filePathS), O_RDONLY); if (opaque->fd == -1) { opaque->fd = 0; return 0; } struct stat s; int r = fstat(opaque->fd, &s); if (r != 0) return 0; opaque->mapl = s.st_size; void *map = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, opaque->fd, 0); if (map == 0) return 0; #else opaque->file = new QFile(QString::fromUtf16(filePath)); if (!opaque->file->open(QFile::ReadOnly)) return 0; uchar *map = opaque->file->map(0, opaque->file->size()); if (!map) return 0; #endif opaque->map = reinterpret_cast(map); opaque->xml = new QXmlStreamReader(opaque->map); return static_cast(opaque.take()); } static void closeScanner(void *ptr) { Opaq *opaque = static_cast(ptr); delete opaque; } static const char *nextQrc(void *opaq, int *size, int *flags) { Opaq *o= static_cast(opaq); while (!o->xml->atEnd()) { o->xml->readNext(); switch (o->xml->tokenType()) { case QXmlStreamReader::StartElement: if (o->xml->name() == QLatin1String("file")) { o->current = o->xml->readElementText(QXmlStreamReader::ErrorOnUnexpectedElement).toUtf8(); *flags = SC_LOCAL_INCLUDE_FLAG; *size = o->current.size(); return o->current.data(); } break; case QXmlStreamReader::EndDocument: return 0; default: break; } } return 0; } static const char **additionalFileTags(void *, int *size) { *size = 0; return 0; } extern "C" { ScannerPlugin qrcScanner = { "qt_qrc_scanner", "qrc", openScanner, closeScanner, nextQrc, additionalFileTags, NoScannerFlags }; ScannerPlugin *theScanners[] = {&qrcScanner, NULL}; SCANNER_EXPORT ScannerPlugin **getScanners() { return theScanners; } } // extern "C" qbs-src-1.4.5/src/plugins/scanner/scanner.h000066400000000000000000000055611266132464200206130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef SCANNER_H #define SCANNER_H #ifdef __cplusplus extern "C" { #endif #define SC_LOCAL_INCLUDE_FLAG 0x1 #define SC_GLOBAL_INCLUDE_FLAG 0x2 enum OpenScannerFlags { ScanForDependenciesFlag = 0x01, ScanForFileTagsFlag = 0x02 }; /** * Open a file that's going to be scanned. * The file path encoding is UTF-16 on all platforms. * * Returns a scanner handle. */ typedef void *(*scanOpen_f) (const unsigned short *filePath, int flags); /** * Closes the given scanner handle. */ typedef void (*scanClose_f) (void *opaq); /** * Return the next result (filename) of the scan. */ typedef const char *(*scanNext_f) (void *opaq, int *size, int *flags); /** * Returns a list of type hints for the scanned file. * May return null. * * Example: if a C++ header file contains Q_OBJECT, * the type hint 'moc_hpp' is returned. */ typedef const char** (*scanAdditionalFileTags_f) (void *opaq, int *size); enum ScannerFlags { NoScannerFlags = 0x00, ScannerUsesCppIncludePaths = 0x01, ScannerRecursiveDependencies = 0x02 }; class ScannerPlugin { public: const char *name; const char *fileTag; scanOpen_f open; scanClose_f close; scanNext_f next; scanAdditionalFileTags_f additionalFileTags; int flags; }; typedef ScannerPlugin **(*getScanners_f)(); #ifdef __cplusplus } #endif #endif // SCANNER_H qbs-src-1.4.5/src/plugins/scanner/scanner.pro000066400000000000000000000000451266132464200211540ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS = cpp qt qbs-src-1.4.5/src/plugins/scanner/scannerplugin.qbs000066400000000000000000000005221266132464200223600ustar00rootroot00000000000000import qbs 1.0 DynamicLibrary { Depends { name: "cpp" } Depends { name: "Qt.core" } destinationDirectory: project.libDirName + "/qbs/plugins" Group { fileTagsFilter: ["dynamiclibrary"] qbs.install: true qbs.installDir: project.pluginsInstallDir + "/qbs/plugins" } bundle.isBundle: false } qbs-src-1.4.5/src/src.qbs000066400000000000000000000002351266132464200151660ustar00rootroot00000000000000import qbs Project { references: [ "app/apps.qbs", "lib/libs.qbs", "libexec/libexec.qbs", "plugins/plugins.qbs" ] } qbs-src-1.4.5/static.pro000066400000000000000000000044071266132464200151170ustar00rootroot00000000000000TEMPLATE = app TARGET = phony_target CONFIG -= qt sdk separate_debug_info gdb_dwarf_index QT = LIBS = macx:CONFIG -= app_bundle isEmpty(vcproj) { QMAKE_LINK = @: IGNORE THIS LINE OBJECTS_DIR = win32:CONFIG -= embed_manifest_exe } else { CONFIG += console PHONY_DEPS = . phony_src.input = PHONY_DEPS phony_src.output = phony.c phony_src.variable_out = GENERATED_SOURCES phony_src.commands = echo int main() { return 0; } > phony.c phony_src.name = CREATE phony.c phony_src.CONFIG += combine QMAKE_EXTRA_COMPILERS += phony_src } DATA_DIRS = share/qbs/imports share/qbs/modules win32:DATA_FILES = $$PWD/bin/ibmsvc.xml $$PWD/bin/ibqbs.bat defineReplace(cleanPath) { win32:1 ~= s|\\\\|/|g contains(1, ^/.*):pfx = / else:pfx = segs = $$split(1, /) out = for(seg, segs) { equals(seg, ..):out = $$member(out, 0, -2) else:!equals(seg, .):out += $$seg } return($$join(out, /, $$pfx)) } # For use in custom compilers which just copy files defineReplace(stripSrcDir) { return($$relative_path($$absolute_path($$1, $$OUT_PWD), $$_PRO_FILE_PWD_)) } for(data_dir, DATA_DIRS) { files = $$files($$PWD/$$data_dir/*, true) win32:files ~= s|\\\\|/|g for(file, files):!exists($$file/*):FILES += $$file } FILES += $$DATA_FILES OTHER_FILES += $$FILES !isEqual(PWD, $$OUT_PWD)|!isEmpty(QBS_RESOURCES_BUILD_DIR) { copy2build.input = FILES !isEmpty(QBS_RESOURCES_BUILD_DIR): \ copy2build.output = $${QBS_RESOURCES_BUILD_DIR}/${QMAKE_FUNC_FILE_IN_stripSrcDir} else: \ copy2build.output = ${QMAKE_FUNC_FILE_IN_stripSrcDir} isEmpty(vcproj):copy2build.variable_out = PRE_TARGETDEPS win32:copy2build.commands = $$QMAKE_COPY \"${QMAKE_FILE_IN}\" \"${QMAKE_FILE_OUT}\" unix:copy2build.commands = $$QMAKE_COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT} copy2build.name = COPY ${QMAKE_FILE_IN} copy2build.CONFIG += no_link QMAKE_EXTRA_COMPILERS += copy2build } include(src/install_prefix.pri) share.files = share/qbs !isEmpty(QBS_RESOURCES_INSTALL_DIR): \ installPrefix = $${QBS_RESOURCES_INSTALL_DIR} else: \ installPrefix = $${QBS_INSTALL_PREFIX} share.path = $${installPrefix}/share examples.files = examples examples.path = $${share.path}/qbs INSTALLS += share examples qbs-src-1.4.5/tests/000077500000000000000000000000001266132464200142435ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/000077500000000000000000000000001266132464200152135ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/000077500000000000000000000000001266132464200157645ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/api.pro000066400000000000000000000015301266132464200172560ustar00rootroot00000000000000TARGET = tst_api HEADERS = tst_api.h SOURCES = tst_api.cpp include(../../../src/library_dirname.pri) isEmpty(QBS_RELATIVE_LIBEXEC_PATH):QBS_RELATIVE_LIBEXEC_PATH=../libexec/qbs isEmpty(QBS_RELATIVE_PLUGINS_PATH):QBS_RELATIVE_PLUGINS_PATH=../$${QBS_LIBRARY_DIRNAME} isEmpty(QBS_RELATIVE_SEARCH_PATH):QBS_RELATIVE_SEARCH_PATH=.. DEFINES += QBS_RELATIVE_LIBEXEC_PATH=\\\"$${QBS_RELATIVE_LIBEXEC_PATH}\\\" DEFINES += QBS_RELATIVE_PLUGINS_PATH=\\\"$${QBS_RELATIVE_PLUGINS_PATH}\\\" DEFINES += QBS_RELATIVE_SEARCH_PATH=\\\"$${QBS_RELATIVE_SEARCH_PATH}\\\" qbs_enable_project_file_updates:DEFINES += QBS_ENABLE_PROJECT_FILE_UPDATES include(../auto.pri) DATA_DIRS = testdata for(data_dir, DATA_DIRS) { files = $$files($$PWD/$$data_dir/*, true) win32:files ~= s|\\\\|/|g for(file, files):!exists($$file/*):FILES += $$file } OTHER_FILES += $$FILES qbs-src-1.4.5/tests/auto/api/api.qbs000066400000000000000000000011251266132464200172430ustar00rootroot00000000000000import qbs QbsAutotest { testName: "api" files: ["../shared.h", "tst_api.h", "tst_api.cpp"] cpp.defines: base.concat([ 'SRCDIR="' + path + '"', 'QBS_RELATIVE_LIBEXEC_PATH="' + project.relativeLibexecPath + '"', 'QBS_RELATIVE_SEARCH_PATH="' + project.relativeSearchPath + '"', 'QBS_RELATIVE_PLUGINS_PATH="' + project.relativePluginsPath + '"' ]).concat(project.enableProjectFileUpdates ? ["QBS_ENABLE_PROJECT_FILE_UPDATES"] : []) Group { name: "testdata" prefix: "testdata/" files: ["**/*"] fileTags: [] } } qbs-src-1.4.5/tests/auto/api/testdata/000077500000000000000000000000001266132464200175755ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/QBS-728/000077500000000000000000000000001266132464200205405ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/QBS-728/project.qbs000066400000000000000000000002721266132464200227160ustar00rootroot00000000000000import qbs Product { property bool isBlubbOS: qbs.targetOS.contains("blubb-OS") profiles: isBlubbOS ? ["blubb-profile"] : [project.profile] qbs.architecture: "blubb-arch" } qbs-src-1.4.5/tests/auto/api/testdata/add-qobject-macro-to-cpp-file/000077500000000000000000000000001266132464200251665ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/add-qobject-macro-to-cpp-file/main.cpp000066400000000000000000000000751266132464200266200ustar00rootroot00000000000000#include "object.h" int main() { Object o; o.f(); } qbs-src-1.4.5/tests/auto/api/testdata/add-qobject-macro-to-cpp-file/object.cpp000066400000000000000000000002341266132464200271370ustar00rootroot00000000000000#include "object.h" #include // class InternalClass : public QObject // { // Q_OBJECT // }; void Object::f() { } // #include "object.moc" qbs-src-1.4.5/tests/auto/api/testdata/add-qobject-macro-to-cpp-file/object.h000066400000000000000000000000501266132464200266000ustar00rootroot00000000000000class Object { public: void f(); }; qbs-src-1.4.5/tests/auto/api/testdata/add-qobject-macro-to-cpp-file/project.qbs000066400000000000000000000001211266132464200273350ustar00rootroot00000000000000import qbs QtApplication { files: ["main.cpp", "object.h", "object.cpp"] } qbs-src-1.4.5/tests/auto/api/testdata/added-file-persistent/000077500000000000000000000000001266132464200237515ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/added-file-persistent/file.cpp000066400000000000000000000000151266132464200253700ustar00rootroot00000000000000void f() { } qbs-src-1.4.5/tests/auto/api/testdata/added-file-persistent/main.cpp000066400000000000000000000000371266132464200254010ustar00rootroot00000000000000void f(); int main() { f(); } qbs-src-1.4.5/tests/auto/api/testdata/added-file-persistent/project.qbs000066400000000000000000000001371266132464200261270ustar00rootroot00000000000000import qbs CppApplication { files: [ 'main.cpp', /* 'file.cpp' */ ] } qbs-src-1.4.5/tests/auto/api/testdata/app-without-sources/000077500000000000000000000000001266132464200235375ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/app-without-sources/a.c000066400000000000000000000000311266132464200241150ustar00rootroot00000000000000int foo() { return 42; } qbs-src-1.4.5/tests/auto/api/testdata/app-without-sources/b.c000066400000000000000000000001751266132464200241270ustar00rootroot00000000000000#include int foo(); // defined in a.cpp int main() { printf("The answer is %d.\n", foo()); return 0; } qbs-src-1.4.5/tests/auto/api/testdata/app-without-sources/project.qbs000066400000000000000000000012541266132464200257160ustar00rootroot00000000000000import qbs 1.0 Project { StaticLibrary { name: "a" Depends { name: "cpp" } files: [ "a.c", ] } StaticLibrary { name: "b" Depends { name: "a" } Depends { name: "cpp" } files: [ "b.c", ] } CppApplication { name: "appWithoutSources" // HACK: cpp.entryPoint currently not working 100% with gcc Properties { condition: qbs.toolchain.contains("msvc") cpp.entryPoint: "main" } cpp.entryPoint: undefined bundle.isBundle: false Depends { name: "a" } Depends { name: "b" } } } qbs-src-1.4.5/tests/auto/api/testdata/base-properties/000077500000000000000000000000001266132464200227015ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/base-properties/imports/000077500000000000000000000000001266132464200243765ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/base-properties/imports/Bar.qbs000066400000000000000000000001261266132464200256100ustar00rootroot00000000000000import qbs 1.0 Product { Depends { name: "cpp" } cpp.defines: ["FROM_BAR"] } qbs-src-1.4.5/tests/auto/api/testdata/base-properties/imports/Foo.qbs000066400000000000000000000001711266132464200256270ustar00rootroot00000000000000import qbs 1.0 Bar { type: "application" consoleApplication: true cpp.defines: base.concat(["FROM_FOO"]) } qbs-src-1.4.5/tests/auto/api/testdata/base-properties/main.cpp000066400000000000000000000032511266132464200243320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef FROM_FOO #error FROM_FOO missing! #endif #ifndef FROM_BAR #error FROM_BAR missing! #endif #ifndef FROM_PRJ #error FROM_PRJ missing! #endif int main() { return 0; } qbs-src-1.4.5/tests/auto/api/testdata/base-properties/prj.qbs000066400000000000000000000002271266132464200242040ustar00rootroot00000000000000import qbs 1.0 import "imports/Foo.qbs" as Foo Project { Foo { cpp.defines: base.concat(["FROM_PRJ"]); files: "main.cpp" } } qbs-src-1.4.5/tests/auto/api/testdata/build-properties-source/000077500000000000000000000000001266132464200243645ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/build-properties-source/main.cpp000066400000000000000000000031561266132464200260210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #ifndef WORLD # error WORLD is not defined #endif int main() { puts("Hello " WORLD "!"); } qbs-src-1.4.5/tests/auto/api/testdata/build-properties-source/project.qbs000066400000000000000000000004241266132464200265410ustar00rootroot00000000000000import qbs 1.0 Project { Product { type: "application" consoleApplication: true name: "HelloWorld" Depends { name: 'cpp' } Group { cpp.defines: ['WORLD="BANANA"'] files : [ "main.cpp" ] } } } qbs-src-1.4.5/tests/auto/api/testdata/build-single-file/000077500000000000000000000000001266132464200230705ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/build-single-file/compiled.cpp000066400000000000000000000000141266132464200253630ustar00rootroot00000000000000void f() {} qbs-src-1.4.5/tests/auto/api/testdata/build-single-file/ignored1.cpp000066400000000000000000000000001266132464200252720ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/build-single-file/ignored2.cpp000066400000000000000000000000001266132464200252730ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/build-single-file/project.qbs000066400000000000000000000001331266132464200252420ustar00rootroot00000000000000import qbs CppApplication { files: ["ignored1.cpp", "ignored2.cpp", "compiled.cpp"] } qbs-src-1.4.5/tests/auto/api/testdata/buildgraph-locking/000077500000000000000000000000001266132464200233425ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/buildgraph-locking/project.qbs000066400000000000000000000000301266132464200255100ustar00rootroot00000000000000import qbs Project { } qbs-src-1.4.5/tests/auto/api/testdata/change-dependent-lib/000077500000000000000000000000001266132464200235325ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/change-dependent-lib/change-dependent-lib.qbs000066400000000000000000000006671266132464200302070ustar00rootroot00000000000000import qbs 1.0 Project { Application { name : "HelloWorld" Group { files : [ "main.cpp" ] } Depends { name: "cpp" } Depends { name: "mylib" } } DynamicLibrary { name : "mylib" version: "1.2.3" Group { files : [ "mylib.cpp" ] } Depends { name: "cpp" } cpp.defines: ["XXXX"] bundle.isBundle: false } } qbs-src-1.4.5/tests/auto/api/testdata/change-dependent-lib/main.cpp000066400000000000000000000034361266132464200251700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #if defined(_WIN32) || defined(WIN32) # define EXPORT __declspec(dllexport) # define IMPORT __declspec(dllimport) #else # define EXPORT # define IMPORT #endif IMPORT int mylib_hello(); int main() { puts("application says hello!"); return mylib_hello(); } qbs-src-1.4.5/tests/auto/api/testdata/change-dependent-lib/mylib.cpp000066400000000000000000000033761266132464200253630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #if defined(_WIN32) || defined(WIN32) # define EXPORT __declspec(dllexport) # define IMPORT __declspec(dllimport) #else # define EXPORT # define IMPORT #endif EXPORT int mylib_hello() { puts("mylib says hello!"); return 0; } qbs-src-1.4.5/tests/auto/api/testdata/codegen/000077500000000000000000000000001266132464200212015ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/codegen/foo.txt000066400000000000000000000000141266132464200225200ustar00rootroot00000000000000Hello World qbs-src-1.4.5/tests/auto/api/testdata/codegen/project.qbs000066400000000000000000000051111266132464200233540ustar00rootroot00000000000000import qbs 1.0 import qbs.FileInfo Project { property string name: 'codegen' property string osSpecificName: name.toUpperCase() + '_' + qbs.targetOS[0].toUpperCase() Product { type: 'application' consoleApplication: true name: project.name property var replacements: ({ NUMBERTYPE: "int", STRINGTYPE: "char **", FUNCTIONNAME: "main" }) Group { files: 'foo.txt' fileTags: ['text'] } Depends { name: 'cpp' } Depends { name: 'Qt.core' } } Rule { inputs: ['text'] Artifact { fileTags: ['cpp'] filePath: input.baseName + '.cpp' } prepare: { function expandMacros(str, table) { var rex = /\$\w+/; var m = rex.exec(str); while (m != null) { str = str.substr(0, m.index) + table[m[0].substr(1)] + str.substr(m.index + m[0].length); m = rex.exec(str); } return str; } // check whether multipart module name translation is working var actual = product.moduleProperty("Qt.core", "mocName"); if (!actual || !actual.contains("moc")) throw "multipart module name translation is broken"; // check whether we can access project properties here var expected = "CODEGEN_" + product.moduleProperty("qbs", "targetOS")[0].toUpperCase(); if (project.osSpecificName !== expected) throw "Wrong project property value: " + project.osSpecificName + "\nexpected: " + expected; var code = '$NUMBERTYPE $FUNCTIONNAME($NUMBERTYPE, $STRINGTYPE) { return 0; }'; code = expandMacros(code, product.replacements); var args = ['echo ' + code + '>' + output.filePath] var cmd if (product.moduleProperty("qbs", "hostOS").contains('windows')) { cmd = new Command('cmd.exe', ['/C'].concat(args)); } else { args[0] = args[0].replace(/\(/g, '\\(') args[0] = args[0].replace(/\)/g, '\\)') args[0] = args[0].replace(/;/g, '\\;') cmd = new Command('/bin/sh', ['-c'].concat(args)) } cmd.description = 'generate\t' + FileInfo.fileName(output.filePath); cmd.highlight = 'codegen'; return cmd; } } } qbs-src-1.4.5/tests/auto/api/testdata/command-extraction/000077500000000000000000000000001266132464200233715ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/command-extraction/main.cpp000066400000000000000000000000161266132464200250160ustar00rootroot00000000000000int main() {} qbs-src-1.4.5/tests/auto/api/testdata/command-extraction/project.qbs000066400000000000000000000000651266132464200255470ustar00rootroot00000000000000import qbs CppApplication { files: "main.cpp" } qbs-src-1.4.5/tests/auto/api/testdata/disabled-product/000077500000000000000000000000001266132464200230225ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/disabled-product/disabledProduct.qbs000066400000000000000000000002511266132464200266370ustar00rootroot00000000000000import qbs CppApplication { condition: false files: "main.cpp" Group { condition: qbs.targetOS.contains("stuff") qbs.install: false } } qbs-src-1.4.5/tests/auto/api/testdata/disabled-product/main.cpp000066400000000000000000000000231266132464200244450ustar00rootroot00000000000000thiswillnotcompile qbs-src-1.4.5/tests/auto/api/testdata/disabled-project/000077500000000000000000000000001266132464200230105ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/disabled-project/disabled_project.qbs000066400000000000000000000001641266132464200270150ustar00rootroot00000000000000import qbs import qbs.File Project { condition: File.exists("blubb"); references: "blubb/nosuchfile.qbs" } qbs-src-1.4.5/tests/auto/api/testdata/disabled_install_group/000077500000000000000000000000001266132464200243065ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/disabled_install_group/main.cpp000066400000000000000000000000171266132464200257340ustar00rootroot00000000000000int main() { } qbs-src-1.4.5/tests/auto/api/testdata/disabled_install_group/project.qbs000066400000000000000000000002721266132464200264640ustar00rootroot00000000000000import qbs CppApplication { files: "main.cpp" Group { condition: false qbs.install: true fileTagsFilter: product.type } bundle.isBundle: false } qbs-src-1.4.5/tests/auto/api/testdata/duplicate-product-names/000077500000000000000000000000001266132464200243265ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/duplicate-product-names/explicit.qbs000066400000000000000000000001621266132464200266550ustar00rootroot00000000000000import qbs Project { Product { name: "blubb" } Product { name: "blubb" } Product { name: "blubb" } } qbs-src-1.4.5/tests/auto/api/testdata/duplicate-product-names/implicit-indirect.qbs000066400000000000000000000001351266132464200304450ustar00rootroot00000000000000import qbs Project { references: ["subdir1/subproject.qbs", "subdir2/subproject.qbs"] } qbs-src-1.4.5/tests/auto/api/testdata/duplicate-product-names/implicit.qbs000066400000000000000000000001101266132464200266370ustar00rootroot00000000000000import qbs Project { Product { } Product { } Product { } } qbs-src-1.4.5/tests/auto/api/testdata/duplicate-product-names/subdir1/000077500000000000000000000000001266132464200256775ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/duplicate-product-names/subdir1/subproject.qbs000066400000000000000000000000301266132464200305570ustar00rootroot00000000000000import qbs Product { } qbs-src-1.4.5/tests/auto/api/testdata/duplicate-product-names/subdir2/000077500000000000000000000000001266132464200257005ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/duplicate-product-names/subdir2/subproject.qbs000066400000000000000000000000301266132464200305600ustar00rootroot00000000000000import qbs Product { } qbs-src-1.4.5/tests/auto/api/testdata/dynamic-libs/000077500000000000000000000000001266132464200221505ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/dynamic-libs/lib1.cpp000066400000000000000000000034511266132464200235060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #if defined(_WIN32) || defined(WIN32) # define EXPORT __declspec(dllexport) # define IMPORT __declspec(dllimport) #else # define EXPORT # define IMPORT #endif IMPORT void lib2_hello(); EXPORT int lib1_hello() { puts("lib1 says hello!"); lib2_hello(); return 0; } qbs-src-1.4.5/tests/auto/api/testdata/dynamic-libs/lib2.cpp000066400000000000000000000035041266132464200235060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #if defined(_WIN32) || defined(WIN32) # define EXPORT __declspec(dllexport) # define IMPORT __declspec(dllimport) #else # define EXPORT __attribute__((visibility("default"))) # define IMPORT #endif IMPORT void lib3_hello(); EXPORT void lib2_hello() { puts("lib2 says hello!"); lib3_hello(); } qbs-src-1.4.5/tests/auto/api/testdata/dynamic-libs/lib3.cpp000066400000000000000000000035641266132464200235150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #if defined(_WIN32) || defined(WIN32) # define EXPORT __declspec(dllexport) # define IMPORT __declspec(dllimport) #else # define EXPORT __attribute__((visibility("default"))) # define IMPORT #endif EXPORT void lib3_hello() { puts("lib3 says hello!"); } EXPORT char* lib3_greeting() { static char greeting[] = "hello"; return greeting; } qbs-src-1.4.5/tests/auto/api/testdata/dynamic-libs/lib4.cpp000066400000000000000000000002611266132464200235050ustar00rootroot00000000000000#include "lib4.h" TestMe::TestMe() { } void TestMe::hello1() const { puts("lib4 says hello!"); } void TestMe::hello2Impl() const { puts("lib4 says hello inline!"); } qbs-src-1.4.5/tests/auto/api/testdata/dynamic-libs/lib4.h000066400000000000000000000007451266132464200231610ustar00rootroot00000000000000#ifndef LIB4_H #define LIB4_H #include #ifdef TEST_LIB # if defined(_WIN32) || defined(WIN32) # define LIB_EXPORT __declspec(dllexport) # define LIB_NO_EXPORT # else # define LIB_EXPORT __attribute__((visibility("default"))) # endif #else # define LIB_EXPORT #endif class LIB_EXPORT TestMe { public: TestMe(); void hello1() const; inline void hello2() const { hello2Impl(); } private: void hello2Impl() const; }; #endif // LIB4_H qbs-src-1.4.5/tests/auto/api/testdata/dynamic-libs/link_dynamiclib.qbs000066400000000000000000000026531266132464200260150ustar00rootroot00000000000000import qbs 1.0 Project { Application { name : "HelloWorld" destinationDirectory: "bin" Group { files : [ "main.cpp" ] } Depends { name: "cpp" } Depends { name: "lib1" } Depends { name: "lib4" } } DynamicLibrary { name : "lib1" destinationDirectory: "bin" Group { files : [ "lib1.cpp" ] } Depends { name: "cpp" } Depends { name: "lib2" } bundle.isBundle: false } DynamicLibrary { name : "lib2" destinationDirectory: "bin" cpp.visibility: 'default' Group { files : [ "lib2.cpp" ] } Depends { name: "cpp" } Depends { name: "lib3" } bundle.isBundle: false } DynamicLibrary { name : "lib3" destinationDirectory: "bin" cpp.visibility: 'hidden' Group { files : [ "lib3.cpp" ] } Depends { name: "cpp" } bundle.isBundle: false } DynamicLibrary { name : "lib4" destinationDirectory: "bin" cpp.visibility: 'hiddenInlines' cpp.defines: "TEST_LIB" Group { files : [ "lib4.h", "lib4.cpp" ] } Depends { name: "cpp" } bundle.isBundle: false Export { Depends { name: "cpp" } cpp.includePaths: [product.sourceDirectory] } } } qbs-src-1.4.5/tests/auto/api/testdata/dynamic-libs/main.cpp000066400000000000000000000035451266132464200236070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #include #if defined(_WIN32) || defined(WIN32) # define EXPORT __declspec(dllexport) # define IMPORT __declspec(dllimport) #else # define EXPORT # define IMPORT #endif IMPORT int lib1_hello(); int main() { puts("application says hello!"); TestMe test; test.hello1(); test.hello2(); return lib1_hello(); } qbs-src-1.4.5/tests/auto/api/testdata/empty-filetag-list/000077500000000000000000000000001266132464200233155ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/empty-filetag-list/dontcompilethis.cpp000066400000000000000000000000211266132464200272170ustar00rootroot00000000000000This is not C++. qbs-src-1.4.5/tests/auto/api/testdata/empty-filetag-list/project.qbs000066400000000000000000000001531266132464200254710ustar00rootroot00000000000000import qbs CppApplication { Group { files: "dontcompilethis.cpp" fileTags: [] } } qbs-src-1.4.5/tests/auto/api/testdata/empty-submodules-list/000077500000000000000000000000001266132464200240645ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/empty-submodules-list/project.qbs000066400000000000000000000001401266132464200262340ustar00rootroot00000000000000import qbs CppApplication { Depends { name: "dummy" submodules: [] } } qbs-src-1.4.5/tests/auto/api/testdata/enable-and-disable-product/000077500000000000000000000000001266132464200246425ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/enable-and-disable-product/main.cpp000066400000000000000000000000161266132464200262670ustar00rootroot00000000000000int main() {} qbs-src-1.4.5/tests/auto/api/testdata/enable-and-disable-product/project.qbs000066400000000000000000000003111266132464200270120ustar00rootroot00000000000000import qbs CppApplication { property string prop: undefined // Influences source artifact properties and the product condition condition: prop cpp.visibility: prop files: "main.cpp" } qbs-src-1.4.5/tests/auto/api/testdata/explicitly-depends-on/000077500000000000000000000000001266132464200240155ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/explicitly-depends-on/dependency.txt000066400000000000000000000000001266132464200266620ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/explicitly-depends-on/project.qbs000066400000000000000000000013171266132464200261740ustar00rootroot00000000000000import qbs import qbs.TextFile Product { type: "mytype" files: "dependency.txt" FileTagger { patterns: "*.txt" fileTags: ["txt"] } Transformer { explicitlyDependsOn: "txt" Artifact { filePath: "test.mytype" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating output artifact"; cmd.highlight = "codegen"; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.WriteOnly); file.truncate(); file.close(); } return cmd; } } } qbs-src-1.4.5/tests/auto/api/testdata/export-item-with-group/000077500000000000000000000000001266132464200241555ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/export-item-with-group/main.cpp000066400000000000000000000000171266132464200256030ustar00rootroot00000000000000int main() { } qbs-src-1.4.5/tests/auto/api/testdata/export-item-with-group/project.qbs000066400000000000000000000004251266132464200263330ustar00rootroot00000000000000import qbs Project { Product { name: "dep" Export { Depends { name: "cpp" } Group { files: ["main.cpp"] } } } Application { name: "app" bundle.isBundle: false Depends { name: "dep" } } } qbs-src-1.4.5/tests/auto/api/testdata/export-simple/000077500000000000000000000000001266132464200224055ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/export-simple/lib1.cpp000066400000000000000000000033741266132464200237470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #if defined(_WIN32) || defined(WIN32) # define EXPORT __declspec(dllexport) # define IMPORT __declspec(dllimport) #else # define EXPORT # define IMPORT #endif EXPORT int lib1_hello() { puts("lib1 says hello!"); return 0; } qbs-src-1.4.5/tests/auto/api/testdata/export-simple/main.cpp000066400000000000000000000034341266132464200240410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #if defined(_WIN32) || defined(WIN32) # define EXPORT __declspec(dllexport) # define IMPORT __declspec(dllimport) #else # define EXPORT # define IMPORT #endif IMPORT int lib1_hello(); int main() { puts("application says hello!"); return lib1_hello(); } qbs-src-1.4.5/tests/auto/api/testdata/export-simple/project.qbs000066400000000000000000000017251266132464200245670ustar00rootroot00000000000000import qbs 1.0 Project { Application { name : "HelloWorld" destinationDirectory: "bin" Group { files : [ "main.cpp" ] } Depends { name: "cpp" } Depends { name: 'dummy' } } Product { name: 'dummy' Group { files: 'main.cpp' qbs.install: true } Export { Depends { name: 'dummy2' } Properties { // QBS-550 condition: false qbs.optimization: "ludicrous speed" } } } Product { name: 'dummy2' Group { files: 'lib1.cpp' qbs.install: true } Export { Depends { name: 'lib1' } } } DynamicLibrary { name : "lib1" destinationDirectory: "bin" Group { files : [ "lib1.cpp" ] } Depends { name: "cpp" } bundle.isBundle: false } } qbs-src-1.4.5/tests/auto/api/testdata/export-with-recursive-depends/000077500000000000000000000000001266132464200255145ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/export-with-recursive-depends/main1.cpp000066400000000000000000000000161266132464200272220ustar00rootroot00000000000000int main() {} qbs-src-1.4.5/tests/auto/api/testdata/export-with-recursive-depends/main2.cpp000066400000000000000000000000631266132464200272250ustar00rootroot00000000000000int main() { #ifndef HAS_FOO blubb(); #endif } qbs-src-1.4.5/tests/auto/api/testdata/export-with-recursive-depends/modules/000077500000000000000000000000001266132464200271645ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/export-with-recursive-depends/modules/module1/000077500000000000000000000000001266132464200305325ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/export-with-recursive-depends/modules/module1/module1.qbs000066400000000000000000000000671266132464200326120ustar00rootroot00000000000000import qbs Module { Depends { name: "module2" } } qbs-src-1.4.5/tests/auto/api/testdata/export-with-recursive-depends/modules/module2/000077500000000000000000000000001266132464200305335ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/export-with-recursive-depends/modules/module2/module2.qbs000066400000000000000000000001201266132464200326020ustar00rootroot00000000000000import qbs Module { Depends { name: "cpp" } cpp.defines: ["HAS_FOO"] } qbs-src-1.4.5/tests/auto/api/testdata/export-with-recursive-depends/project.qbs000066400000000000000000000003771266132464200277000ustar00rootroot00000000000000import qbs Project { CppApplication { name: "app1" files: "main1.cpp" Export { Depends { name: "module1" } } } CppApplication { name: "app2" Depends { name: "app1" } files: "main2.cpp" } } qbs-src-1.4.5/tests/auto/api/testdata/file-tagger/000077500000000000000000000000001266132464200217635ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/file-tagger/bla.txt000066400000000000000000000002131266132464200232560ustar00rootroot00000000000000#include class MyObject : public QObject { Q_OBJECT }; int main() { MyObject obj; return 0; } #include "bla.moc" qbs-src-1.4.5/tests/auto/api/testdata/file-tagger/moc_cpp.qbs000066400000000000000000000020471266132464200241150ustar00rootroot00000000000000import qbs 1.0 import qbs.TextFile import qbs.FileInfo Project { Product { type: "application" consoleApplication: true name: "moc_cpp" Depends { name: "Qt.core" } Group { files: 'bla.txt' fileTags: ['text'] } } Rule { inputs: ['text'] Artifact { fileTags: ['cpp'] filePath: input.baseName + '.cpp' } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = function () { var file = new TextFile(input.filePath, TextFile.ReadOnly); var text = file.readAll(); file.close(); file = new TextFile(output.filePath, TextFile.WriteOnly); file.truncate(); file.write(text); file.close(); } cmd.description = 'generating ' + FileInfo.fileName(output.filePath); cmd.highlight = 'codegen'; return cmd; } } } qbs-src-1.4.5/tests/auto/api/testdata/filetagsfilter_override/000077500000000000000000000000001266132464200245005ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/filetagsfilter_override/InstalledApp.qbs000066400000000000000000000003041266132464200275640ustar00rootroot00000000000000import qbs CppApplication { type: "application" consoleApplication: true Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "hurz" } } qbs-src-1.4.5/tests/auto/api/testdata/filetagsfilter_override/main.cpp000066400000000000000000000000161266132464200261250ustar00rootroot00000000000000int main() {} qbs-src-1.4.5/tests/auto/api/testdata/filetagsfilter_override/project.qbs000066400000000000000000000003201266132464200266500ustar00rootroot00000000000000import qbs import "InstalledApp.qbs" as InstalledApp InstalledApp { files: "main.cpp" Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "habicht" } } qbs-src-1.4.5/tests/auto/api/testdata/infinite-loop-js/000077500000000000000000000000001266132464200227635ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/infinite-loop-js/infinite-loop.qbs000066400000000000000000000006501266132464200262470ustar00rootroot00000000000000import qbs Product { type: "mytype" Transformer { Artifact { filePath: "output.txt" fileTags: "mytype" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Running infinite loop"; cmd.sourceCode = function() { while (true) ; } return cmd; } } } qbs-src-1.4.5/tests/auto/api/testdata/infinite-loop-process/000077500000000000000000000000001266132464200240255ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/infinite-loop-process/infinite-loop.qbs000066400000000000000000000012751266132464200273150ustar00rootroot00000000000000import qbs Project { QtApplication { type: "application" consoleApplication: true // suppress bundle generation files: "main.cpp" name: "infinite-loop" } Product { type: "mytype" name: "caller" Depends { name: "infinite-loop" } Rule { inputsFromDependencies: "application" Artifact { filePath: "dummy" fileTags: "mytype" } prepare: { var cmd = new Command(inputs["application"][0].filePath); cmd.description = "Calling application that runs forever"; return cmd; } } } } qbs-src-1.4.5/tests/auto/api/testdata/infinite-loop-process/main.cpp000066400000000000000000000003121266132464200254510ustar00rootroot00000000000000#include class MyThread : public QThread { public: static void mySleep(unsigned long secs) { sleep(secs); } // sleep() is protected in Qt 4. }; int main() { MyThread::mySleep(60); } qbs-src-1.4.5/tests/auto/api/testdata/infinite-loop-resolving/000077500000000000000000000000001266132464200243575ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/infinite-loop-resolving/project.qbs000066400000000000000000000001041266132464200265270ustar00rootroot00000000000000import qbs Product { type: { while (true); return "Haha!"; } } qbs-src-1.4.5/tests/auto/api/testdata/inherit-qbs-search-paths/000077500000000000000000000000001266132464200244025ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/inherit-qbs-search-paths/imports/000077500000000000000000000000001266132464200260775ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/inherit-qbs-search-paths/imports/Foo.qbs000066400000000000000000000001561266132464200273330ustar00rootroot00000000000000import qbs 1.0 Product { type: "application" consoleApplication: true Depends { name: 'bli' } } qbs-src-1.4.5/tests/auto/api/testdata/inherit-qbs-search-paths/main.cpp000066400000000000000000000001201266132464200260230ustar00rootroot00000000000000#ifndef HAVE_BLI #error HAVE_BLI missing! #endif int main() { return 0; } qbs-src-1.4.5/tests/auto/api/testdata/inherit-qbs-search-paths/prj.qbs000066400000000000000000000003061266132464200257030ustar00rootroot00000000000000import qbs 1.0 import "imports/Foo.qbs" as Foo Project { qbsSearchPaths: "subdir" Project { qbsSearchPaths: "subdir2" Foo { files: "main.cpp" } } } qbs-src-1.4.5/tests/auto/api/testdata/inherit-qbs-search-paths/subdir/000077500000000000000000000000001266132464200256725ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/inherit-qbs-search-paths/subdir/modules/000077500000000000000000000000001266132464200273425ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/inherit-qbs-search-paths/subdir/modules/bli/000077500000000000000000000000001266132464200301105ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/inherit-qbs-search-paths/subdir/modules/bli/m.qbs000066400000000000000000000001261266132464200310520ustar00rootroot00000000000000import qbs 1.0 Module { Depends {name : "cpp" } cpp.defines: ["HAVE_BLI"] } qbs-src-1.4.5/tests/auto/api/testdata/inherit-qbs-search-paths/subdir2/000077500000000000000000000000001266132464200257545ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/inherit-qbs-search-paths/subdir2/modules/000077500000000000000000000000001266132464200274245ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/inherit-qbs-search-paths/subdir2/modules/bla/000077500000000000000000000000001266132464200301625ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/inherit-qbs-search-paths/subdir2/modules/bla/m.qbs000066400000000000000000000001261266132464200311240ustar00rootroot00000000000000import qbs 1.0 Module { Depends {name : "cpp" } cpp.defines: ["HAVE_BLA"] } qbs-src-1.4.5/tests/auto/api/testdata/installed-artifact/000077500000000000000000000000001266132464200233475ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/installed-artifact/installed_artifact.qbs000066400000000000000000000010501266132464200277060ustar00rootroot00000000000000import qbs 1.0 Project { CppApplication { name: "other app" files: ["main.cpp"] } CppApplication { name: "installedApp" type: "application" consoleApplication: true Depends { name: "other app" } Group { files: "main.cpp" qbs.install: true qbs.installDir: "src" } qbs.installPrefix: "/usr" Group { fileTagsFilter: "application" qbs.install: true qbs.installDir: "bin" } } } qbs-src-1.4.5/tests/auto/api/testdata/installed-artifact/main.cpp000066400000000000000000000000161266132464200247740ustar00rootroot00000000000000int main() {} qbs-src-1.4.5/tests/auto/api/testdata/is-runnable/000077500000000000000000000000001266132464200220145ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/is-runnable/project.qbs000066400000000000000000000002251266132464200241700ustar00rootroot00000000000000import qbs Project { CppApplication { name: "app" } DynamicLibrary { name: "lib" bundle.isBundle: false } } qbs-src-1.4.5/tests/auto/api/testdata/lib-same-source/000077500000000000000000000000001266132464200225645ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/lib-same-source/main.cpp000066400000000000000000000030651266132464200242200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include int main() { puts("Hello WOrld!"); } qbs-src-1.4.5/tests/auto/api/testdata/lib-same-source/project.qbs000066400000000000000000000006311266132464200247410ustar00rootroot00000000000000import qbs 1.0 Project { Product { type: "application" consoleApplication: true name : "HelloWorldApp" Depends { name: 'cpp' } Group { files : [ "main.cpp" ] } } Product { type: "staticlibrary" name : "HelloWorldLib" Depends { name: 'cpp' } Group { files : [ "main.cpp" ] } } } qbs-src-1.4.5/tests/auto/api/testdata/link-static-lib/000077500000000000000000000000001266132464200225635ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/link-static-lib/helper1/000077500000000000000000000000001266132464200241235ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/link-static-lib/helper1/helper1.cpp000066400000000000000000000031331266132464200261670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "helper1.h" #include int getSomeNumber() { return 12 * getOddNumber(); } qbs-src-1.4.5/tests/auto/api/testdata/link-static-lib/helper1/helper1.h000066400000000000000000000031011266132464200256270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef HELPER1_H #define HELPER1_H extern int getSomeNumber(); #endif qbs-src-1.4.5/tests/auto/api/testdata/link-static-lib/helper2/000077500000000000000000000000001266132464200241245ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/link-static-lib/helper2/helper2.cpp000066400000000000000000000030641266132464200261740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "helper2.h" int getOddNumber() { return 13; } qbs-src-1.4.5/tests/auto/api/testdata/link-static-lib/helper2/helper2.h000066400000000000000000000031001266132464200256300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef HELPER2_H #define HELPER2_H extern int getOddNumber(); #endif qbs-src-1.4.5/tests/auto/api/testdata/link-static-lib/main.cpp000066400000000000000000000030721266132464200242150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include int bla(); int main() { return bla(); } qbs-src-1.4.5/tests/auto/api/testdata/link-static-lib/mystaticlib.cpp000066400000000000000000000032211266132464200256110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #include int bla() { int n = getSomeNumber(); printf("Hello World! The magic number is %d.", n); return n; } qbs-src-1.4.5/tests/auto/api/testdata/link-static-lib/mystaticlibhelper.cpp000066400000000000000000000000531266132464200270110ustar00rootroot00000000000000int helper_function() { return 156; } qbs-src-1.4.5/tests/auto/api/testdata/link-static-lib/project.qbs000066400000000000000000000020441266132464200247400ustar00rootroot00000000000000import qbs 1.0 Project { Product { type: "application" consoleApplication: true name: "HelloWorld" files : [ "main.cpp" ] Depends { name: "cpp" } Depends { name: "mystaticlib" } } StaticLibrary { name : "mystaticlib" files : [ "mystaticlib.cpp" ] Depends { name: "cpp" } Depends { name: "helper1" } } StaticLibrary { name : "helper1" files : [ "helper1/helper1.h", "helper1/helper1.cpp" ] Depends { name: "cpp" } Depends { name: "helper2" } Export { Depends { name: "cpp" } cpp.includePaths: [product.sourceDirectory + '/helper1'] } } StaticLibrary { name : "helper2" files : [ "helper2/helper2.h", "helper2/helper2.cpp" ] Depends { name: "cpp" } Export { Depends { name: "cpp" } cpp.includePaths: [product.sourceDirectory + '/helper2'] } } } qbs-src-1.4.5/tests/auto/api/testdata/lots-of-dots/000077500000000000000000000000001266132464200221275ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/lots-of-dots/dotty.matrix.ui000066400000000000000000000006541266132464200251410ustar00rootroot00000000000000 Form 0 0 400 300 Form qbs-src-1.4.5/tests/auto/api/testdata/lots-of-dots/m.a.i.n.cpp000066400000000000000000000001761266132464200237750ustar00rootroot00000000000000#include "object.narf.h" #include #include int main() { ObjectNarf obj; puts("..."); } qbs-src-1.4.5/tests/auto/api/testdata/lots-of-dots/object.narf.cpp000066400000000000000000000001561266132464200250300ustar00rootroot00000000000000#include "object.narf.h" #include ObjectNarf::ObjectNarf(QObject *parent) : QObject(parent) {} qbs-src-1.4.5/tests/auto/api/testdata/lots-of-dots/object.narf.h000066400000000000000000000002401266132464200244670ustar00rootroot00000000000000#ifndef OBJECT_H #define OBJECT_H #include class ObjectNarf : public QObject { Q_OBJECT public: ObjectNarf(QObject *parent = 0); }; #endif qbs-src-1.4.5/tests/auto/api/testdata/lots-of-dots/polka.dots.qrc000066400000000000000000000001441266132464200247130ustar00rootroot00000000000000 m.a.i.n.cpp qbs-src-1.4.5/tests/auto/api/testdata/lots-of-dots/project.qbs000066400000000000000000000005041266132464200243030ustar00rootroot00000000000000import qbs 1.0 Project { QtGuiApplication { type: "application" consoleApplication: true name: "lots.of.dots" files : [ "m.a.i.n.cpp", "object.narf.h", "object.narf.cpp", "polka.dots.qrc", "dotty.matrix.ui" ] } } qbs-src-1.4.5/tests/auto/api/testdata/missing-qobject-header/000077500000000000000000000000001266132464200241215ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/missing-qobject-header/main.cpp000066400000000000000000000000751266132464200255530ustar00rootroot00000000000000#include "myobject.h" int main() { MyObject().func(); } qbs-src-1.4.5/tests/auto/api/testdata/missing-qobject-header/myobject.cpp000066400000000000000000000000611266132464200264360ustar00rootroot00000000000000#include "myobject.h" void MyObject::func() { } qbs-src-1.4.5/tests/auto/api/testdata/missing-qobject-header/myobject.h000066400000000000000000000001411266132464200261020ustar00rootroot00000000000000#include class MyObject : public QObject { Q_OBJECT public: void func(); }; qbs-src-1.4.5/tests/auto/api/testdata/moc-cpp/000077500000000000000000000000001266132464200211335ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/moc-cpp/bla.cpp000066400000000000000000000002131266132464200223710ustar00rootroot00000000000000#include class MyObject : public QObject { Q_OBJECT }; int main() { MyObject obj; return 0; } #include "bla.moc" qbs-src-1.4.5/tests/auto/api/testdata/moc-cpp/project.qbs000066400000000000000000000003321266132464200233060ustar00rootroot00000000000000import qbs 1.0 Project { Product { type: "application" consoleApplication: true name: "moc_cpp" Depends { name: "Qt.core" } files: ["bla.cpp"] } } qbs-src-1.4.5/tests/auto/api/testdata/moc-hpp-included/000077500000000000000000000000001266132464200227255ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/moc-hpp-included/object.cpp000066400000000000000000000002711266132464200246770ustar00rootroot00000000000000#include "object.h" Object::Object(QObject *parent) : QObject(parent) {} #include "moc_object.cpp" #include int main() { Object obj; printf("Hello World\n"); } qbs-src-1.4.5/tests/auto/api/testdata/moc-hpp-included/object.h000066400000000000000000000002301266132464200243370ustar00rootroot00000000000000#ifndef OBJECT_H #define OBJECT_H #include class Object : public QObject { Q_OBJECT public: Object(QObject *parent = 0); }; #endif qbs-src-1.4.5/tests/auto/api/testdata/moc-hpp-included/project.qbs000066400000000000000000000004641266132464200251060ustar00rootroot00000000000000import qbs 1.0 Project { Product { type: "application" consoleApplication: true name: "moc_hpp_included" Depends { name: "Qt.core" } files : [ "object.cpp" ] Group { files : [ "object.h" ] fileTags: [ "hpp" ] } } } qbs-src-1.4.5/tests/auto/api/testdata/moc-hpp/000077500000000000000000000000001266132464200211405ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/moc-hpp/object.cpp000066400000000000000000000002361266132464200231130ustar00rootroot00000000000000#include "object.h" #include Object::Object(QObject *parent) : QObject(parent) {} int main() { Object obj; printf("Hello World\n"); } qbs-src-1.4.5/tests/auto/api/testdata/moc-hpp/object.h000066400000000000000000000002301266132464200225520ustar00rootroot00000000000000#ifndef OBJECT_H #define OBJECT_H #include class Object : public QObject { Q_OBJECT public: Object(QObject *parent = 0); }; #endif qbs-src-1.4.5/tests/auto/api/testdata/moc-hpp/project.qbs000066400000000000000000000003711266132464200233160ustar00rootroot00000000000000import qbs 1.0 Project { Product { type: "application" consoleApplication: true name: "moc_hpp" Depends { name: "Qt.core" } files : [ "object.h", "object.cpp" ] } } qbs-src-1.4.5/tests/auto/api/testdata/multi-arch/000077500000000000000000000000001266132464200216425ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/multi-arch/host+target.input000066400000000000000000000000001266132464200251500ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/multi-arch/host-tool.input000066400000000000000000000000001266132464200246410ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/multi-arch/project.qbs000066400000000000000000000025321266132464200240210ustar00rootroot00000000000000import qbs import qbs.FileInfo import qbs.TextFile Project { property string hostProfile property string targetProfile Product { name: "p1" type: "output" profiles: [project.targetProfile, project.hostProfile] Group { files: "host+target.input" fileTags: "input" } Group { fileTagsFilter: "output" qbs.install: true qbs.installDir: profile } } Product { name: "p2" type: "output" profiles: project.hostProfile Group { files: "host-tool.input" fileTags: "input" } Group { fileTagsFilter: "output" qbs.install: true qbs.installDir: profile } } Rule { inputs: "input" Artifact { filePath: FileInfo.baseName(input.fileName) + ".output" fileTags: "output" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.WriteOnly); file.write(product.moduleProperty("qbs", "architecture")); file.close(); } return cmd; } } } qbs-src-1.4.5/tests/auto/api/testdata/new-output-artifact-in-dependency/000077500000000000000000000000001266132464200262375ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/new-output-artifact-in-dependency/lib.cpp000066400000000000000000000000571266132464200275130ustar00rootroot00000000000000#include Q_DECL_EXPORT void f() {} qbs-src-1.4.5/tests/auto/api/testdata/new-output-artifact-in-dependency/main.cpp000066400000000000000000000000471266132464200276700ustar00rootroot00000000000000//void f(); int main() { // f(); } qbs-src-1.4.5/tests/auto/api/testdata/new-output-artifact-in-dependency/project.qbs000066400000000000000000000004611266132464200304150ustar00rootroot00000000000000import qbs Project { DynamicLibrary { //Depends { name: "cpp" } //Depends { name: "Qt.core" } name: "lib" files: "lib.cpp" bundle.isBundle: false } CppApplication { name: "app" files: "main.cpp" Depends { name: "lib" } } } qbs-src-1.4.5/tests/auto/api/testdata/new-pattern-match/000077500000000000000000000000001266132464200231335ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/new-pattern-match/project.qbs000066400000000000000000000000531266132464200253060ustar00rootroot00000000000000import qbs Product { files: "*.txt" } qbs-src-1.4.5/tests/auto/api/testdata/nonexistingprojectproperties/000077500000000000000000000000001266132464200256465ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/nonexistingprojectproperties/invalidaccessfromproduct.qbs000066400000000000000000000000701266132464200334470ustar00rootroot00000000000000import qbs Project { Product { type: project.blubb } } qbs-src-1.4.5/tests/auto/api/testdata/nonexistingprojectproperties/project.qbs000066400000000000000000000000301266132464200300140ustar00rootroot00000000000000import qbs Project { } qbs-src-1.4.5/tests/auto/api/testdata/objc/000077500000000000000000000000001266132464200205125ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/objc/main.mm000066400000000000000000000007401266132464200217720ustar00rootroot00000000000000#import #include int main(int argc, char **argv) { // We support both C++ QCoreApplication app(argc, argv); Q_UNUSED(app); // And Objective-C NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]; NSString *productVersion = [version objectForKey:@"ProductVersion"]; NSLog(@"Hello, OS X %@!", productVersion); // So it's Objective-C++ } qbs-src-1.4.5/tests/auto/api/testdata/objc/objc.qbs000066400000000000000000000002501266132464200221330ustar00rootroot00000000000000import qbs 1.0 Project { QtApplication { condition: qbs.targetOS.contains("osx") files: "main.mm" cpp.frameworks: [ "Foundation" ] } } qbs-src-1.4.5/tests/auto/api/testdata/precompiled-header/000077500000000000000000000000001266132464200233265ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/precompiled-header/main.cpp000066400000000000000000000010071266132464200247540ustar00rootroot00000000000000#include "myobject.h" #include #include #include using namespace std; int main() { MyObject obj; list lst; lst.push_back(1); lst.push_back(2); lst.push_back(3); lst.push_back(4); lst.push_back(5); lst.push_back(6); lst.push_back(7); lst.push_back(8); lst.push_back(9); reverse(lst.begin(), lst.end()); for (list::iterator it=lst.begin(); it != lst.end(); ++it) cout << *it << ", "; cout << endl; return 0; } qbs-src-1.4.5/tests/auto/api/testdata/precompiled-header/myobject.cpp000066400000000000000000000003021266132464200256410ustar00rootroot00000000000000#include #include "myobject.h" MyObject::MyObject() { std::cout << "MyObject::MyObject()\n"; } MyObject::~MyObject() { std::cout << "MyObject::~MyObject()" << std::endl; } qbs-src-1.4.5/tests/auto/api/testdata/precompiled-header/myobject.h000066400000000000000000000002461266132464200253150ustar00rootroot00000000000000#ifndef MYOBJECT_H #define MYOBJECT_H #include class MyObject : public QObject { Q_OBJECT public: MyObject(); ~MyObject(); }; #endif qbs-src-1.4.5/tests/auto/api/testdata/precompiled-header/project.qbs000066400000000000000000000004541266132464200255060ustar00rootroot00000000000000import qbs 1.0 Product { type: "application" consoleApplication: true name: "MyApp" files: ["stable.h", "myobject.h", "main.cpp", "myobject.cpp"] Depends { name: "cpp" } cpp.precompiledHeader: "stable.h" Depends { name: "Qt.core" } } qbs-src-1.4.5/tests/auto/api/testdata/precompiled-header/stable.h000066400000000000000000000002031266132464200247440ustar00rootroot00000000000000/* Add C includes here */ #if defined __cplusplus /* Add C++ includes here */ # include # include #endif qbs-src-1.4.5/tests/auto/api/testdata/productNameWithDots/000077500000000000000000000000001266132464200235445ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/productNameWithDots/app.cpp000066400000000000000000000000311266132464200250220ustar00rootroot00000000000000int main() { return 0; } qbs-src-1.4.5/tests/auto/api/testdata/productNameWithDots/lib.cpp000066400000000000000000000000161266132464200250130ustar00rootroot00000000000000void foo() {} qbs-src-1.4.5/tests/auto/api/testdata/productNameWithDots/project.qbs000066400000000000000000000005651266132464200257270ustar00rootroot00000000000000import qbs Project { Product { Depends { name: "cpp" } Depends { name: "bundle" } type: ["application"] name: "myapp" Depends { name: "foo.bar.bla" } files: ["app.cpp"] bundle.isBundle: false } StaticLibrary { Depends { name: "cpp" } name: "foo.bar.bla" files: ["lib.cpp"] } } qbs-src-1.4.5/tests/auto/api/testdata/project-editing/000077500000000000000000000000001266132464200226645ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/project-editing/existingfile1.txt000066400000000000000000000000001266132464200261660ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/project-editing/existingfile2.txt000066400000000000000000000000001266132464200261670ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/project-editing/existingfile3.txt000066400000000000000000000000001266132464200261700ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/project-editing/file.cpp000066400000000000000000000000001266132464200242750ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/project-editing/file.h000066400000000000000000000000001266132464200237420ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/project-editing/main.cpp000066400000000000000000000000001266132464200243020ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/project-editing/newfile1.txt000066400000000000000000000000001266132464200251250ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/project-editing/newfile2.txt000066400000000000000000000000001266132464200251260ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/project-editing/newfile3.txt000066400000000000000000000000001266132464200251270ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/project-editing/newfile4.txt000066400000000000000000000000001266132464200251300ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/project-editing/project-with-no-files.qbs000066400000000000000000000001131266132464200275170ustar00rootroot00000000000000import qbs CppApplication { Group { files: "file.cpp" } } qbs-src-1.4.5/tests/auto/api/testdata/project-editing/project.qbs000066400000000000000000000014041266132464200250400ustar00rootroot00000000000000import qbs CppApplication { Group { name: "Existing Group 1" files: ["existingfile1.txt"] } property string aFile: "existingfile2.txt" Group { name: "Existing Group 2" files: product.aFile } Group { name: "Existing Group 3" files: { var file = "existingfile3.txt"; return file; } } Group { name: "Existing Group 4" prefix: "subdir/" files: [] } Group { name: "Existing Group 5" prefix: "blubb" files: [] } Group { name: "Group with wildcards" files: "*.klaus" } Group { name: "Other group with wildcards" files: "*.wildcard" } files: "main.cpp" } qbs-src-1.4.5/tests/auto/api/testdata/project-editing/subdir/000077500000000000000000000000001266132464200241545ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/project-editing/subdir/file.txt000066400000000000000000000000001266132464200256220ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/project-editing/test.wildcard000066400000000000000000000000001266132464200253440ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/project-invalidation/000077500000000000000000000000001266132464200237225ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/project-invalidation/project.early-error.qbs000066400000000000000000000001071266132464200303370ustar00rootroot00000000000000import qbs Product { type: "mytype" files: "nosuchfile.txt" } qbs-src-1.4.5/tests/auto/api/testdata/project-invalidation/project.late-error.qbs000066400000000000000000000002621266132464200301520ustar00rootroot00000000000000import qbs Product { type: "mytype" Transformer { Artifact { filePath: "blubb" fileTags: "mytype" } prepare: [] } } qbs-src-1.4.5/tests/auto/api/testdata/project-invalidation/project.no-error.qbs000066400000000000000000000000531266132464200276370ustar00rootroot00000000000000import qbs Product { type: "mytype" } qbs-src-1.4.5/tests/auto/api/testdata/project-locking/000077500000000000000000000000001266132464200226675ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/project-locking/project.qbs000066400000000000000000000000301266132464200250350ustar00rootroot00000000000000import qbs Project { } qbs-src-1.4.5/tests/auto/api/testdata/project-properties-by-name/000077500000000000000000000000001266132464200247635ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/project-properties-by-name/main1.cpp000066400000000000000000000001521266132464200264720ustar00rootroot00000000000000#ifndef SUB1 #error "Missing define" #endif #ifdef SUB2 #error "Extraneous define" #endif int main() { } qbs-src-1.4.5/tests/auto/api/testdata/project-properties-by-name/main2.cpp000066400000000000000000000001521266132464200264730ustar00rootroot00000000000000#ifndef SUB2 #error "Missing define" #endif #ifdef SUB1 #error "Extraneous define" #endif int main() { } qbs-src-1.4.5/tests/auto/api/testdata/project-properties-by-name/project.qbs000066400000000000000000000007241266132464200271430ustar00rootroot00000000000000import qbs Project { name: "toplevel" property stringList theDefines: [] Project { name: "subproject1" CppApplication { name: "subproduct1" files: ["main1.cpp"] cpp.defines: project.theDefines } } Project { name: "subproject2" CppApplication { name: "subproduct2" files: ["main2.cpp"] cpp.defines: project.theDefines } } } qbs-src-1.4.5/tests/auto/api/testdata/project-with-properties-item/000077500000000000000000000000001266132464200253425ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/project-with-properties-item/project.qbs000066400000000000000000000003641266132464200275220ustar00rootroot00000000000000import qbs 1.0 Project { property string binPath: "/usr/bin" property string libPath: "/usr/lib" Properties { condition: qbs.targetOS.contains("osx") binPath: "/Users/boo" libPath: "/Libraries/foo" } } qbs-src-1.4.5/tests/auto/api/testdata/properties-blocks/000077500000000000000000000000001266132464200232445ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/properties-blocks/main.cpp000066400000000000000000000034441266132464200247010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #ifndef HAVE_MAIN_CPP # error missing define HAVE_MAIN_CPP #endif #ifndef DEFINE_IN_PROPERTIES # error missing define DEFINE_IN_PROPERTIES #endif int main() { #ifdef _DEBUG puts("Hello World! (debug version)"); #else puts("Hello World! (release version)"); #endif } qbs-src-1.4.5/tests/auto/api/testdata/properties-blocks/propertiesblocks.qbs000066400000000000000000000010551266132464200273460ustar00rootroot00000000000000import qbs 1.0 Product { Depends { name: 'cpp' } Properties { condition: true type: 'application' consoleApplication: true name: 'HelloWorld' } Properties { condition: name == 'HelloWorld' cpp.defines: ['DEFINE_IN_PROPERTIES'] } Properties { condition: qbs.targetOS.contains("weird") cpp.staticLibraries: "abc" } Group { cpp.defines: outer.concat(['HAVE_MAIN_CPP', cpp.debugInformation ? '_DEBUG' : '_RELEASE']) files: ['main.cpp'] } } qbs-src-1.4.5/tests/auto/api/testdata/qt5-plugin/000077500000000000000000000000001266132464200216025ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/qt5-plugin/echointerface.h000066400000000000000000000005701266132464200245540ustar00rootroot00000000000000 #ifndef ECHOINTERFACE_H #define ECHOINTERFACE_H #include //! [0] class EchoInterface { public: virtual ~EchoInterface() {} virtual QString echo(const QString &message) = 0; }; QT_BEGIN_NAMESPACE #define EchoInterface_iid "org.qt-project.Qt.Examples.EchoInterface" Q_DECLARE_INTERFACE(EchoInterface, EchoInterface_iid) QT_END_NAMESPACE //! [0] #endif qbs-src-1.4.5/tests/auto/api/testdata/qt5-plugin/echoplugin.cpp000066400000000000000000000001421266132464200244400ustar00rootroot00000000000000#include "echoplugin.h" QString EchoPlugin::echo(const QString &message) { return message; } qbs-src-1.4.5/tests/auto/api/testdata/qt5-plugin/echoplugin.h000066400000000000000000000005521266132464200241120ustar00rootroot00000000000000 #ifndef ECHOPLUGIN_H #define ECHOPLUGIN_H #include #include #include "echointerface.h" class EchoPlugin : public QObject, EchoInterface { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.EchoInterface" FILE "echoplugin.json") Q_INTERFACES(EchoInterface) public: QString echo(const QString &message); }; #endif qbs-src-1.4.5/tests/auto/api/testdata/qt5-plugin/echoplugin.json.source000066400000000000000000000000031266132464200261220ustar00rootroot00000000000000{} qbs-src-1.4.5/tests/auto/api/testdata/qt5-plugin/echoplugin_dummy.cpp000066400000000000000000000000241266132464200256520ustar00rootroot00000000000000void dummyFunc() {} qbs-src-1.4.5/tests/auto/api/testdata/qt5-plugin/project.qbs000066400000000000000000000020101266132464200237500ustar00rootroot00000000000000import qbs.base import qbs.File import qbs.FileInfo DynamicLibrary { name: "echoplugin" Depends { name: "Qt.core" } Depends { name: "cpp" } bundle.isBundle: false Group { condition: Qt.core.versionMajor >= 5 files: [ "echoplugin.h", "echoplugin.cpp", "echoplugin.json.source" ] } Group { condition: Qt.core.versionMajor < 5 files: "echoplugin_dummy.cpp" } cpp.includePaths: buildDirectory Transformer { condition: Qt.core.versionMajor >= 5 inputs: ["echoplugin.json.source"] Artifact { filePath: "echoplugin.json" fileTags: ["qt_plugin_metadata"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + FileInfo.fileName(output.filePath); cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } } } qbs-src-1.4.5/tests/auto/api/testdata/rc/000077500000000000000000000000001266132464200202015ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/rc/main.cpp000066400000000000000000000030251266132464200216310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ int main() { return 0; } qbs-src-1.4.5/tests/auto/api/testdata/rc/rc.qbs000066400000000000000000000002741266132464200213170ustar00rootroot00000000000000import qbs 1.0 Application { type: "application" consoleApplication: true name: "rc" Depends { name: 'cpp' } files: [ "main.cpp", "test.rc" ] } qbs-src-1.4.5/tests/auto/api/testdata/rc/test.rc000066400000000000000000000005701266132464200215100ustar00rootroot00000000000000#define IDR_VERSION1 1 IDR_VERSION1 VERSIONINFO FILEVERSION 1,0,0,0 PRODUCTVERSION 1,0,0,0 FILEOS 0x00000004 FILETYPE 0x00000000 BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "FFFF0000" BEGIN VALUE "FileVersion", "1.0.0.0\0" VALUE "ProductVersion", "1.0.0.0\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0xFFFF, 0x0000 END END qbs-src-1.4.5/tests/auto/api/testdata/recursive-wildcards/000077500000000000000000000000001266132464200235565ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/recursive-wildcards/dir/000077500000000000000000000000001266132464200243345ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/recursive-wildcards/dir/file1.txt000066400000000000000000000000001266132464200260630ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/recursive-wildcards/dir/subdir/000077500000000000000000000000001266132464200256245ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/recursive-wildcards/dir/subdir/file2.txt000066400000000000000000000000001266132464200273540ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/recursive-wildcards/recursive_wildcards.qbs000066400000000000000000000001561266132464200303320ustar00rootroot00000000000000Product { Group { files: "dir/**" qbs.install: true qbs.installDir: "dir" } } qbs-src-1.4.5/tests/auto/api/testdata/references/000077500000000000000000000000001266132464200217165ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/references/invalid1.qbs000066400000000000000000000001001266132464200241230ustar00rootroot00000000000000import qbs Project { references: "subdir-with-no-project" }qbs-src-1.4.5/tests/auto/api/testdata/references/invalid2.qbs000066400000000000000000000001071266132464200241330ustar00rootroot00000000000000import qbs Project { references: "subdir-with-multiple-projects" }qbs-src-1.4.5/tests/auto/api/testdata/references/subdir-with-multiple-projects/000077500000000000000000000000001266132464200276375ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/references/subdir-with-multiple-projects/subproject1.qbs000066400000000000000000000000001266132464200325750ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/references/subdir-with-multiple-projects/subproject2.qbs000066400000000000000000000000001266132464200325760ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/references/subdir-with-multiple-projects/subproject3.qbs000066400000000000000000000000001266132464200325770ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/references/subdir-with-no-project/000077500000000000000000000000001266132464200262355ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/references/subdir-with-no-project/test.txt000066400000000000000000000000001266132464200277430ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/references/subdir-with-one-project/000077500000000000000000000000001266132464200264025ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/references/subdir-with-one-project/p.qbs000066400000000000000000000000301266132464200273410ustar00rootroot00000000000000import qbs Project { } qbs-src-1.4.5/tests/auto/api/testdata/references/subdir-with-one-project/test.txt000066400000000000000000000000001266132464200301100ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/references/valid.qbs000066400000000000000000000001021266132464200235150ustar00rootroot00000000000000import qbs Project { references: "subdir-with-one-project" } qbs-src-1.4.5/tests/auto/api/testdata/remove-file-dependency/000077500000000000000000000000001266132464200241235ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/remove-file-dependency/main.cpp000066400000000000000000000001771266132464200255600ustar00rootroot00000000000000#include "someheader.h" #include int main() { printf("The magic value is %d.\n", magicValue()); return 0; } qbs-src-1.4.5/tests/auto/api/testdata/remove-file-dependency/removeFileDependency.qbs000066400000000000000000000002161266132464200307250ustar00rootroot00000000000000import qbs CppApplication { files: ["main.cpp"] // Do not reference header files here to force them to be FileDependency objects. } qbs-src-1.4.5/tests/auto/api/testdata/remove-file-dependency/someheader.h000066400000000000000000000000501266132464200264030ustar00rootroot00000000000000inline int magicValue() { return 156; } qbs-src-1.4.5/tests/auto/api/testdata/rename-product/000077500000000000000000000000001266132464200225225ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/rename-product/lib.cpp000066400000000000000000000000541266132464200237730ustar00rootroot00000000000000#include MY_EXPORT void f() { } qbs-src-1.4.5/tests/auto/api/testdata/rename-product/main.cpp000066400000000000000000000000431266132464200241470ustar00rootroot00000000000000void f(); int main() { f(); } qbs-src-1.4.5/tests/auto/api/testdata/rename-product/rename.qbs000066400000000000000000000005601266132464200245010ustar00rootroot00000000000000import qbs Project { CppApplication { Depends { name: "TheLib" } cpp.defines: "MY_EXPORT=" files: "main.cpp" } DynamicLibrary { name: "TheLib" Depends { name: "cpp" } Depends { name: "Qt.core" } cpp.defines: "MY_EXPORT=Q_DECL_EXPORT" files: "lib.cpp" bundle.isBundle: false } } qbs-src-1.4.5/tests/auto/api/testdata/rename-target-artifact/000077500000000000000000000000001266132464200241235ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/rename-target-artifact/lib.cpp000066400000000000000000000000541266132464200253740ustar00rootroot00000000000000#include MY_EXPORT void f() { } qbs-src-1.4.5/tests/auto/api/testdata/rename-target-artifact/main.cpp000066400000000000000000000000431266132464200255500ustar00rootroot00000000000000void f(); int main() { f(); } qbs-src-1.4.5/tests/auto/api/testdata/rename-target-artifact/rename.qbs000066400000000000000000000006161266132464200261040ustar00rootroot00000000000000import qbs Project { CppApplication { Depends { name: "TheLib" } cpp.defines: "MY_EXPORT=" files: "main.cpp" } DynamicLibrary { name: "TheLib" targetName: "the_lib" Depends { name: "cpp" } Depends { name: "Qt.core" } cpp.defines: "MY_EXPORT=Q_DECL_EXPORT" files: "lib.cpp" bundle.isBundle: false } } qbs-src-1.4.5/tests/auto/api/testdata/same-base-name/000077500000000000000000000000001266132464200223505ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/same-base-name/lib.c000066400000000000000000000001401266132464200232550ustar00rootroot00000000000000#include extern void printHelloC() { printf("Hello from C in " __FILE__ "\n"); } qbs-src-1.4.5/tests/auto/api/testdata/same-base-name/lib.cpp000066400000000000000000000001711266132464200236210ustar00rootroot00000000000000#include extern "C" void printHelloCpp() { std::cout << "Hello from C++ in " << __FILE__ << std::endl; } qbs-src-1.4.5/tests/auto/api/testdata/same-base-name/lib.m000066400000000000000000000001671266132464200233000ustar00rootroot00000000000000#import extern void printHelloObjc() { NSLog(@"Hello from Objective-C in " __FILE__); } qbs-src-1.4.5/tests/auto/api/testdata/same-base-name/lib.mm000066400000000000000000000002721266132464200234520ustar00rootroot00000000000000#include #import extern "C" void printHelloObjcpp() { NSLog(@"Hello from Objective-C++..."); std::cout << "...in " __FILE__ << std::endl; } qbs-src-1.4.5/tests/auto/api/testdata/same-base-name/main.c000066400000000000000000000004331266132464200234400ustar00rootroot00000000000000extern void printHelloC(); extern void printHelloCpp(); #ifdef __APPLE__ extern void printHelloObjc(); extern void printHelloObjcpp(); #endif int main() { printHelloC(); printHelloCpp(); #ifdef __APPLE__ printHelloObjc(); printHelloObjcpp(); #endif return 0; } qbs-src-1.4.5/tests/auto/api/testdata/same-base-name/project.qbs000066400000000000000000000012501266132464200245230ustar00rootroot00000000000000import qbs 1.0 Project { CppApplication { type: "application" consoleApplication: true Depends { name: "basenamelib" } name: "basename" files: "main.c" } StaticLibrary { Depends { name: "cpp" } name: "basenamelib" files: [ "lib.c", "lib.cpp" ] Group { condition: qbs.targetOS.contains("darwin") files: [ "lib.m", "lib.mm" ] } Export { Depends { name: "cpp" } cpp.frameworks: qbs.targetOS.contains("darwin") ? "Foundation" : undefined } } } qbs-src-1.4.5/tests/auto/api/testdata/simple-probe/000077500000000000000000000000001266132464200221735ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/simple-probe/main.cpp000066400000000000000000000000311266132464200236150ustar00rootroot00000000000000int main() { return 0; } qbs-src-1.4.5/tests/auto/api/testdata/simple-probe/project.qbs000066400000000000000000000012351266132464200243510ustar00rootroot00000000000000import qbs 1.0 import qbs.Probes CppApplication { Probe { id: probe1 property string someString configure: { someString = "one"; found = true; } } Probe { id: probe2 configure: { found = false; } } name: "MyApp" type: { if (!probe1.found) throw "probe1 not found"; if (probe2.found) throw "probe2 unexpectedly found"; if (probe1.someString !== "one") throw "probe1.someString expected to be \"one\"." return "application" } consoleApplication: true files: ["main.cpp"] } qbs-src-1.4.5/tests/auto/api/testdata/soft-dependency/000077500000000000000000000000001266132464200226645ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/soft-dependency/main.cpp000066400000000000000000000000501266132464200243070ustar00rootroot00000000000000int main() { thisShouldNotLink(); } qbs-src-1.4.5/tests/auto/api/testdata/soft-dependency/project.qbs000066400000000000000000000003141266132464200250370ustar00rootroot00000000000000import qbs Application { Depends { name: "nosuchmodule" required: false } Depends { name: "cpp" condition: nosuchmodule.present } files: "main.cpp" } qbs-src-1.4.5/tests/auto/api/testdata/source-file-in-build-dir/000077500000000000000000000000001266132464200242675ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/source-file-in-build-dir/file.cpp000066400000000000000000000000001266132464200257000ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/source-file-in-build-dir/project.qbs000066400000000000000000000000651266132464200264450ustar00rootroot00000000000000import qbs CppApplication { files: "**/*.cpp" } qbs-src-1.4.5/tests/auto/api/testdata/source-file-in-build-dir/qt-debug/000077500000000000000000000000001266132464200257775ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/source-file-in-build-dir/qt-debug/moc_blubb.cpp000066400000000000000000000000001266132464200304150ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/source-file-in-build-dir/qt-debug/qt-debug.bg000066400000000000000000000000001266132464200300070ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/static-lib-deps/000077500000000000000000000000001266132464200225615ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/static-lib-deps/a1.cpp000066400000000000000000000001101266132464200235560ustar00rootroot00000000000000#include void a1() { std::cout << "a1" << std::endl; } qbs-src-1.4.5/tests/auto/api/testdata/static-lib-deps/a2.cpp000066400000000000000000000001101266132464200235570ustar00rootroot00000000000000#include void a2() { std::cout << "a2" << std::endl; } qbs-src-1.4.5/tests/auto/api/testdata/static-lib-deps/b.cpp000066400000000000000000000000441266132464200235040ustar00rootroot00000000000000void a1(); void b() { a1(); } qbs-src-1.4.5/tests/auto/api/testdata/static-lib-deps/c.cpp000066400000000000000000000000441266132464200235050ustar00rootroot00000000000000void a2(); void c() { a2(); } qbs-src-1.4.5/tests/auto/api/testdata/static-lib-deps/d.cpp000066400000000000000000000005751266132464200235170ustar00rootroot00000000000000#ifdef WITH_PTHREAD #include #elif defined(WITH_SETUPAPI) #include #include #endif void b(); void c(); int d() { b(); c(); #ifdef WITH_PTHREAD pthread_t self = pthread_self(); return static_cast(self); #elif defined(WITH_SETUPAPI) CABINET_INFO ci; ci.SetId = 0; return ci.SetId; #else return 0; #endif } qbs-src-1.4.5/tests/auto/api/testdata/static-lib-deps/e.cpp000066400000000000000000000000471266132464200235120ustar00rootroot00000000000000int d(); int e() { return d(); } qbs-src-1.4.5/tests/auto/api/testdata/static-lib-deps/main.cpp000066400000000000000000000000521266132464200242060ustar00rootroot00000000000000int e(); int main() { return e(); } qbs-src-1.4.5/tests/auto/api/testdata/static-lib-deps/project.qbs000066400000000000000000000033641266132464200247440ustar00rootroot00000000000000import qbs 1.0 Project { StaticLibrary { name: "a" Depends { name: "cpp" } files: [ "a1.cpp", "a2.cpp", ] } StaticLibrary { name: "b" Depends { name: "cpp" } Depends { name: "a" } files: [ "b.cpp", ] } StaticLibrary { name: "c" Depends { name: "cpp" } Depends { name: "a" } files: [ "c.cpp", ] } StaticLibrary { name: "d" Depends { name: "cpp" } Depends { name: "b" } Depends { name: "c" } files: [ "d.cpp", ] Properties { condition: qbs.targetOS.contains("windows") cpp.defines: ["WITH_SETUPAPI"] } Properties { condition: qbs.targetOS.contains("linux") cpp.defines: ["WITH_PTHREAD"] } Export { Depends { name: "cpp" } Properties { condition: qbs.targetOS.contains("linux") cpp.staticLibraries: ["pthread"] } Properties { condition: qbs.targetOS.contains("windows") cpp.staticLibraries: ["setupapi"] } } } StaticLibrary { name: "e" Depends { name: "cpp" } Depends { name: "d" } files: [ "e.cpp", ] } CppApplication { name: "staticLibDeps" type: "application" consoleApplication: true Depends { name: "e" } Properties { condition: qbs.targetOS.contains("linux") cpp.linkerFlags: ["-static"] } files: [ "main.cpp", ] } } qbs-src-1.4.5/tests/auto/api/testdata/subprojects/000077500000000000000000000000001266132464200221405ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/subprojects/resources/000077500000000000000000000000001266132464200241525ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/subprojects/resources/imports/000077500000000000000000000000001266132464200256475ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/subprojects/resources/imports/LibraryType/000077500000000000000000000000001266132464200301155ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/subprojects/resources/imports/LibraryType/type.js000066400000000000000000000000551266132464200314340ustar00rootroot00000000000000function type() { return "dynamiclibrary"; } qbs-src-1.4.5/tests/auto/api/testdata/subprojects/resources/modules/000077500000000000000000000000001266132464200256225ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/subprojects/resources/modules/QtCoreDepender/000077500000000000000000000000001266132464200304665ustar00rootroot00000000000000qtcoredepender.qbs000066400000000000000000000000671266132464200341250ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/subprojects/resources/modules/QtCoreDependerimport qbs Module { Depends { name: "Qt.core" } } qbs-src-1.4.5/tests/auto/api/testdata/subprojects/subproject1/000077500000000000000000000000001266132464200244015ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/subprojects/subproject1/main.cpp000066400000000000000000000000431266132464200260260ustar00rootroot00000000000000void f(); int main() { f(); } qbs-src-1.4.5/tests/auto/api/testdata/subprojects/subproject2/000077500000000000000000000000001266132464200244025ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/subprojects/subproject2/subproject2.qbs000066400000000000000000000005011266132464200273470ustar00rootroot00000000000000import qbs Project { name: "subproject2" property string libNamePrefix: "test" SubProject { filePath: "subproject3/subproject3.qbs" inheritProperties: true Properties { name: "overridden name" condition: true libNameSuffix: "Lib" } } } qbs-src-1.4.5/tests/auto/api/testdata/subprojects/subproject2/subproject3/000077500000000000000000000000001266132464200266455ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/subprojects/subproject2/subproject3/subproject3.qbs000066400000000000000000000006421266132464200316210ustar00rootroot00000000000000import qbs import LibraryType Project { condition: false property string libNameSuffix: "blubb" Product { name: project.libNamePrefix + project.libNameSuffix type: LibraryType.type() Depends { name: "cpp" } Depends { name: "QtCoreDepender" } cpp.defines: "MY_EXPORT=Q_DECL_EXPORT" files: "testlib.cpp" Export { Depends { name: "Qt.core" } } } } qbs-src-1.4.5/tests/auto/api/testdata/subprojects/subproject2/subproject3/testlib.cpp000066400000000000000000000000531266132464200310150ustar00rootroot00000000000000#include MY_EXPORT void f() {} qbs-src-1.4.5/tests/auto/api/testdata/subprojects/toplevelproject.qbs000066400000000000000000000005651266132464200260760ustar00rootroot00000000000000import qbs Project { name: "top level project" references: ["subproject2"] Project { condition: true name: "app-project" CppApplication { name: "app" Depends { name: "testLib" } cpp.defines: "MY_EXPORT=" files: "subproject1/main.cpp" } } qbsSearchPaths: ["resources"] } qbs-src-1.4.5/tests/auto/api/testdata/transformers/000077500000000000000000000000001266132464200223225ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/transformers/main.cpp000066400000000000000000000050301266132464200237500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #include #include using namespace std; bool displayTextFile(const string &dirPath, const string &fileName) { string fullPath = dirPath + fileName; ifstream istream(fullPath.c_str()); if (!istream.is_open()) { cout << "Cannot open " << fileName << endl; return false; } cout << "---" << fileName << "---" << endl; char buf[256]; unsigned int i = 1; while (istream.good()) { istream.getline(buf, sizeof(buf)); cout << i++ << ": " << buf << endl; } return true; } int main(int, char **argv) { string appPath(argv[0]); size_t i = appPath.find_last_of('/'); if (i == string::npos) i = appPath.find_last_of('\\'); if (i == string::npos) // No path, plain executable was called appPath.clear(); else appPath.resize(i + 1); if (!displayTextFile(appPath, "foo.txt")) return 1; if (!displayTextFile(appPath, "bar.txt")) return 2; cout << "-------------" << endl; return 0; } qbs-src-1.4.5/tests/auto/api/testdata/transformers/transformers.qbs000066400000000000000000000055411266132464200255630ustar00rootroot00000000000000import qbs 1.0 import qbs.File import qbs.TextFile import qbs.Xml import qbs.FileInfo Project { Product { name: "HelloWorld" type: "application" consoleApplication: true files: ["main.cpp"] Depends { name: "cpp" } Transformer { // no inputs -> just a generator Artifact { filePath: "foo.txt" fileTags: "text" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating foo.txt"; cmd.highlight = "linker"; cmd.sourceCode = function () { File.remove(output.filePath); var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write("Dear Sir/Madam,\n\n"); f.write("this is a generated file.\n\n\n"); f.write("Best Regards and Mellow Greetings,\nYour Build Tool.\n"); f.close(); } return cmd; } } Transformer { // no inputs -> just a generator Artifact { filePath: "foo.xml" fileTags: "xml" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating foo.xml"; cmd.highlight = "linker"; cmd.sourceCode = function () { File.remove(output.filePath); var doc = new XmlDomDocument(); var root = doc.createElement("root"); doc.appendChild(root); var tag = doc.createElement("Greeting"); root.appendChild(tag); tag.appendChild(doc.createTextNode("text node")); doc.save(output.filePath); } return cmd; } } Transformer { inputs: ["main.cpp"] // will be taken from the source dir Artifact { filePath: "bar.txt" fileTags: "text" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating bar.txt"; cmd.highlight = "linker"; cmd.inputFileName = input.filePath; cmd.sourceCode = function() { File.remove(output.filePath); var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write("Dear Sir/Madam,\n\n"); f.write("this file was generated from " + inputFileName + ".\n\n\n"); f.write("Best Regards and Mellow Greetings,\nYour Build Tool.\n"); f.close(); } return cmd; } } } } qbs-src-1.4.5/tests/auto/api/testdata/two-default-property-values/000077500000000000000000000000001266132464200252075ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/two-default-property-values/modules/000077500000000000000000000000001266132464200266575ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/two-default-property-values/modules/mymodule/000077500000000000000000000000001266132464200305125ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/two-default-property-values/modules/mymodule/mymodule.qbs000066400000000000000000000011561266132464200330570ustar00rootroot00000000000000import qbs import qbs.TextFile Module { property string direct property string indirect: direct ? "set" : "unset" Rule { inputs: ["txt"] Artifact { filePath: product.moduleProperty("mymodule", "indirect") fileTags: ["mymodule"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); }; return [cmd]; } } } qbs-src-1.4.5/tests/auto/api/testdata/two-default-property-values/modules/myothermodule/000077500000000000000000000000001266132464200315545ustar00rootroot00000000000000myothermodule.qbs000066400000000000000000000000701266132464200350760ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/two-default-property-values/modules/myothermoduleimport qbs Module { Depends { name: "mymodule" } } qbs-src-1.4.5/tests/auto/api/testdata/two-default-property-values/project.qbs000066400000000000000000000004011266132464200273570ustar00rootroot00000000000000import qbs Product { name: "two-default-property-values" type: "mymodule" Depends { name: "mymodule" } Depends { name: "myothermodule" } mymodule.direct: "dummy" Group { files: ["test.txt"] fileTags: ["txt"] } } qbs-src-1.4.5/tests/auto/api/testdata/two-default-property-values/test.txt000066400000000000000000000000001266132464200267150ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/type-change/000077500000000000000000000000001266132464200220015ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/type-change/main.cpp000066400000000000000000000000161266132464200234260ustar00rootroot00000000000000int main() {} qbs-src-1.4.5/tests/auto/api/testdata/type-change/project.qbs000066400000000000000000000001451266132464200241560ustar00rootroot00000000000000import qbs Product { files: "main.cpp" Depends { name: "cpp" } // type: "application" } qbs-src-1.4.5/tests/auto/api/testdata/uic/000077500000000000000000000000001266132464200203555ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/api/testdata/uic/bla.cpp000066400000000000000000000031231266132464200216160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "bla.h" int main() { Ui::MainWindow mainWindow; Q_UNUSED(mainWindow); } qbs-src-1.4.5/tests/auto/api/testdata/uic/bla.h000066400000000000000000000030101266132464200212560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "ui.h" qbs-src-1.4.5/tests/auto/api/testdata/uic/ui.h000066400000000000000000000030131266132464200211400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "ui_ui.h" qbs-src-1.4.5/tests/auto/api/testdata/uic/ui.ui000066400000000000000000000012641266132464200213340ustar00rootroot00000000000000 MainWindow 0 0 800 600 MainWindow 0 0 800 25 qbs-src-1.4.5/tests/auto/api/testdata/uic/uic.qbs000066400000000000000000000003711266132464200216450ustar00rootroot00000000000000import qbs 1.0 Project { QtGuiApplication { type: "application" consoleApplication: true name: "ui" files: [ "bla.cpp", "bla.h", "ui.ui", "ui.h" ] } } qbs-src-1.4.5/tests/auto/api/tst_api.cpp000066400000000000000000002216341266132464200201430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "tst_api.h" #include "../shared.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define VERIFY_NO_ERROR(errorInfo) \ QVERIFY2(!errorInfo.hasError(), qPrintable(errorInfo.toString())) #define WAIT_FOR_NEW_TIMESTAMP() waitForNewTimestamp(m_workingDataDir) class LogSink: public qbs::ILogSink { public: QString output; void doPrintWarning(const qbs::ErrorInfo &error) { qDebug("%s", qPrintable(error.toString())); } void doPrintMessage(qbs::LoggerLevel, const QString &message, const QString &) { output += message; } }; class BuildDescriptionReceiver : public QObject { Q_OBJECT public: QString descriptions; private slots: void handleDescription(const QString &, const QString &description) { descriptions += description; } }; class ProcessResultReceiver : public QObject { Q_OBJECT public: QString output; private slots: void handleProcessResult(const qbs::ProcessResult &result) { output += result.stdErr().join(QLatin1Char('\n')); output += result.stdOut().join(QLatin1Char('\n')); } }; class TaskReceiver : public QObject { Q_OBJECT public: QString taskDescriptions; private slots: void handleTaskStart(const QString &task) { taskDescriptions += task; } }; static void removeBuildDir(const qbs::SetupProjectParameters ¶ms) { QString message; const QString dir = params.buildRoot() + '/' + params.topLevelProfile() + '-' + params.buildVariant(); if (!qbs::Internal::removeDirectoryWithContents(dir, &message)) qFatal("Could not remove build dir: %s", qPrintable(message)); } static bool waitForFinished(qbs::AbstractJob *job, int timeout = 0) { if (job->state() == qbs::AbstractJob::StateFinished) return true; QEventLoop loop; QObject::connect(job, SIGNAL(finished(bool,qbs::AbstractJob*)), &loop, SLOT(quit())); if (timeout > 0) { QTimer timer; QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); timer.setSingleShot(true); timer.start(timeout); loop.exec(); return timer.isActive(); // Timer ended the loop <=> job did not finish. } loop.exec(); return true; } TestApi::TestApi() : m_logSink(new LogSink) , m_sourceDataDir(QDir::cleanPath(SRCDIR "/testdata")) , m_workingDataDir(testWorkDir(QStringLiteral("api"))) { } TestApi::~TestApi() { delete m_logSink; } void TestApi::initTestCase() { QString errorMessage; qbs::Internal::removeDirectoryWithContents(m_workingDataDir, &errorMessage); QVERIFY2(qbs::Internal::copyFileRecursion(m_sourceDataDir, m_workingDataDir, false, &errorMessage), qPrintable(errorMessage)); } void TestApi::addQObjectMacroToCppFile() { BuildDescriptionReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("add-qobject-macro-to-cpp-file/project.qbs", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(!receiver.descriptions.contains("moc"), qPrintable(receiver.descriptions)); receiver.descriptions.clear(); WAIT_FOR_NEW_TIMESTAMP(); QFile cppFile("object.cpp"); QVERIFY2(cppFile.open(QIODevice::ReadWrite), qPrintable(cppFile.errorString())); QByteArray contents = cppFile.readAll(); contents.replace("// ", ""); cppFile.resize(0); cppFile.write(contents); cppFile.close(); errorInfo = doBuildProject("add-qobject-macro-to-cpp-file/project.qbs", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(receiver.descriptions.contains("moc"), qPrintable(receiver.descriptions)); } static bool isAboutUndefinedSymbols(const QString &_message) { const QString message = _message.toLower(); return message.contains("undefined") || message.contains("unresolved"); } void TestApi::addedFilePersistent() { // On the initial run, linking will fail. const QString relProjectFilePath = "added-file-persistent/project.qbs"; ProcessResultReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject(relProjectFilePath, 0, &receiver); QVERIFY(errorInfo.hasError()); QVERIFY2(isAboutUndefinedSymbols(receiver.output), qPrintable((receiver.output))); receiver.output.clear(); // Add a file. qbs must schedule it for rule application on the next build. WAIT_FOR_NEW_TIMESTAMP(); const qbs::SetupProjectParameters params = defaultSetupParameters(relProjectFilePath); QFile projectFile(params.projectFilePath()); QVERIFY2(projectFile.open(QIODevice::ReadWrite), qPrintable(projectFile.errorString())); const QByteArray originalContent = projectFile.readAll(); QByteArray addedFileContent = originalContent; addedFileContent.replace("/* 'file.cpp' */", "'file.cpp'"); projectFile.resize(0); projectFile.write(addedFileContent); projectFile.flush(); QScopedPointer setupJob(qbs::Project().setupProject(params, m_logSink, 0)); waitForFinished(setupJob.data()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); setupJob.reset(0); // Remove the file again. qbs must unschedule the rule application again. // Consequently, the linking step must fail as in the initial run. WAIT_FOR_NEW_TIMESTAMP(); projectFile.resize(0); projectFile.write(originalContent); projectFile.flush(); errorInfo = doBuildProject(relProjectFilePath, 0, &receiver); QVERIFY(errorInfo.hasError()); QVERIFY2(isAboutUndefinedSymbols(receiver.output), qPrintable((receiver.output))); // Add the file again. qbs must schedule it for rule application on the next build. WAIT_FOR_NEW_TIMESTAMP(); projectFile.resize(0); projectFile.write(addedFileContent); projectFile.close(); setupJob.reset(qbs::Project().setupProject(params, m_logSink, 0)); waitForFinished(setupJob.data()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); setupJob.reset(0); // qbs must remember that a file was scheduled for rule application. The build must then // succeed, as now all necessary symbols are linked in. errorInfo = doBuildProject(relProjectFilePath); VERIFY_NO_ERROR(errorInfo); } void TestApi::baseProperties() { const qbs::ErrorInfo errorInfo = doBuildProject("base-properties/prj.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::buildGraphLocking() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("buildgraph-locking/project.qbs"); QScopedPointer setupJob(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.data()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); const qbs::Project project = setupJob->project(); Q_UNUSED(project); setupJob.reset(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.data()); QVERIFY(setupJob->error().hasError()); QVERIFY2(setupJob->error().toString().contains("lock"), qPrintable(setupJob->error().toString())); } void TestApi::buildProject() { QFETCH(QString, projectSubDir); QFETCH(QString, productFileName); qbs::SetupProjectParameters params = defaultSetupParameters(projectSubDir + "/project.qbs"); removeBuildDir(params); qbs::ErrorInfo errorInfo = doBuildProject(projectSubDir + "/project.qbs"); VERIFY_NO_ERROR(errorInfo); QVERIFY(regularFileExists(relativeBuildGraphFilePath())); if (!productFileName.isEmpty()) { QVERIFY2(regularFileExists(productFileName), qPrintable(productFileName)); QVERIFY2(QFile::remove(productFileName), qPrintable(productFileName)); } WAIT_FOR_NEW_TIMESTAMP(); qbs::BuildOptions options; options.setForceTimestampCheck(true); errorInfo = doBuildProject(projectSubDir + "/project.qbs", 0, 0, 0, options); VERIFY_NO_ERROR(errorInfo); if (!productFileName.isEmpty()) QVERIFY2(regularFileExists(productFileName), qPrintable(productFileName)); QVERIFY(regularFileExists(relativeBuildGraphFilePath())); } void TestApi::buildProject_data() { QTest::addColumn("projectSubDir"); QTest::addColumn("productFileName"); QTest::newRow("BPs in Sources") << QString("build-properties-source") << relativeExecutableFilePath("HelloWorld"); QTest::newRow("code generator") << QString("codegen") << relativeExecutableFilePath("codegen"); QTest::newRow("link static libs") << QString("link-static-lib") << relativeExecutableFilePath("HelloWorld"); QTest::newRow("precompiled header") << QString("precompiled-header") << relativeExecutableFilePath("MyApp"); QTest::newRow("lots of dots") << QString("lots-of-dots") << relativeExecutableFilePath("lots.of.dots"); QTest::newRow("Qt5 plugin") << QString("qt5-plugin") << relativeProductBuildDir("echoplugin") + '/' + qbs::Internal::HostOsInfo::dynamicLibraryName("echoplugin"); QTest::newRow("Q_OBJECT in source") << QString("moc-cpp") << relativeExecutableFilePath("moc_cpp"); QTest::newRow("Q_OBJECT in header") << QString("moc-hpp") << relativeExecutableFilePath("moc_hpp"); QTest::newRow("Q_OBJECT in header, moc_XXX.cpp included") << QString("moc-hpp-included") << relativeExecutableFilePath("moc_hpp_included"); QTest::newRow("app and lib with same source file") << QString("lib-same-source") << relativeExecutableFilePath("HelloWorldApp"); QTest::newRow("source files with the same base name but different extensions") << QString("same-base-name") << relativeExecutableFilePath("basename"); QTest::newRow("static library dependencies") << QString("static-lib-deps") << relativeExecutableFilePath("staticLibDeps"); QTest::newRow("simple probes") << QString("simple-probe") << relativeExecutableFilePath("MyApp"); QTest::newRow("application without sources") << QString("app-without-sources") << relativeExecutableFilePath("appWithoutSources"); QTest::newRow("productNameWithDots") << QString("productNameWithDots") << relativeExecutableFilePath("myapp"); QTest::newRow("only default properties") << QString("two-default-property-values") << relativeProductBuildDir("two-default-property-values") + "/set"; QTest::newRow("Export item with Group") << QString("export-item-with-group") << relativeExecutableFilePath("app"); QTest::newRow("QBS-728") << QString("QBS-728") << QString(); } void TestApi::buildProjectDryRun() { QFETCH(QString, projectSubDir); QFETCH(QString, productFileName); qbs::SetupProjectParameters params = defaultSetupParameters(projectSubDir + "/project.qbs"); removeBuildDir(params); qbs::BuildOptions options; options.setDryRun(true); const qbs::ErrorInfo errorInfo = doBuildProject(projectSubDir + "/project.qbs", 0, 0, 0, options); VERIFY_NO_ERROR(errorInfo); QVERIFY2(!QFileInfo::exists(relativeBuildDir()), qPrintable(QDir(relativeBuildDir()) .entryList(QDir::NoDotAndDotDot | QDir::AllEntries | QDir::System).join(", "))); } void TestApi::buildProjectDryRun_data() { return buildProject_data(); } void TestApi::buildSingleFile() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("build-single-file/project.qbs"); QScopedPointer setupJob(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.data()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); qbs::BuildOptions options; options.setDryRun(true); options.setFilesToConsider(QStringList(setupParams.buildRoot() + "/compiled.cpp")); options.setActiveFileTags(QStringList("obj")); m_logSink->setLogLevel(qbs::LoggerMaxLevel); QScopedPointer buildJob(project.buildAllProducts(options)); BuildDescriptionReceiver receiver; connect(buildJob.data(), SIGNAL(reportCommandDescription(QString,QString)), &receiver, SLOT(handleDescription(QString,QString))); waitForFinished(buildJob.data()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); QCOMPARE(receiver.descriptions.count("compiling"), 1); QVERIFY2(receiver.descriptions.contains("compiling compiled.cpp"), qPrintable(receiver.descriptions)); } qbs::GroupData findGroup(const qbs::ProductData &product, const QString &name) { foreach (const qbs::GroupData &g, product.groups()) { if (g.name() == name) return g; } return qbs::GroupData(); } #ifdef QBS_ENABLE_PROJECT_FILE_UPDATES static qbs::Project::ProductSelection defaultProducts() { return qbs::Project::ProductSelectionDefaultOnly; } static void printProjectData(const qbs::ProjectData &project) { foreach (const qbs::ProductData &p, project.products()) { qDebug(" Product '%s' at %s", qPrintable(p.name()), qPrintable(p.location().toString())); foreach (const qbs::GroupData &g, p.groups()) { qDebug(" Group '%s' at %s", qPrintable(g.name()), qPrintable(g.location().toString())); qDebug(" Files: %s", qPrintable(g.allFilePaths().join(QLatin1String(", ")))); } } } void TestApi::changeContent() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("project-editing/project.qbs"); QScopedPointer job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.data()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); qbs::Project project = job->project(); qbs::ProjectData projectData = project.projectData(); QCOMPARE(projectData.allProducts().count(), 1); qbs::ProductData product = projectData.allProducts().first(); QCOMPARE(product.groups().count(), 8); // Error handling: Invalid product. qbs::ErrorInfo errorInfo = project.addGroup(qbs::ProductData(), "blubb"); QVERIFY(errorInfo.hasError()); QVERIFY(errorInfo.toString().contains("invalid")); // Error handling: Empty group name. errorInfo = project.addGroup(product, QString()); QVERIFY(errorInfo.hasError()); QVERIFY(errorInfo.toString().contains("empty")); errorInfo = project.addGroup(product, "New Group 1"); VERIFY_NO_ERROR(errorInfo); errorInfo = project.addGroup(product, "New Group 2"); VERIFY_NO_ERROR(errorInfo); // Error handling: Group already inserted. errorInfo = project.addGroup(product, "New Group 1"); QVERIFY(errorInfo.hasError()); QVERIFY(errorInfo.toString().contains("already")); // Error handling: Add list of files with double entries. errorInfo = project.addFiles(product, qbs::GroupData(), QStringList() << "file.cpp" << "file.cpp"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("more than once"), qPrintable(errorInfo.toString())); // Add files to empty array literal. projectData = project.projectData(); QVERIFY(projectData.products().count() == 1); product = projectData.products().first(); QCOMPARE(product.groups().count(), 10); qbs::GroupData group = findGroup(product, "New Group 1"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "file.h" << "file.cpp"); VERIFY_NO_ERROR(errorInfo); // Error handling: Add the same file again. projectData = project.projectData(); QVERIFY(projectData.products().count() == 1); product = projectData.products().first(); QCOMPARE(product.groups().count(), 10); group = findGroup(product, "New Group 1"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "file.cpp"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("already"), qPrintable(errorInfo.toString())); // Remove one of the newly added files again. errorInfo = project.removeFiles(product, group, QStringList("file.h")); VERIFY_NO_ERROR(errorInfo); // Error handling: Try to remove the same file again. projectData = project.projectData(); QVERIFY(projectData.products().count() == 1); product = projectData.products().first(); QCOMPARE(product.groups().count(), 10); group = findGroup(product, "New Group 1"); QVERIFY(group.isValid()); errorInfo = project.removeFiles(product, group, QStringList() << "file.h"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("not known"), qPrintable(errorInfo.toString())); // Error handling: Try to remove a file from a complex list. group = findGroup(product, "Existing Group 2"); QVERIFY(group.isValid()); errorInfo = project.removeFiles(product, group, QStringList() << "existingfile2.txt"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("complex"), qPrintable(errorInfo.toString())); // Remove file from product's 'files' binding. errorInfo = project.removeFiles(product, qbs::GroupData(), QStringList("main.cpp")); VERIFY_NO_ERROR(errorInfo); // Add file to non-empty array literal. projectData = project.projectData(); QVERIFY(projectData.products().count() == 1); product = projectData.products().first(); group = findGroup(product, "Existing Group 1"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "newfile1.txt"); VERIFY_NO_ERROR(errorInfo); // Add files to list represented as a single string. projectData = project.projectData(); QVERIFY(projectData.products().count() == 1); product = projectData.products().first(); errorInfo = project.addFiles(product, qbs::GroupData(), QStringList() << "newfile2.txt"); VERIFY_NO_ERROR(errorInfo); // Add files to list represented as an identifier. projectData = project.projectData(); QVERIFY(projectData.products().count() == 1); product = projectData.products().first(); group = findGroup(product, "Existing Group 2"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "newfile3.txt"); VERIFY_NO_ERROR(errorInfo); // Add files to list represented as a block of code (not yet implemented). projectData = project.projectData(); QVERIFY(projectData.products().count() == 1); product = projectData.products().first(); group = findGroup(product, "Existing Group 3"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "newfile4.txt"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("complex"), qPrintable(errorInfo.toString())); // Add file to group with directory prefix. projectData = project.projectData(); QVERIFY(projectData.products().count() == 1); product = projectData.products().first(); group = findGroup(product, "Existing Group 4"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "file.txt"); VERIFY_NO_ERROR(errorInfo); // Error handling: Add file to group with non-directory prefix. projectData = project.projectData(); QVERIFY(projectData.products().count() == 1); product = projectData.products().first(); group = findGroup(product, "Existing Group 5"); QVERIFY(group.isValid()); errorInfo = project.addFiles(product, group, QStringList() << "newfile1.txt"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("prefix"), qPrintable(errorInfo.toString())); // Remove group. projectData = project.projectData(); QVERIFY(projectData.products().count() == 1); product = projectData.products().first(); group = findGroup(product, "Existing Group 5"); QVERIFY(group.isValid()); errorInfo = project.removeGroup(product, group); VERIFY_NO_ERROR(errorInfo); projectData = project.projectData(); QVERIFY(projectData.products().count() == 1); QCOMPARE(projectData.products().first().groups().count(), 9); // Error handling: Try to remove the same group again. errorInfo = project.removeGroup(product, group); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("does not exist"), qPrintable(errorInfo.toString())); // Add a file to a group where the file name is already matched by a wildcard. projectData = project.projectData(); QVERIFY(projectData.products().count() == 1); product = projectData.products().first(); group = findGroup(product, "Group with wildcards"); QVERIFY(group.isValid()); QFile newFile("koerper.klaus"); QVERIFY2(newFile.open(QIODevice::WriteOnly), qPrintable(newFile.errorString())); newFile.close(); errorInfo = project.addFiles(product, group, QStringList() << newFile.fileName()); VERIFY_NO_ERROR(errorInfo); projectData = project.projectData(); QVERIFY(projectData.products().count() == 1); product = projectData.products().first(); group = findGroup(product, "Group with wildcards"); QVERIFY(group.isValid()); QCOMPARE(group.sourceArtifactsFromWildcards().count(), 1); QCOMPARE(group.sourceArtifactsFromWildcards().first().filePath(), QFileInfo(newFile).absoluteFilePath()); // Error checking: Try to remove a file that originates from a wildcard pattern. projectData = project.projectData(); QVERIFY(projectData.products().count() == 1); product = projectData.products().first(); group = findGroup(product, "Other group with wildcards"); QVERIFY(group.isValid()); errorInfo = project.removeFiles(product, group, QStringList() << "test.wildcard"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("pattern"), qPrintable(errorInfo.toString())); // Check whether building will take the added and removed cpp files into account. // This must not be moved below the re-resolving test!!! qbs::BuildOptions buildOptions; buildOptions.setDryRun(true); BuildDescriptionReceiver rcvr; QScopedPointer buildJob(project.buildAllProducts(buildOptions, defaultProducts(), this)); connect(buildJob.data(), SIGNAL(reportCommandDescription(QString,QString)), &rcvr, SLOT(handleDescription(QString,QString))); waitForFinished(buildJob.data()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); QVERIFY(rcvr.descriptions.contains("compiling file.cpp")); QVERIFY(!rcvr.descriptions.contains("compiling main.cpp")); // Now check whether the data updates were done correctly. projectData = project.projectData(); job.reset(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(job.data()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); project = job->project(); qbs::ProjectData newProjectData = project.projectData(); // Can't use Project::operator== here, as the target artifacts will differ due to the build // not having run yet. bool projectDataMatches = newProjectData.products().count() == 1 && projectData.products().count() == 1 && newProjectData.products().first().groups() == projectData.products().first().groups(); if (!projectDataMatches) { qDebug("This is the assumed project:"); printProjectData(projectData); qDebug("This is the actual project:"); printProjectData(newProjectData); } QVERIFY(projectDataMatches); // Will fail if e.g. code locations don't match. // Now try building again and check if the newly resolved product behaves the same way. buildJob.reset(project.buildAllProducts(buildOptions, defaultProducts(), this)); connect(buildJob.data(), SIGNAL(reportCommandDescription(QString,QString)), &rcvr, SLOT(handleDescription(QString,QString))); waitForFinished(buildJob.data()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); QVERIFY(rcvr.descriptions.contains("compiling file.cpp")); QVERIFY(!rcvr.descriptions.contains("compiling main.cpp")); // Now, after the build, the project data must be entirely identical. QVERIFY(projectData == project.projectData()); // Error handling: Try to change the project during a build. buildJob.reset(project.buildAllProducts(buildOptions, defaultProducts(), this)); errorInfo = project.addGroup(newProjectData.products().first(), "blubb"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("in process"), qPrintable(errorInfo.toString())); waitForFinished(buildJob.data()); errorInfo = project.addGroup(newProjectData.products().first(), "blubb"); VERIFY_NO_ERROR(errorInfo); project = qbs::Project(); job.reset(0); buildJob.reset(0); removeBuildDir(setupParams); // Add a file to the top level of a product that does not have a "files" binding yet. setupParams.setProjectFilePath(QDir::cleanPath(m_workingDataDir + "/project-editing/project-with-no-files.qbs")); job.reset(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(job.data()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); project = job->project(); projectData = project.projectData(); QCOMPARE(projectData.allProducts().count(), 1); product = projectData.allProducts().first(); errorInfo = project.addFiles(product, qbs::GroupData(), QStringList("main.cpp")); VERIFY_NO_ERROR(errorInfo); projectData = project.projectData(); rcvr.descriptions.clear(); buildJob.reset(project.buildAllProducts(buildOptions, defaultProducts(), this)); connect(buildJob.data(), SIGNAL(reportCommandDescription(QString,QString)), &rcvr, SLOT(handleDescription(QString,QString))); waitForFinished(buildJob.data()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); QVERIFY(rcvr.descriptions.contains("compiling main.cpp")); job.reset(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(job.data()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); // Can't use Project::operator== here, as the target artifacts will differ due to the build // not having run yet. newProjectData = job->project().projectData(); projectDataMatches = newProjectData.products().count() == 1 && projectData.products().count() == 1 && newProjectData.products().first().groups() == projectData.products().first().groups(); if (!projectDataMatches) { printProjectData(projectData); qDebug("\n====\n"); printProjectData(newProjectData); } QVERIFY(projectDataMatches); } #endif // QBS_ENABLE_PROJECT_FILE_UPDATES void TestApi::commandExtraction() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("/command-extraction/project.qbs"); QScopedPointer setupJob(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.data()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); qbs::ProjectData projectData = project.projectData(); QCOMPARE(projectData.allProducts().count(), 1); qbs::ProductData productData = projectData.allProducts().first(); qbs::ErrorInfo errorInfo; const QString projectDirPath = QDir::cleanPath(QFileInfo(setupParams.projectFilePath()).path()); const QString sourceFilePath = projectDirPath + "/main.cpp"; // Before the first build, no rules exist. qbs::RuleCommandList commands = project.ruleCommands(productData, sourceFilePath, "obj", &errorInfo); QCOMPARE(commands.count(), 0); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("No rule"), qPrintable(errorInfo.toString())); qbs::BuildOptions options; options.setDryRun(true); QScopedPointer buildJob(project.buildAllProducts(options)); waitForFinished(buildJob.data()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); projectData = project.projectData(); QCOMPARE(projectData.allProducts().count(), 1); productData = projectData.allProducts().first(); errorInfo = qbs::ErrorInfo(); // After the build, the compile command must be found. commands = project.ruleCommands(productData, sourceFilePath, "obj", &errorInfo); QCOMPARE(commands.count(), 1); QVERIFY2(!errorInfo.hasError(), qPrintable(errorInfo.toString())); const qbs::RuleCommand command = commands.first(); QCOMPARE(command.type(), qbs::RuleCommand::ProcessCommandType); QVERIFY(!command.executable().isEmpty()); QVERIFY(!command.arguments().isEmpty()); } void TestApi::changeDependentLib() { qbs::ErrorInfo errorInfo = doBuildProject("change-dependent-lib/change-dependent-lib.qbs"); VERIFY_NO_ERROR(errorInfo); WAIT_FOR_NEW_TIMESTAMP(); const QString qbsFileName("change-dependent-lib.qbs"); QFile qbsFile(qbsFileName); QVERIFY(qbsFile.open(QIODevice::ReadWrite)); const QByteArray content1 = qbsFile.readAll(); QByteArray content2 = content1; content2.replace("cpp.defines: [\"XXXX\"]", "cpp.defines: [\"ABCD\"]"); QVERIFY(content1 != content2); qbsFile.seek(0); qbsFile.write(content2); qbsFile.close(); errorInfo = doBuildProject("change-dependent-lib/change-dependent-lib.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::enableAndDisableProduct() { BuildDescriptionReceiver bdr; qbs::ErrorInfo errorInfo = doBuildProject("enable-and-disable-product/project.qbs", &bdr); VERIFY_NO_ERROR(errorInfo); QVERIFY(!bdr.descriptions.contains("compiling")); WAIT_FOR_NEW_TIMESTAMP(); QFile projectFile("project.qbs"); QVERIFY(projectFile.open(QIODevice::ReadWrite)); QByteArray content = projectFile.readAll(); content.replace("undefined", "'hidden'"); projectFile.resize(0); projectFile.write(content); projectFile.close(); bdr.descriptions.clear(); errorInfo = doBuildProject("enable-and-disable-product/project.qbs", &bdr); VERIFY_NO_ERROR(errorInfo); QVERIFY(bdr.descriptions.contains("linking")); WAIT_FOR_NEW_TIMESTAMP(); touch("main.cpp"); QVERIFY(projectFile.open(QIODevice::ReadWrite)); content = projectFile.readAll(); content.replace("'hidden'", "undefined"); projectFile.resize(0); projectFile.write(content); projectFile.close(); bdr.descriptions.clear(); errorInfo = doBuildProject("enable-and-disable-product/project.qbs", &bdr); VERIFY_NO_ERROR(errorInfo); QVERIFY(!bdr.descriptions.contains("compiling")); } static qbs::ErrorInfo forceRuleEvaluation(const qbs::Project project) { qbs::BuildOptions buildOptions; buildOptions.setDryRun(true); QScopedPointer buildJob(project.buildAllProducts(buildOptions)); waitForFinished(buildJob.data()); return buildJob->error(); } void TestApi::disabledInstallGroup() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("disabled_install_group/project.qbs"); QScopedPointer job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.data()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); const qbs::Project project = job->project(); const qbs::ErrorInfo errorInfo = forceRuleEvaluation(project); VERIFY_NO_ERROR(errorInfo); qbs::ProjectData projectData = project.projectData(); QCOMPARE(projectData.allProducts().count(), 1); qbs::ProductData product = projectData.allProducts().first(); const QList targets = product.targetArtifacts(); QCOMPARE(targets.count(), 1); QVERIFY(targets.first().isExecutable()); QList installableFiles = project.installableFilesForProduct(product, qbs::InstallOptions()); QCOMPARE(installableFiles.count(), 0); QCOMPARE(project.targetExecutable(product, qbs::InstallOptions()), targets.first().filePath()); } void TestApi::disabledProduct() { const qbs::ErrorInfo errorInfo = doBuildProject("disabled-product/disabledProduct.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::disabledProject() { const qbs::ErrorInfo errorInfo = doBuildProject("disabled-project/disabled_project.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::duplicateProductNames() { QFETCH(QString, projectFileName); const qbs::ErrorInfo errorInfo = doBuildProject("duplicate-product-names/" + projectFileName); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("Duplicate product name"), qPrintable(errorInfo.toString())); } void TestApi::duplicateProductNames_data() { QTest::addColumn("projectFileName"); QTest::newRow("Names explicitly set") << QString("explicit.qbs"); QTest::newRow("Unnamed products in same file") << QString("implicit.qbs"); QTest::newRow("Unnamed products in files of the same name") << QString("implicit-indirect.qbs"); } void TestApi::dynamicLibs() { const qbs::ErrorInfo errorInfo = doBuildProject("dynamic-libs/link_dynamiclib.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::emptyFileTagList() { const qbs::ErrorInfo errorInfo = doBuildProject("empty-filetag-list/project.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::emptySubmodulesList() { const qbs::ErrorInfo errorInfo = doBuildProject("empty-submodules-list/project.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::explicitlyDependsOn() { BuildDescriptionReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("explicitly-depends-on/project.qbs", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(receiver.descriptions.contains("Creating output artifact")); receiver.descriptions.clear(); errorInfo = doBuildProject("explicitly-depends-on/project.qbs", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(!receiver.descriptions.contains("Creating output artifact")); WAIT_FOR_NEW_TIMESTAMP(); touch("dependency.txt"); errorInfo = doBuildProject("explicitly-depends-on/project.qbs", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(receiver.descriptions.contains("Creating output artifact")); } void TestApi::exportSimple() { const qbs::ErrorInfo errorInfo = doBuildProject("export-simple/project.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::exportWithRecursiveDepends() { const qbs::ErrorInfo errorInfo = doBuildProject("export-with-recursive-depends/project.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::fileTagger() { BuildDescriptionReceiver receiver; const qbs::ErrorInfo errorInfo = doBuildProject("file-tagger/moc_cpp.qbs", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(receiver.descriptions.contains("moc bla.cpp"), qPrintable(receiver.descriptions)); } void TestApi::fileTagsFilterOverride() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("filetagsfilter_override/project.qbs"); QScopedPointer job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.data()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); qbs::Project project = job->project(); const qbs::ErrorInfo errorInfo = forceRuleEvaluation(project); VERIFY_NO_ERROR(errorInfo); qbs::ProjectData projectData = project.projectData(); QCOMPARE(projectData.allProducts().count(), 1); const qbs::ProductData product = projectData.allProducts().first(); QList installableFiles = project.installableFilesForProduct(product, qbs::InstallOptions()); QCOMPARE(installableFiles.count(), 1); QVERIFY(installableFiles.first().targetFilePath().contains("habicht")); } void TestApi::infiniteLoopBuilding() { QFETCH(QString, projectDirName); qbs::SetupProjectParameters setupParams = defaultSetupParameters(projectDirName + "/infinite-loop.qbs"); QScopedPointer setupJob(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.data()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); const QScopedPointer buildJob(project.buildAllProducts(qbs::BuildOptions())); QTimer::singleShot(1000, buildJob.data(), SLOT(cancel())); QVERIFY(waitForFinished(buildJob.data(), 600000)); } void TestApi::infiniteLoopBuilding_data() { QTest::addColumn("projectDirName"); QTest::newRow("JS Command") << QString("infinite-loop-js"); QTest::newRow("Process Command") << QString("infinite-loop-process"); } void TestApi::infiniteLoopResolving() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("infinite-loop-resolving/project.qbs"); QScopedPointer setupJob(qbs::Project().setupProject(setupParams, m_logSink, 0)); QTimer::singleShot(1000, setupJob.data(), SLOT(cancel())); QVERIFY(waitForFinished(setupJob.data(), 600000)); QVERIFY2(setupJob->error().toString().toLower().contains("cancel"), qPrintable(setupJob->error().toString())); } void TestApi::inheritQbsSearchPaths() { const QString projectFilePath = "inherit-qbs-search-paths/prj.qbs"; qbs::ErrorInfo errorInfo = doBuildProject(projectFilePath); VERIFY_NO_ERROR(errorInfo); WAIT_FOR_NEW_TIMESTAMP(); QFile projectFile(m_workingDataDir + '/' + projectFilePath); QVERIFY(projectFile.open(QIODevice::ReadWrite)); QByteArray content = projectFile.readAll(); content.replace("qbsSearchPaths: \"subdir\"", "//qbsSearchPaths: \"subdir\""); projectFile.resize(0); projectFile.write(content); projectFile.close(); errorInfo = doBuildProject(projectFilePath); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("Product dependency 'bli' not found"), qPrintable(errorInfo.toString())); QVariantMap overriddenValues; overriddenValues.insert("project.qbsSearchPaths", QStringList() << "subdir"); errorInfo = doBuildProject(projectFilePath, 0, 0, 0, qbs::BuildOptions(), overriddenValues); VERIFY_NO_ERROR(errorInfo); } template T findElem(const QList &list, Pred p) { const auto it = std::find_if(list.constBegin(), list.constEnd(), p); return it == list.constEnd() ? T() : *it; } void TestApi::installableFiles() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("installed-artifact/installed_artifact.qbs"); QScopedPointer job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.data()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); qbs::Project project = job->project(); const qbs::ErrorInfo errorInfo = forceRuleEvaluation(project); VERIFY_NO_ERROR(errorInfo); qbs::ProjectData projectData = project.projectData(); QCOMPARE(projectData.allProducts().count(), 2); qbs::ProductData product = findElem(projectData.allProducts(), [](const qbs::ProductData &p) { return p.name() == QLatin1String("installedApp"); }); QVERIFY(product.isValid()); qbs::InstallOptions installOptions; installOptions.setInstallRoot(QLatin1String("/tmp")); QList installableFiles = project.installableFilesForProduct(product, installOptions); QCOMPARE(installableFiles.count(), 2); foreach (const qbs::InstallableFile &f,installableFiles) { if (!f.sourceFilePath().endsWith("main.cpp")) { QVERIFY(f.isExecutable()); QString expectedTargetFilePath = qbs::Internal::HostOsInfo ::appendExecutableSuffix(QLatin1String("/tmp/usr/bin/installedApp")); QCOMPARE(f.targetFilePath(), expectedTargetFilePath); QCOMPARE(project.targetExecutable(product, installOptions), expectedTargetFilePath); break; } } setupParams = defaultSetupParameters("recursive-wildcards/recursive_wildcards.qbs"); job.reset(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(job.data()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); project = job->project(); projectData = project.projectData(); QCOMPARE(projectData.allProducts().count(), 1); product = projectData.allProducts().first(); installableFiles = project.installableFilesForProduct(product, installOptions); QCOMPARE(installableFiles.count(), 2); foreach (const qbs::InstallableFile &f, installableFiles) QVERIFY(!f.isExecutable()); QCOMPARE(installableFiles.first().targetFilePath(), QLatin1String("/tmp/dir/file1.txt")); QCOMPARE(installableFiles.last().targetFilePath(), QLatin1String("/tmp/dir/file2.txt")); } void TestApi::isRunnable() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("is-runnable/project.qbs"); QScopedPointer job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.data()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); qbs::Project project = job->project(); const QList products = project.projectData().products(); QCOMPARE(products.count(), 2); foreach (const qbs::ProductData &p, products) { QVERIFY2(p.name() == "app" || p.name() == "lib", qPrintable(p.name())); if (p.name() == "app") QVERIFY(p.isRunnable()); else QVERIFY(!p.isRunnable()); } } void TestApi::listBuildSystemFiles() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("subprojects/toplevelproject.qbs"); QScopedPointer job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.data()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); const QSet buildSystemFiles = job->project().buildSystemFiles(); QVERIFY(buildSystemFiles.contains(setupParams.projectFilePath())); QVERIFY(buildSystemFiles.contains(setupParams.buildRoot() + "/subproject2/subproject2.qbs")); QVERIFY(buildSystemFiles.contains(setupParams.buildRoot() + "/subproject2/subproject3/subproject3.qbs")); } void TestApi::mocCppIncluded() { // Initial build. qbs::ErrorInfo errorInfo = doBuildProject("moc-hpp-included/project.qbs"); VERIFY_NO_ERROR(errorInfo); // Touch header and try again. WAIT_FOR_NEW_TIMESTAMP(); QFile headerFile("object.h"); QVERIFY2(headerFile.open(QIODevice::WriteOnly | QIODevice::Append), qPrintable(headerFile.errorString())); headerFile.write("\n"); headerFile.close(); errorInfo = doBuildProject("moc-hpp-included/project.qbs"); VERIFY_NO_ERROR(errorInfo); // Touch cpp file and try again. WAIT_FOR_NEW_TIMESTAMP(); QFile cppFile("object.cpp"); QVERIFY2(cppFile.open(QIODevice::WriteOnly | QIODevice::Append), qPrintable(cppFile.errorString())); cppFile.write("\n"); cppFile.close(); errorInfo = doBuildProject("moc-hpp-included/project.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::multiArch() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("multi-arch/project.qbs"); qbs::Settings settings((QString())); qbs::Internal::TemporaryProfile tph("host", &settings); qbs::Profile hostProfile = tph.p; hostProfile.setValue("qbs.architecture", "host-arch"); qbs::Internal::TemporaryProfile tpt("target", &settings); qbs::Profile targetProfile = tpt.p; targetProfile.setValue("qbs.architecture", "target-arch"); QVariantMap overriddenValues; overriddenValues.insert("project.hostProfile", hostProfile.name()); overriddenValues.insert("project.targetProfile", targetProfile.name()); setupParams.setOverriddenValues(overriddenValues); QScopedPointer setupJob(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.data()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); QCOMPARE(project.profile(), profileName()); const QList &products = project.projectData().products(); QCOMPARE(products.count(), 3); QList hostProducts; QList targetProducts; foreach (const qbs::ProductData &p, products) { QVERIFY2(p.profile() == hostProfile.name() || p.profile() == targetProfile.name(), qPrintable(p.profile())); if (p.profile() == hostProfile.name()) hostProducts << p; else targetProducts << p; } QCOMPARE(hostProducts.count(), 2); QCOMPARE(targetProducts.count(), 1); QCOMPARE(targetProducts.first().name(), QLatin1String("p1")); QStringList hostProductNames = QStringList() << hostProducts.first().name() << hostProducts.last().name(); QCOMPARE(hostProductNames.count("p1"), 1); QCOMPARE(hostProductNames.count("p2"), 1); QScopedPointer buildJob(project.buildAllProducts(qbs::BuildOptions())); waitForFinished(buildJob.data()); QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString())); const QString outputBaseDir = setupParams.buildRoot() + '/'; QFile p1HostArtifact(outputBaseDir + relativeProductBuildDir("p1", "host") + "/host+target.output"); QVERIFY2(p1HostArtifact.exists(), qPrintable(p1HostArtifact.fileName())); QVERIFY2(p1HostArtifact.open(QIODevice::ReadOnly), qPrintable(p1HostArtifact.errorString())); QCOMPARE(p1HostArtifact.readAll().constData(), "host-arch"); QFile p1TargetArtifact(outputBaseDir + relativeProductBuildDir("p1", "target") + "/host+target.output"); QVERIFY2(p1TargetArtifact.exists(), qPrintable(p1TargetArtifact.fileName())); QVERIFY2(p1TargetArtifact.open(QIODevice::ReadOnly), qPrintable(p1TargetArtifact.errorString())); QCOMPARE(p1TargetArtifact.readAll().constData(), "target-arch"); QFile p2Artifact(outputBaseDir + relativeProductBuildDir("p2", "host") + "/host-tool.output"); QVERIFY2(p2Artifact.exists(), qPrintable(p2Artifact.fileName())); QVERIFY2(p2Artifact.open(QIODevice::ReadOnly), qPrintable(p2Artifact.errorString())); QCOMPARE(p2Artifact.readAll().constData(), "host-arch"); const QString installRoot = outputBaseDir + relativeBuildDir() + '/' + qbs::InstallOptions::defaultInstallRoot(); QScopedPointer installJob(project.installAllProducts(qbs::InstallOptions())); waitForFinished(installJob.data()); QVERIFY2(!installJob->error().hasError(), qPrintable(installJob->error().toString())); QFile p1HostArtifactInstalled(installRoot + "/host/host+target.output"); QVERIFY2(p1HostArtifactInstalled.exists(), qPrintable(p1HostArtifactInstalled.fileName())); QFile p1TargetArtifactInstalled(installRoot + "/target/host+target.output"); QVERIFY2(p1TargetArtifactInstalled.exists(), qPrintable(p1TargetArtifactInstalled.fileName())); QFile p2ArtifactInstalled(installRoot + "/host/host-tool.output"); QVERIFY2(p2ArtifactInstalled.exists(), qPrintable(p2ArtifactInstalled.fileName())); // Error check: Try to build for the same profile twice. overriddenValues.insert("project.targetProfile", hostProfile.name()); setupParams.setOverriddenValues(overriddenValues); setupJob.reset(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.data()); QVERIFY(setupJob->error().hasError()); QVERIFY2(setupJob->error().toString().contains(hostProfile.name()) && setupJob->error().toString().contains("not allowed"), qPrintable(setupJob->error().toString())); // Error check: Try to build for the same profile twice, this time attaching // the properties via the product name. overriddenValues.clear(); overriddenValues.insert("p1.profiles", targetProfile.name() + ',' + targetProfile.name()); setupParams.setOverriddenValues(overriddenValues); setupJob.reset(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.data()); QVERIFY(setupJob->error().hasError()); QVERIFY2(setupJob->error().toString().contains(targetProfile.name()) && setupJob->error().toString().contains("not allowed"), qPrintable(setupJob->error().toString())); } void TestApi::newOutputArtifactInDependency() { BuildDescriptionReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("new-output-artifact-in-dependency/project.qbs", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(receiver.descriptions.contains("linking app")); const QByteArray linkingLibString = QByteArray("linking ") + qbs::Internal::HostOsInfo::dynamicLibraryName("lib").toLatin1(); QVERIFY(!receiver.descriptions.contains(linkingLibString)); receiver.descriptions.clear(); WAIT_FOR_NEW_TIMESTAMP(); QFile projectFile("project.qbs"); QVERIFY2(projectFile.open(QIODevice::ReadWrite), qPrintable(projectFile.errorString())); QByteArray contents = projectFile.readAll(); contents.replace("//Depends", "Depends"); projectFile.resize(0); projectFile.write(contents); projectFile.close(); errorInfo = doBuildProject("new-output-artifact-in-dependency/project.qbs", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(receiver.descriptions.contains("linking app")); QVERIFY(receiver.descriptions.contains(linkingLibString)); } void TestApi::newPatternMatch() { TaskReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("new-pattern-match/project.qbs", 0, 0, &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(receiver.taskDescriptions.contains("Resolving"), qPrintable(m_logSink->output)); receiver.taskDescriptions.clear(); errorInfo = doBuildProject("new-pattern-match/project.qbs", 0, 0, &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(!receiver.taskDescriptions.contains("Resolving")); QFile f("test.txt"); QVERIFY2(f.open(QIODevice::WriteOnly), qPrintable(f.errorString())); f.close(); errorInfo = doBuildProject("new-pattern-match/project.qbs", 0, 0, &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(receiver.taskDescriptions.contains("Resolving")); receiver.taskDescriptions.clear(); errorInfo = doBuildProject("new-pattern-match/project.qbs", 0, 0, &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(!receiver.taskDescriptions.contains("Resolving")); f.remove(); errorInfo = doBuildProject("new-pattern-match/project.qbs", 0, 0, &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY(receiver.taskDescriptions.contains("Resolving")); } void TestApi::nonexistingProjectPropertyFromProduct() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("nonexistingprojectproperties/invalidaccessfromproduct.qbs"); QScopedPointer job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.data()); QEXPECT_FAIL("", "QBS-432", Abort); QVERIFY(job->error().hasError()); QVERIFY2(job->error().toString().contains(QLatin1String("blubb")), qPrintable(job->error().toString())); } void TestApi::nonexistingProjectPropertyFromCommandLine() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("nonexistingprojectproperties/project.qbs"); removeBuildDir(setupParams); QVariantMap projectProperties; projectProperties.insert(QLatin1String("project.blubb"), QLatin1String("true")); setupParams.setOverriddenValues(projectProperties); QScopedPointer job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.data()); QVERIFY(job->error().hasError()); QVERIFY2(job->error().toString().contains(QLatin1String("blubb")), qPrintable(job->error().toString())); } void TestApi::objC() { const qbs::ErrorInfo errorInfo = doBuildProject("objc/objc.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::projectInvalidation() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("project-invalidation/project.qbs"); QVERIFY(QFile::copy("project.no-error.qbs", "project.qbs")); QScopedPointer setupJob(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.data()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); QVERIFY(project.isValid()); WAIT_FOR_NEW_TIMESTAMP(); copyFileAndUpdateTimestamp("project.early-error.qbs", "project.qbs"); setupJob.reset(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.data()); QVERIFY(setupJob->error().hasError()); QVERIFY(project.isValid()); // Error in Loader, old project still valid. WAIT_FOR_NEW_TIMESTAMP(); copyFileAndUpdateTimestamp("project.late-error.qbs", "project.qbs"); setupJob.reset(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.data()); QVERIFY(setupJob->error().hasError()); QVERIFY(!project.isValid()); // Error in build data re-resolving, old project not valid anymore. } void TestApi::projectLocking() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("project-locking/project.qbs"); QScopedPointer setupJob(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob.data()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); qbs::Project project = setupJob->project(); setupJob.reset(project.setupProject(setupParams, m_logSink, 0)); QScopedPointer setupJob2(project.setupProject(setupParams, m_logSink, 0)); waitForFinished(setupJob2.data()); QVERIFY(setupJob2->error().hasError()); QVERIFY2(setupJob2->error().toString() .contains("Cannot start a job while another one is in progress."), qPrintable(setupJob2->error().toString())); waitForFinished(setupJob.data()); QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString())); } void TestApi::projectPropertiesByName() { const QString projectFile = "project-properties-by-name/project.qbs"; qbs::ErrorInfo errorInfo = doBuildProject(projectFile); QVERIFY(errorInfo.hasError()); QVariantMap overridden; overridden.insert("project.theDefines", QStringList() << "SUB1" << "SUB2"); errorInfo = doBuildProject(projectFile, 0, 0, 0, qbs::BuildOptions(), overridden); QVERIFY(errorInfo.hasError()); overridden.clear(); overridden.insert("subproject1.theDefines", QStringList() << "SUB1"); errorInfo = doBuildProject(projectFile, 0, 0, 0, qbs::BuildOptions(), overridden); QVERIFY(errorInfo.hasError()); overridden.insert("subproject2.theDefines", QStringList() << "SUB2"); errorInfo = doBuildProject(projectFile, 0, 0, 0, qbs::BuildOptions(), overridden); VERIFY_NO_ERROR(errorInfo); } void TestApi::projectWithPropertiesItem() { const qbs::ErrorInfo errorInfo = doBuildProject("project-with-properties-item/project.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::propertiesBlocks() { const qbs::ErrorInfo errorInfo = doBuildProject("properties-blocks/propertiesblocks.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::rc() { BuildDescriptionReceiver receiver; const qbs::ErrorInfo errorInfo = doBuildProject("rc/rc.qbs", &receiver); VERIFY_NO_ERROR(errorInfo); const bool rcFileWasCompiled = receiver.descriptions.contains("compiling test.rc"); QCOMPARE(rcFileWasCompiled, qbs::Internal::HostOsInfo::isWindowsHost()); } qbs::SetupProjectParameters TestApi::defaultSetupParameters(const QString &projectFilePath) const { qbs::SetupProjectParameters setupParams; const QString projectDirPath = QDir::cleanPath(m_workingDataDir + QLatin1Char('/') + QFileInfo(projectFilePath).path()); setupParams.setProjectFilePath(projectDirPath + QLatin1Char('/') + QFileInfo(projectFilePath).fileName()); setupParams.setPropertyCheckingMode(qbs::SetupProjectParameters::PropertyCheckingStrict); QDir::setCurrent(projectDirPath); setupParams.setBuildRoot(projectDirPath); qbs::Settings settings((QString())); const qbs::Preferences prefs(&settings, profileName()); setupParams.setSearchPaths(prefs.searchPaths(QDir::cleanPath(QCoreApplication::applicationDirPath() + QLatin1String("/" QBS_RELATIVE_SEARCH_PATH)))); setupParams.setPluginPaths(prefs.pluginPaths(QDir::cleanPath(QCoreApplication::applicationDirPath() + QLatin1String("/" QBS_RELATIVE_PLUGINS_PATH)))); setupParams.setLibexecPath(QDir::cleanPath(QCoreApplication::applicationDirPath() + QLatin1String("/" QBS_RELATIVE_LIBEXEC_PATH))); setupParams.setTopLevelProfile(profileName()); setupParams.setBuildVariant(QLatin1String("debug")); return setupParams; } void TestApi::references() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("references/invalid1.qbs"); const QString projectDir = QDir::cleanPath(m_workingDataDir + "/references"); QScopedPointer job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.data()); QVERIFY(job->error().hasError()); QString errorString = job->error().toString(); QVERIFY2(errorString.contains("does not contain"), qPrintable(errorString)); setupParams.setProjectFilePath(projectDir + QLatin1String("/invalid2.qbs")); job.reset(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.data()); QVERIFY(job->error().hasError()); errorString = job->error().toString(); QVERIFY2(errorString.contains("contains more than one"), qPrintable(errorString)); setupParams.setProjectFilePath(projectDir + QLatin1String("/valid.qbs")); job.reset(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.data()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); const qbs::ProjectData topLevelProject = job->project().projectData(); QCOMPARE(topLevelProject.subProjects().count(), 1); const QString subProjectFileName = QFileInfo(topLevelProject.subProjects().first().location().filePath()).fileName(); QCOMPARE(subProjectFileName, QString("p.qbs")); } void TestApi::renameProduct() { // Initial run. qbs::ErrorInfo errorInfo = doBuildProject("rename-product/rename.qbs"); VERIFY_NO_ERROR(errorInfo); // Rename lib and adapt Depends item. WAIT_FOR_NEW_TIMESTAMP(); QFile f("rename.qbs"); QVERIFY(f.open(QIODevice::ReadWrite)); QByteArray contents = f.readAll(); contents.replace("TheLib", "thelib"); f.resize(0); f.write(contents); f.close(); errorInfo = doBuildProject("rename-product/rename.qbs"); VERIFY_NO_ERROR(errorInfo); // Rename lib and don't adapt Depends item. WAIT_FOR_NEW_TIMESTAMP(); QVERIFY(f.open(QIODevice::ReadWrite)); contents = f.readAll(); const int libNameIndex = contents.lastIndexOf("thelib"); QVERIFY(libNameIndex != -1); contents.replace(libNameIndex, 6, "TheLib"); f.resize(0); f.write(contents); f.close(); errorInfo = doBuildProject("rename-product/rename.qbs"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("Product dependency 'thelib' not found"), qPrintable(errorInfo.toString())); } void TestApi::renameTargetArtifact() { // Initial run. BuildDescriptionReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("rename-target-artifact/rename.qbs", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(receiver.descriptions.contains("compiling"), qPrintable(receiver.descriptions)); QCOMPARE(receiver.descriptions.count("linking"), 2); receiver.descriptions.clear(); // Rename library file name. WAIT_FOR_NEW_TIMESTAMP(); QFile f("rename.qbs"); QVERIFY(f.open(QIODevice::ReadWrite)); QByteArray contents = f.readAll(); contents.replace("the_lib", "TheLib"); f.resize(0); f.write(contents); f.close(); errorInfo = doBuildProject("rename-target-artifact/rename.qbs", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(!receiver.descriptions.contains("compiling"), qPrintable(receiver.descriptions)); QCOMPARE(receiver.descriptions.count("linking"), 2); } void TestApi::removeFileDependency() { qbs::ErrorInfo errorInfo = doBuildProject("remove-file-dependency/removeFileDependency.qbs"); VERIFY_NO_ERROR(errorInfo); QFile::remove("someheader.h"); ProcessResultReceiver receiver; errorInfo = doBuildProject("remove-file-dependency/removeFileDependency.qbs", 0, &receiver); QVERIFY(errorInfo.hasError()); QVERIFY2(receiver.output.contains("someheader.h"), qPrintable(receiver.output)); } void TestApi::resolveProject() { QFETCH(QString, projectSubDir); QFETCH(QString, productFileName); const qbs::SetupProjectParameters params = defaultSetupParameters(projectSubDir + "/project.qbs"); removeBuildDir(params); const QScopedPointer setupJob(qbs::Project().setupProject(params, m_logSink, 0)); waitForFinished(setupJob.data()); VERIFY_NO_ERROR(setupJob->error()); QVERIFY2(!QFile::exists(productFileName), qPrintable(productFileName)); QVERIFY(regularFileExists(relativeBuildGraphFilePath())); } void TestApi::resolveProject_data() { return buildProject_data(); } void TestApi::resolveProjectDryRun() { QFETCH(QString, projectSubDir); QFETCH(QString, productFileName); qbs::SetupProjectParameters params = defaultSetupParameters(projectSubDir + "/project.qbs"); params.setDryRun(true); removeBuildDir(params); const QScopedPointer setupJob(qbs::Project().setupProject(params, m_logSink, 0)); waitForFinished(setupJob.data()); VERIFY_NO_ERROR(setupJob->error()); QVERIFY2(!QFile::exists(productFileName), qPrintable(productFileName)); QVERIFY(!regularFileExists(relativeBuildGraphFilePath())); } void TestApi::resolveProjectDryRun_data() { return resolveProject_data(); } void TestApi::softDependency() { const qbs::ErrorInfo errorInfo = doBuildProject("soft-dependency/project.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::sourceFileInBuildDir() { qbs::SetupProjectParameters setupParams = defaultSetupParameters("source-file-in-build-dir/project.qbs"); QScopedPointer job(qbs::Project().setupProject(setupParams, m_logSink, 0)); waitForFinished(job.data()); QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString())); const qbs::ProjectData projectData = job->project().projectData(); QCOMPARE(projectData.allProducts().count(), 1); const qbs::ProductData product = projectData.allProducts().first(); QCOMPARE(product.profile(), profileName()); QCOMPARE(product.groups().count(), 1); const qbs::GroupData group = product.groups().first(); QCOMPARE(group.allFilePaths().count(), 1); } void TestApi::subProjects() { const qbs::SetupProjectParameters params = defaultSetupParameters("subprojects/toplevelproject.qbs"); removeBuildDir(params); // Check all three types of subproject creation, plus property overrides. qbs::ErrorInfo errorInfo = doBuildProject("subprojects/toplevelproject.qbs"); VERIFY_NO_ERROR(errorInfo); // Disabling both the project with the dependency and the one with the dependent // should not cause an error. WAIT_FOR_NEW_TIMESTAMP(); QFile f(params.projectFilePath()); QVERIFY(f.open(QIODevice::ReadWrite)); QByteArray contents = f.readAll(); contents.replace("condition: true", "condition: false"); f.resize(0); f.write(contents); f.close(); f.setFileName(params.buildRoot() + "/subproject2/subproject2.qbs"); QVERIFY(f.open(QIODevice::ReadWrite)); contents = f.readAll(); contents.replace("condition: true", "condition: false"); f.resize(0); f.write(contents); f.close(); errorInfo = doBuildProject("subprojects/toplevelproject.qbs"); VERIFY_NO_ERROR(errorInfo); // Disabling the project with the dependency only is an error. // This tests also whether changes in sub-projects are detected. WAIT_FOR_NEW_TIMESTAMP(); f.setFileName(params.projectFilePath()); QVERIFY(f.open(QIODevice::ReadWrite)); contents = f.readAll(); contents.replace("condition: false", "condition: true"); f.resize(0); f.write(contents); f.close(); errorInfo = doBuildProject("subprojects/toplevelproject.qbs"); QVERIFY(errorInfo.hasError()); QVERIFY2(errorInfo.toString().contains("Product dependency 'testLib' not found"), qPrintable(errorInfo.toString())); } void TestApi::trackAddQObjectHeader() { const qbs::SetupProjectParameters params = defaultSetupParameters("missing-qobject-header/missingheader.qbs"); QFile qbsFile(params.projectFilePath()); QVERIFY(qbsFile.open(QIODevice::WriteOnly | QIODevice::Truncate)); qbsFile.write("import qbs.base 1.0\nCppApplication {\n Depends { name: 'Qt.core' }\n" " files: ['main.cpp', 'myobject.cpp']\n}"); qbsFile.close(); ProcessResultReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("missing-qobject-header/missingheader.qbs", 0, &receiver); QVERIFY(errorInfo.hasError()); QVERIFY2(isAboutUndefinedSymbols(receiver.output), qPrintable(receiver.output)); WAIT_FOR_NEW_TIMESTAMP(); QVERIFY(qbsFile.open(QIODevice::WriteOnly | QIODevice::Truncate)); qbsFile.write("import qbs.base 1.0\nCppApplication {\n Depends { name: 'Qt.core' }\n" " files: ['main.cpp', 'myobject.cpp','myobject.h']\n}"); qbsFile.close(); errorInfo = doBuildProject("missing-qobject-header/missingheader.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::trackRemoveQObjectHeader() { const qbs::SetupProjectParameters params = defaultSetupParameters("missing-qobject-header/missingheader.qbs"); removeBuildDir(params); QFile qbsFile(params.projectFilePath()); QVERIFY(qbsFile.open(QIODevice::WriteOnly | QIODevice::Truncate)); qbsFile.write("import qbs.base 1.0\nCppApplication {\n Depends { name: 'Qt.core' }\n" " files: ['main.cpp', 'myobject.cpp','myobject.h']\n}"); qbsFile.close(); qbs::ErrorInfo errorInfo = doBuildProject("missing-qobject-header/missingheader.qbs"); VERIFY_NO_ERROR(errorInfo); WAIT_FOR_NEW_TIMESTAMP(); QVERIFY(qbsFile.open(QIODevice::WriteOnly | QIODevice::Truncate)); qbsFile.write("import qbs.base 1.0\nCppApplication {\n Depends { name: 'Qt.core' }\n" " files: ['main.cpp', 'myobject.cpp']\n}"); qbsFile.close(); ProcessResultReceiver receiver; errorInfo = doBuildProject("missing-qobject-header/missingheader.qbs", 0, &receiver); QVERIFY(errorInfo.hasError()); QVERIFY2(isAboutUndefinedSymbols(receiver.output), qPrintable(receiver.output)); } void TestApi::transformers() { const qbs::ErrorInfo errorInfo = doBuildProject("transformers/transformers.qbs"); VERIFY_NO_ERROR(errorInfo); } void TestApi::typeChange() { BuildDescriptionReceiver receiver; qbs::ErrorInfo errorInfo = doBuildProject("type-change/project.qbs", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(!receiver.descriptions.contains("compiling"), qPrintable(receiver.descriptions)); WAIT_FOR_NEW_TIMESTAMP(); QFile projectFile("project.qbs"); QVERIFY2(projectFile.open(QIODevice::ReadWrite), qPrintable(projectFile.errorString())); QByteArray content = projectFile.readAll(); content.replace("//", ""); projectFile.resize(0); projectFile.write(content); projectFile.close(); errorInfo = doBuildProject("type-change/project.qbs", &receiver); VERIFY_NO_ERROR(errorInfo); QVERIFY2(receiver.descriptions.contains("compiling"), qPrintable(receiver.descriptions)); } void TestApi::uic() { const qbs::ErrorInfo errorInfo = doBuildProject("uic/uic.qbs"); VERIFY_NO_ERROR(errorInfo); } qbs::ErrorInfo TestApi::doBuildProject(const QString &projectFilePath, QObject *buildDescriptionReceiver, QObject *procResultReceiver, QObject *taskReceiver, const qbs::BuildOptions &options, const QVariantMap overriddenValues) { qbs::SetupProjectParameters params = defaultSetupParameters(projectFilePath); params.setOverriddenValues(overriddenValues); params.setDryRun(options.dryRun()); const QScopedPointer setupJob(qbs::Project().setupProject(params, m_logSink, 0)); if (taskReceiver) { connect(setupJob.data(), SIGNAL(taskStarted(QString,int,qbs::AbstractJob*)), taskReceiver, SLOT(handleTaskStart(QString))); } waitForFinished(setupJob.data()); if (setupJob->error().hasError()) return setupJob->error(); const QScopedPointer buildJob(setupJob->project().buildAllProducts(options)); if (buildDescriptionReceiver) { connect(buildJob.data(), SIGNAL(reportCommandDescription(QString,QString)), buildDescriptionReceiver, SLOT(handleDescription(QString,QString))); } if (procResultReceiver) { connect(buildJob.data(), SIGNAL(reportProcessResult(qbs::ProcessResult)), procResultReceiver, SLOT(handleProcessResult(qbs::ProcessResult))); } waitForFinished(buildJob.data()); return buildJob->error(); } QTEST_MAIN(TestApi) #include "tst_api.moc" qbs-src-1.4.5/tests/auto/api/tst_api.h000066400000000000000000000106071266132464200176040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_TST_API_H #define QBS_TST_API_H #include #include #include namespace qbs { class ErrorInfo; class SetupProjectParameters; } class LogSink; class TestApi : public QObject { Q_OBJECT public: TestApi(); ~TestApi(); private slots: void initTestCase(); void addQObjectMacroToCppFile(); void addedFilePersistent(); void baseProperties(); void buildGraphLocking(); void buildProject(); void buildProject_data(); void buildProjectDryRun(); void buildProjectDryRun_data(); void buildSingleFile(); #ifdef QBS_ENABLE_PROJECT_FILE_UPDATES void changeContent(); #endif void changeDependentLib(); void commandExtraction(); void disabledInstallGroup(); void disabledProduct(); void disabledProject(); void duplicateProductNames(); void duplicateProductNames_data(); void dynamicLibs(); void emptyFileTagList(); void emptySubmodulesList(); void enableAndDisableProduct(); void explicitlyDependsOn(); void exportSimple(); void exportWithRecursiveDepends(); void fileTagger(); void fileTagsFilterOverride(); void infiniteLoopBuilding(); void infiniteLoopBuilding_data(); void infiniteLoopResolving(); void inheritQbsSearchPaths(); void installableFiles(); void isRunnable(); void listBuildSystemFiles(); void mocCppIncluded(); void multiArch(); void newOutputArtifactInDependency(); void newPatternMatch(); void nonexistingProjectPropertyFromCommandLine(); void nonexistingProjectPropertyFromProduct(); void objC(); void projectInvalidation(); void projectLocking(); void projectPropertiesByName(); void projectWithPropertiesItem(); void propertiesBlocks(); void rc(); void references(); void removeFileDependency(); void renameProduct(); void renameTargetArtifact(); void resolveProject(); void resolveProject_data(); void resolveProjectDryRun(); void resolveProjectDryRun_data(); void softDependency(); void sourceFileInBuildDir(); void subProjects(); void trackAddQObjectHeader(); void trackRemoveQObjectHeader(); void transformers(); void typeChange(); void uic(); private: qbs::SetupProjectParameters defaultSetupParameters(const QString &projectFilePath) const; qbs::ErrorInfo doBuildProject(const QString &projectFilePath, QObject *buildDescriptionReceiver = 0, QObject *procResultReceiver = 0, QObject *taskReceiver = 0, const qbs::BuildOptions &options = qbs::BuildOptions(), const QVariantMap overriddenValues = QVariantMap()); LogSink * const m_logSink; const QString m_sourceDataDir; const QString m_workingDataDir; }; #endif // Include guard. qbs-src-1.4.5/tests/auto/auto.pri000066400000000000000000000004611266132464200167000ustar00rootroot00000000000000TEMPLATE = app DESTDIR = ../../../bin DEFINES += SRCDIR=\\\"$$_PRO_FILE_PWD_\\\" INCLUDEPATH += $$PWD/../../src QT = core script testlib CONFIG += depend_includepath testcase console CONFIG -= app_bundle CONFIG += c++11 target.CONFIG += no_default_install include(../../src/lib/corelib/use_corelib.pri) qbs-src-1.4.5/tests/auto/auto.pro000066400000000000000000000002561266132464200167100ustar00rootroot00000000000000TEMPLATE=subdirs qbs_enable_unit_tests { SUBDIRS += \ buildgraph \ language \ tools \ } SUBDIRS += \ cmdlineparser \ blackbox \ api qbs-src-1.4.5/tests/auto/auto.qbs000066400000000000000000000005331266132464200166730ustar00rootroot00000000000000import qbs Project { name: "Autotests" references: [ "api/api.qbs", "blackbox/blackbox.qbs", "cmdlineparser/cmdlineparser.qbs" ].concat(unitTests) property pathList unitTests: enableUnitTests ? [ "buildgraph/buildgraph.qbs", "language/language.qbs", "tools/tools.qbs" ] : [] } qbs-src-1.4.5/tests/auto/blackbox/000077500000000000000000000000001266132464200170005ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/blackbox.pro000066400000000000000000000004601266132464200213070ustar00rootroot00000000000000TARGET = tst_blackbox HEADERS = tst_blackbox.h SOURCES = tst_blackbox.cpp include(../auto.pri) DATA_DIRS = testdata for(data_dir, DATA_DIRS) { files = $$files($$PWD/$$data_dir/*, true) win32:files ~= s|\\\\|/|g for(file, files):!exists($$file/*):FILES += $$file } OTHER_FILES += $$FILES qbs-src-1.4.5/tests/auto/blackbox/blackbox.qbs000066400000000000000000000005661266132464200213030ustar00rootroot00000000000000import qbs 1.0 QbsAutotest { testName: "blackbox" Depends { name: "qbs_app" } Depends { name: "qbs-setup-toolchains" } files: ["../shared.h", "tst_blackbox.h", "tst_blackbox.cpp", ] cpp.defines: base.concat(['SRCDIR="' + path + '"']) Group { name: "testdata" prefix: "testdata/" files: ["**/*"] fileTags: [] } } qbs-src-1.4.5/tests/auto/blackbox/testdata/000077500000000000000000000000001266132464200206115ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/000077500000000000000000000000001266132464200222315ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/000077500000000000000000000000001266132464200272505ustar00rootroot00000000000000multiple-apks-per-project.qbs000066400000000000000000000001301266132464200347110ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-projectimport qbs Project { references: [ "product1", "product2", ] } qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/000077500000000000000000000000001266132464200310115ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/product1.qbs000066400000000000000000000011251266132464200332600ustar00rootroot00000000000000import qbs Project { DynamicLibrary { name: "p1lib1" files: ["src/main/jni/lib1.cpp"] Android.ndk.appStl: "stlport_shared" architectures: ["mipsel", "x86"] cpp.useRPaths: false } DynamicLibrary { name: "p1lib2" files: ["src/main/jni/lib2.cpp"] Android.ndk.appStl: "stlport_shared" cpp.useRPaths: false } AndroidApk { name: "twolibs1" packageName: "io.qt.dummy1" Depends { productTypes: ["android.nativelibrary"] limitToSubProject: true } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/src/000077500000000000000000000000001266132464200316005ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/src/main/000077500000000000000000000000001266132464200325245ustar00rootroot00000000000000AndroidManifest.xml000066400000000000000000000017231266132464200362410ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/src/main qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/src/main/java/000077500000000000000000000000001266132464200334455ustar00rootroot00000000000000io/000077500000000000000000000000001266132464200337755ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/src/main/javaqt/000077500000000000000000000000001266132464200344215ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/src/main/java/iodummy/000077500000000000000000000000001266132464200355545ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/src/main/java/io/qtDummy.java000066400000000000000000000002661266132464200375160ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/src/main/java/io/qt/dummypackage io.qt.dummy; import android.app.Activity; public class Dummy extends Activity { static { System.loadLibrary("lib1"); System.loadLibrary("lib"); } } qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/src/main/jni/000077500000000000000000000000001266132464200333045ustar00rootroot00000000000000lib1.cpp000066400000000000000000000000141266132464200345530ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/src/main/jnivoid f() {} lib2.cpp000066400000000000000000000000141266132464200345540ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/src/main/jnivoid g() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/src/main/res/000077500000000000000000000000001266132464200333155ustar00rootroot00000000000000values/000077500000000000000000000000001266132464200345355ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/src/main/resstrings.xml000066400000000000000000000001051266132464200367440ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product1/src/main/res/values dummy1 qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product2/000077500000000000000000000000001266132464200310125ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product2/product2.qbs000066400000000000000000000007421266132464200332660ustar00rootroot00000000000000import qbs Project { DynamicLibrary { name: "p2lib1" files: ["src/main/jni/lib1.cpp"] cpp.useRPaths: false } DynamicLibrary { name: "p2lib2" files: ["src/main/jni/lib2.cpp"] Android.ndk.appStl: "stlport_shared" } AndroidApk { name: "twolibs2" packageName: "io.qt.dummy2" Depends { productTypes: ["android.nativelibrary"] limitToSubProject: true } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product2/src/000077500000000000000000000000001266132464200316015ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product2/src/main/000077500000000000000000000000001266132464200325255ustar00rootroot00000000000000AndroidManifest.xml000066400000000000000000000017231266132464200362420ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product2/src/main qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product2/src/main/java/000077500000000000000000000000001266132464200334465ustar00rootroot00000000000000io/000077500000000000000000000000001266132464200337765ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product2/src/main/javaqt/000077500000000000000000000000001266132464200344225ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product2/src/main/java/iodummy/000077500000000000000000000000001266132464200355555ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product2/src/main/java/io/qtDummy.java000066400000000000000000000002661266132464200375170ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product2/src/main/java/io/qt/dummypackage io.qt.dummy; import android.app.Activity; public class Dummy extends Activity { static { System.loadLibrary("lib1"); System.loadLibrary("lib"); } } qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product2/src/main/jni/000077500000000000000000000000001266132464200333055ustar00rootroot00000000000000lib1.cpp000066400000000000000000000000141266132464200345540ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product2/src/main/jnivoid f() {} lib2.cpp000066400000000000000000000000141266132464200345550ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-apks-per-project/product2/src/main/jnivoid g() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-libs-per-apk/000077500000000000000000000000001266132464200263505ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-libs-per-apk/multiple-libs-per-apk.qbs000066400000000000000000000007561266132464200332060ustar00rootroot00000000000000import qbs Project { DynamicLibrary { name: "lib1" files: ["src/main/jni/lib1.cpp"] Android.ndk.appStl: "stlport_shared" cpp.useRPaths: false } DynamicLibrary { name: "lib2" files: ["src/main/jni/lib2.cpp"] Android.ndk.appStl: "stlport_shared" cpp.useRPaths: false } AndroidApk { name: "twolibs" packageName: "io.qt.dummy" Depends { productTypes: ["android.nativelibrary"] } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-libs-per-apk/src/000077500000000000000000000000001266132464200271375ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-libs-per-apk/src/main/000077500000000000000000000000001266132464200300635ustar00rootroot00000000000000AndroidManifest.xml000066400000000000000000000017211266132464200335760ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-libs-per-apk/src/main qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-libs-per-apk/src/main/java/000077500000000000000000000000001266132464200310045ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-libs-per-apk/src/main/java/io/000077500000000000000000000000001266132464200314135ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-libs-per-apk/src/main/java/io/qt/000077500000000000000000000000001266132464200320375ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-libs-per-apk/src/main/java/io/qt/dummy/000077500000000000000000000000001266132464200331725ustar00rootroot00000000000000Dummy.java000066400000000000000000000002661266132464200350550ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-libs-per-apk/src/main/java/io/qt/dummypackage io.qt.dummy; import android.app.Activity; public class Dummy extends Activity { static { System.loadLibrary("lib1"); System.loadLibrary("lib"); } } qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-libs-per-apk/src/main/jni/000077500000000000000000000000001266132464200306435ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-libs-per-apk/src/main/jni/lib1.cpp000066400000000000000000000000141266132464200321710ustar00rootroot00000000000000void f() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-libs-per-apk/src/main/jni/lib2.cpp000066400000000000000000000000141266132464200321720ustar00rootroot00000000000000void g() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-libs-per-apk/src/main/res/000077500000000000000000000000001266132464200306545ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-libs-per-apk/src/main/res/values/000077500000000000000000000000001266132464200321535ustar00rootroot00000000000000strings.xml000066400000000000000000000001041266132464200343020ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/multiple-libs-per-apk/src/main/res/values dummy qbs-src-1.4.5/tests/auto/blackbox/testdata/android/no-native/000077500000000000000000000000001266132464200241315ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/no-native/no-native.qbs000066400000000000000000000003041266132464200265350ustar00rootroot00000000000000import qbs AndroidApk { name: "com.example.android.basicmediadecoder" sourceSetDir: Android.sdk.sdkDir + "/samples/android-21/media/BasicMediaDecoder/Application/src/main" } qbs-src-1.4.5/tests/auto/blackbox/testdata/android/teapot/000077500000000000000000000000001266132464200235255ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/android/teapot/teapot.qbs000066400000000000000000000046261266132464200255400ustar00rootroot00000000000000import qbs Project { property stringList architectures: ["arm64", "armv7", "x86_64", "mipsel"] StaticLibrary { architectures: project.architectures name: "native-glue" Group { id: glue_sources prefix: Android.ndk.ndkDir + "/sources/android/native_app_glue/" files: ["*.c", "*.h"] } Export { Depends { name: "cpp" } cpp.includePaths: [glue_sources.prefix] cpp.dynamicLibraries: ["log"] } } StaticLibrary { architectures: project.architectures name: "ndk-helper" Depends { name: "native-glue" } Group { id: ndkhelper_sources prefix: Android.ndk.ndkDir + "/sources/android/ndk_helper/" files: ["*.c", "*.cpp", "*.h"] } Android.ndk.appStl: "stlport_shared" Export { Depends { name: "cpp" } cpp.includePaths: [ndkhelper_sources.prefix] cpp.dynamicLibraries: ["log", "android", "EGL", "GLESv2"] } } StaticLibrary { architectures: project.architectures name: "cpufeatures" Group { id: cpufeatures_sources prefix: Android.ndk.ndkDir + "/sources/android/cpufeatures/" files: ["*.c", "*.h"] } Export { Depends { name: "cpp" } cpp.includePaths: [cpufeatures_sources.prefix] cpp.dynamicLibraries: ["dl"] } } DynamicLibrary { name: "TeapotNativeActivity" architectures: project.architectures Depends { name: "cpufeatures" } Depends { name: "native-glue" } Depends { name: "ndk-helper" } Group { name: "C++ sources" prefix: Android.ndk.ndkDir + "/samples/Teapot/jni/" files: [ "TeapotNativeActivity.cpp", "TeapotRenderer.cpp", "TeapotRenderer.h", "teapot.inl", ] } FileTagger { patterns: ["*.inl"]; fileTags: ["hpp"] } Android.ndk.appStl: "stlport_shared" cpp.dynamicLibraries: ["log", "android", "EGL", "GLESv2"] cpp.useRPaths: false } AndroidApk { name: "com.sample.teapot" sourceSetDir: Android.sdk.ndkDir + "/samples/Teapot" legacyLayout: true Depends { productTypes: ["android.nativelibrary"] } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/archiver/000077500000000000000000000000001266132464200224145ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/archiver/archivable.qbs000066400000000000000000000004011266132464200252160ustar00rootroot00000000000000import qbs Product { name: "archivable" type: "archiver.archive" Depends { name: "archiver" } archiver.workingDirectory: path Group { files: ["list.txt"] fileTags: ["archiver.input-list"] } files: ["test.txt"] } qbs-src-1.4.5/tests/auto/blackbox/testdata/archiver/list.txt000066400000000000000000000000301266132464200241210ustar00rootroot00000000000000test.txt archivable.qbs qbs-src-1.4.5/tests/auto/blackbox/testdata/archiver/test.txt000066400000000000000000000000001266132464200241220ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/assembly/000077500000000000000000000000001266132464200224305ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/assembly/assembly.qbs000066400000000000000000000015211266132464200247550ustar00rootroot00000000000000import qbs 1.0 Project { StaticLibrary { name : "testa" files : [ "testa.s" ] Depends { name: "cpp" } condition: qbs.toolchain.contains("gcc") } StaticLibrary { name : "testb" files : [ "testb.S" ] Depends { name: "cpp" } condition: qbs.toolchain.contains("gcc") } StaticLibrary { name : "testc" files : [ "testc.sx" ] Depends { name: "cpp" } condition: qbs.toolchain.contains("gcc") } StaticLibrary { name: "testd" Group { condition: product.condition files: ["testd_" + qbs.architecture + ".asm"] } Depends { name: "cpp" } condition: qbs.toolchain.contains("msvc") && (qbs.architecture === "x86" || qbs.architecture === "x86_64") } } qbs-src-1.4.5/tests/auto/blackbox/testdata/assembly/testa.s000066400000000000000000000000401266132464200237260ustar00rootroot00000000000000.globl symbola symbola: nop qbs-src-1.4.5/tests/auto/blackbox/testdata/assembly/testb.S000066400000000000000000000000411266132464200236700ustar00rootroot00000000000000#define bla nop symbolb: bla qbs-src-1.4.5/tests/auto/blackbox/testdata/assembly/testc.sx000066400000000000000000000000411266132464200241210ustar00rootroot00000000000000#define bla nop symbolb: bla qbs-src-1.4.5/tests/auto/blackbox/testdata/assembly/testd_x86.asm000066400000000000000000000001111266132464200247530ustar00rootroot00000000000000.386 .model flat, stdcall .code foo PROC nop RET foo ENDP END qbs-src-1.4.5/tests/auto/blackbox/testdata/assembly/testd_x86_64.asm000066400000000000000000000000561266132464200252740ustar00rootroot00000000000000.code foo PROC nop RET foo ENDP END qbs-src-1.4.5/tests/auto/blackbox/testdata/badInterpreter/000077500000000000000000000000001266132464200235635ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/badInterpreter/badInterpreter.qbs000066400000000000000000000016501266132464200272460ustar00rootroot00000000000000import qbs Project { qbsSearchPaths: base.concat(["qbs"]) Product { Depends { name: "script-test" } name: "script-ok" type: ["application"] Group { files: [product.name] fileTags: ["script"] } } Product { Depends { name: "script-test" } name: "script-noexec" type: ["application"] Group { files: [product.name] fileTags: ["script"] } } Product { Depends { name: "script-test" } name: "script-interp-missing" type: ["application"] Group { files: [product.name] fileTags: ["script"] } } Product { Depends { name: "script-test" } name: "script-interp-noexec" type: ["application"] Group { files: [product.name] fileTags: ["script"] } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/badInterpreter/qbs/000077500000000000000000000000001266132464200243505ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/badInterpreter/qbs/modules/000077500000000000000000000000001266132464200260205ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/badInterpreter/qbs/modules/script-test/000077500000000000000000000000001266132464200303015ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/badInterpreter/qbs/modules/script-test/script-test.qbs000066400000000000000000000020741266132464200332740ustar00rootroot00000000000000import qbs import qbs.FileInfo import qbs.TextFile Module { name: "script-test" Rule { inputs: ["script"] Artifact { filePath: FileInfo.joinPaths(project.buildDirectory, input.fileName) fileTags: ["application"] } prepare: { var cmds = []; var cmd = new JavaScriptCommand(); cmd.description = "copying " + input.fileName; cmd.sourceCode = function() { var tf = new TextFile(input.filePath, TextFile.ReadOnly); var s = tf.readAll().replace("$PWD", project.buildDirectory); tf.close(); var tf2 = new TextFile(output.filePath, TextFile.ReadWrite); tf2.write(s); tf2.close(); }; cmds.push(cmd); if (output.fileName !== "script-noexec") { var cmd2 = new Command("chmod", ["+x", output.filePath]); cmd2.silent = true; cmds.push(cmd2); } return cmds; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/badInterpreter/script-interp-missing000077500000000000000000000000221266132464200277550ustar00rootroot00000000000000#!/does/not/exist qbs-src-1.4.5/tests/auto/blackbox/testdata/badInterpreter/script-interp-noexec000077500000000000000000000000251266132464200275700ustar00rootroot00000000000000#!$PWD/script-noexec qbs-src-1.4.5/tests/auto/blackbox/testdata/badInterpreter/script-noexec000066400000000000000000000000001266132464200262570ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/badInterpreter/script-ok000077500000000000000000000000141266132464200254170ustar00rootroot00000000000000#!/bin/bash qbs-src-1.4.5/tests/auto/blackbox/testdata/build-directories/000077500000000000000000000000001266132464200242225ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/build-directories/project.qbs000066400000000000000000000021721266132464200264010ustar00rootroot00000000000000import qbs Project { Product { name: "p1" type: "blubb1" Transformer { Artifact { filePath: "dummy1.txt" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { print(product.buildDirectory); } return cmd; } } } Product { name: "p2" type: "blubb2" Depends { name: "p1" } Rule { inputsFromDependencies: "blubb1" Artifact { filePath: "dummy2.txt" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { print(product.buildDirectory); print(project.buildDirectory); print(project.sourceDirectory); } return cmd; } } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/change-in-disabled-product/000077500000000000000000000000001266132464200256655ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/change-in-disabled-product/project.qbs000066400000000000000000000001541266132464200300420ustar00rootroot00000000000000import qbs Product { condition: false files: [ 'test1.txt', // 'test2.txt' ] } qbs-src-1.4.5/tests/auto/blackbox/testdata/change-in-disabled-product/test1.txt000066400000000000000000000000001266132464200274540ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/change-in-disabled-product/test2.txt000066400000000000000000000000001266132464200274550ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/changed-files/000077500000000000000000000000001266132464200233025ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/changed-files/file1.cpp000066400000000000000000000000151266132464200250020ustar00rootroot00000000000000void f1() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/changed-files/file2.cpp000066400000000000000000000000151266132464200250030ustar00rootroot00000000000000void f2() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/changed-files/main.cpp000066400000000000000000000000161266132464200247270ustar00rootroot00000000000000int main() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/changed-files/project.qbs000066400000000000000000000014041266132464200254560ustar00rootroot00000000000000import qbs import qbs.TextFile CppApplication { type: ["application", "stuff"] consoleApplication: true files: ["file1.cpp", "file2.cpp", "main.cpp"] Rule { inputs: ["cpp"] outputFileTags: ["stuff"] outputArtifacts: { return [{ filePath: input.completeBaseName + ".stuff", fileTags: ["stuff"] }]; } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating " + output.fileName cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write("crazy stuff"); f.close(); } return cmd; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/clean/000077500000000000000000000000001266132464200216735ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/clean/clean.qbs000066400000000000000000000005531266132464200234670ustar00rootroot00000000000000import qbs 1.0 Project { DynamicLibrary { Depends { name: "cpp" } Depends { name: "Qt.core" } version: "1.1.0" name: "dep" files: "dep.cpp" bundle.isBundle: false } CppApplication { consoleApplication: true name: "app" Depends { name: "dep" } files: "main.cpp" } } qbs-src-1.4.5/tests/auto/blackbox/testdata/clean/dep.cpp000066400000000000000000000000571266132464200231510ustar00rootroot00000000000000#include Q_DECL_EXPORT void f() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/clean/main.cpp000066400000000000000000000000171266132464200233210ustar00rootroot00000000000000int main() { } qbs-src-1.4.5/tests/auto/blackbox/testdata/concurrent-executor/000077500000000000000000000000001266132464200246275ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/concurrent-executor/concurrent-executor.qbs000066400000000000000000000034421266132464200313570ustar00rootroot00000000000000import qbs import qbs.File import qbs.TextFile import "util.js" as Utils Product { type: ["final1", "final2"] Group { files: ["dummy1.input"] fileTags: ["input1"] } Group { files: ["dummy2.input"] fileTags: ["input2"] } Rule { inputs: ["input1"] Artifact { filePath: project.buildDirectory + "/dummy1.final" fileTags: ["final1"] } prepare: { var cmds = []; for (var i = 0; i < 10; ++i) { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.createFile = i == 9; cmd.sourceCode = function() { if (createFile) { print("Creating file"); var file = new TextFile(output.filePath, TextFile.WriteOnly); file.close(); } }; cmds.push(cmd); } return cmds; } } Rule { inputs: ["input2"] Artifact { filePath: "dummy.intermediate" fileTags: ["intermediate"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { }; return [cmd]; } } Rule { inputs: ["intermediate"] Artifact { filePath: "dummy2.final" fileTags: ["final2"] } prepare: { do Utils.sleep(6000); while (!File.exists(project.buildDirectory + "/dummy1.final")); var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { }; return [cmd]; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/concurrent-executor/dummy1.input000066400000000000000000000000001266132464200271120ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/concurrent-executor/dummy2.input000066400000000000000000000000001266132464200271130ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/concurrent-executor/util.js000066400000000000000000000002511266132464200261400ustar00rootroot00000000000000function sleep(timeInMs) { var referenceTime = new Date(); var time = null; do { time = new Date(); } while (time - referenceTime < timeInMs); } qbs-src-1.4.5/tests/auto/blackbox/testdata/dependenciesProperty/000077500000000000000000000000001266132464200250045ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/dependenciesProperty/dependenciesProperty.qbs000066400000000000000000000021471266132464200317120ustar00rootroot00000000000000import qbs 1.0 import qbs.TextFile import qbs.FileInfo Project { Product { type: "deps" name: "product1" Depends { name: "product2" } Transformer { Artifact { fileTags: ["deps"] filePath: product.name + '.deps' } prepare: { var cmd = new JavaScriptCommand(); cmd.description = 'generate ' + FileInfo.fileName(output.filePath); cmd.highlight = 'codegen'; cmd.content = JSON.stringify(product.dependencies); cmd.sourceCode = function() { file = new TextFile(output.filePath, TextFile.WriteOnly); file.truncate(); file.write(content); file.close(); } return cmd; } } } Product { type: "application" consoleApplication: true name: "product2" property string narf: "zort" Depends { name: "cpp" } cpp.defines: ["SMURF"] files: ["product2.cpp"] } } qbs-src-1.4.5/tests/auto/blackbox/testdata/dependenciesProperty/product2.cpp000066400000000000000000000000311266132464200272440ustar00rootroot00000000000000int main() { return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/dynamicMultiplexRule/000077500000000000000000000000001266132464200247715ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/dynamicMultiplexRule/dynamicMultiplexRule.qbs000066400000000000000000000015721266132464200316650ustar00rootroot00000000000000import qbs import qbs.TextFile Project { Product { type: ["stuff"] Group { files: ["one.txt", "two.txt", "three.txt"] fileTags: ["text"] } Rule { multiplex: true inputs: "text" outputFileTags: ["stuff"] outputArtifacts: { return [{ filePath: "stuff-from-" + inputs.text.length + "-inputs", fileTags: ["stuff"] }]; } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write("narf!"); f.close(); } return cmd; } } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/dynamicMultiplexRule/one.txt000066400000000000000000000000001266132464200263010ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/dynamicMultiplexRule/three.txt000066400000000000000000000000001266132464200266270ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/dynamicMultiplexRule/two.txt000066400000000000000000000000001266132464200263310ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/dynamicRuleOutputs/000077500000000000000000000000001266132464200244715ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/dynamicRuleOutputs/after/000077500000000000000000000000001266132464200255725ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/dynamicRuleOutputs/after/numbers.l000066400000000000000000000051551266132464200274300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ /* scanner for integer and float numbers */ %option noyywrap %{ #ifndef CRUCIAL_DEFINE # error CRUCIAL_DEFINE is missing! #endif /* need this for the call to atof() below */ #include %} DIGIT [0-9] %% {DIGIT}+ { printf("integer: %s (%d)\n", yytext, atoi(yytext)); } {DIGIT}+"."{DIGIT}* { printf("float: %s (%g)\n", yytext, atof(yytext)); } "{"[\^{}}\n]*"}" /* eat up one-line comments */ [ \t\n]+ /* eat up whitespace */ . printf("Unexpected character: %s\n", yytext); %% int main(int argc, char **argv) { if (argc > 1) yyin = fopen(argv[1], "r"); else yyin = stdin; yylex(); return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/000077500000000000000000000000001266132464200257335ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/flexoptionsreader.js000066400000000000000000000067231266132464200320360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ // needs import qbs.TextFile function readFlexOptions(filePath) { function splitOptions(str) { var options = []; var opt = ""; var inquote = false; for (var i = 0; i < str.length; ++i) { if (str[i] === '"') { opt += '"'; inquote = !inquote; } else if (str[i] === ' ' && !inquote) { options.push(opt); opt = ""; } else { opt += str[i]; } } if (opt.length) options.push(opt); return options; } function unquote(str) { var l = str.length; if (l > 2 && str[0] === '"' && str[l - 1] === '"') return str.substr(1, l - 2); return str; } function parseOptionLine(result, str) { var options = splitOptions(str); var re = /^(outfile|header-file)=(.*)$/; var reres; for (var k in options) { re.lastIndex = 0; reres = re.exec(options[k]); if (reres === null) continue; result[reres[1]] = unquote(reres[2]); } } var tf = new TextFile(input.filePath); var line; var optrex = /^%option\s+(.*$)/; var res; var options = {}; while (!tf.atEof()) { line = tf.readLine(); if (line === "%%") break; optrex.lastIndex = 0; res = optrex.exec(line); if (res === null) continue; parseOptionLine(options, res[1]); } tf.close(); return options; } qbs-src-1.4.5/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/genlexer.qbs000066400000000000000000000116411266132464200302560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ import qbs 1.0 import qbs.FileInfo import qbs.Probes import qbs.TextFile import "flexoptionsreader.js" as FlexOptionsReader Project { Product { name: "genlexer" type: "application" consoleApplication: true Depends { name: "cpp" } Group { files: ["numbers.l"] fileTags: ["flex"] } Probes.PathProbe { id: flexProbe names: ["flex"] platformPaths: ["/usr/local/bin", "/usr/bin", "/bin"] } property bool isFlexAvailable: flexProbe.found Rule { inputs: ["flex"] outputFileTags: ["c", "hpp"] outputArtifacts: { var options = FlexOptionsReader.readFlexOptions(input.filePath); var sourceFileName = options["outfile"] || "lex.yy.c"; var headerFileName = options["header-file"]; var result = [{ filePath: "GeneratedFiles/" + sourceFileName, fileTags: ["c"], cpp: { defines: ["CRUCIAL_DEFINE"] } }]; if (headerFileName) { result.push({ filePath: "GeneratedFiles/" + headerFileName, fileTags: ["hpp"] }); } return result; } prepare: { var cmd; if (product.isFlexAvailable) { // flex is available. Let's call it. cmd = new Command("flex", [input.filePath]); cmd.workingDirectory = product.buildDirectory + "/GeneratedFiles"; } else { // No flex available here, generate some C source and header. cmd = new JavaScriptCommand(); cmd.sourceFileName = outputs["c"][0].filePath; cmd.headerFileName = outputs["hpp"] ? outputs["hpp"][0].filePath : ""; cmd.sourceCode = function() { var fsrc = new TextFile(sourceFileName, TextFile.WriteOnly); if (headerFileName) { fsrc.write("#include \"" + FileInfo.fileName(headerFileName) + "\"\n\n"); var fhdr = new TextFile(headerFileName, TextFile.WriteOnly); fhdr.write("// a rather empty header file\n"); fhdr.close(); } fsrc.write("\n#ifndef CRUCIAL_DEFINE\n"); fsrc.write("# error CRUCIAL_DEFINE is missing!\n"); fsrc.write("#endif\n\n"); fsrc.write("int main() { return 0; }\n"); fsrc.close(); }; } cmd.description = "flexing " + FileInfo.fileName(input.filePath); return cmd; } } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/numbers.l000066400000000000000000000052551266132464200275720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ /* scanner for integer and float numbers */ %option noyywrap %option outfile="numberscanner.c" header-file="numberscanner.h" %{ #ifndef CRUCIAL_DEFINE # error CRUCIAL_DEFINE is missing! #endif /* need this for the call to atof() below */ #include %} DIGIT [0-9] %% {DIGIT}+ { printf("integer: %s (%d)\n", yytext, atoi(yytext)); } {DIGIT}+"."{DIGIT}* { printf("float: %s (%g)\n", yytext, atof(yytext)); } "{"[\^{}}\n]*"}" /* eat up one-line comments */ [ \t\n]+ /* eat up whitespace */ . printf("Unexpected character: %s\n", yytext); %% int main(int argc, char **argv) { if (argc > 1) yyin = fopen(argv[1], "r"); else yyin = stdin; yylex(); return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/embedInfoPlist/000077500000000000000000000000001266132464200235155ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/embedInfoPlist/embedInfoPlist.qbs000066400000000000000000000004341266132464200271310ustar00rootroot00000000000000import qbs CppApplication { condition: qbs.targetOS.contains("darwin") bundle.isBundle: false files: ["main.m"] cpp.frameworks: ["Foundation"] bundle.infoPlist: { return { "QBS": "org.qt-project.qbs.testdata.embedInfoPlist" }; } } qbs-src-1.4.5/tests/auto/blackbox/testdata/embedInfoPlist/main.m000066400000000000000000000005361266132464200246230ustar00rootroot00000000000000#import int main() { NSDictionary *infoPlist = [[NSBundle mainBundle] infoDictionary]; BOOL success = [[infoPlist objectForKey:@"QBS"] isEqualToString:@"org.qt-project.qbs.testdata.embedInfoPlist"]; fprintf(success ? stdout : stderr, "%s\n", [[infoPlist description] UTF8String]); return success ? 0 : 1; } qbs-src-1.4.5/tests/auto/blackbox/testdata/erroneous/000077500000000000000000000000001266132464200226325ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/erroneous/nonexistentWorkingDir/000077500000000000000000000000001266132464200272105ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/erroneous/nonexistentWorkingDir/project.qbs000066400000000000000000000005361266132464200313710ustar00rootroot00000000000000import qbs Application { name: "kaputt" Transformer { Artifact { filePath: "Stulle" fileTags: ["nutritious"] } prepare: { var cmd = new Command("ls"); cmd.workingDirectory = "/does/not/exist"; cmd.silent = true; return [cmd]; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/export-rule/000077500000000000000000000000001266132464200230775ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/export-rule/blubber.cpp000066400000000000000000000000331266132464200252140ustar00rootroot00000000000000void justSomeFunction() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/export-rule/export-rule.qbs000066400000000000000000000017371266132464200261040ustar00rootroot00000000000000import qbs import qbs.File Project { Application { name: "MyApp" files: ["myapp.blubb"] Depends { name: "blubber" } Depends { name: "cpp" } } StaticLibrary { name: "blubber" files: ["blubber.cpp"] Depends { name: "cpp" } Export { FileTagger { patterns: ["*.blubb"] fileTags: ["blubb"] } Rule { inputs: ["blubb"] Artifact { filePath: input.completeBaseName + ".cpp" fileTags: ["cpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating C++ source file."; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return [cmd]; } } } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/export-rule/myapp.blubb000066400000000000000000000001271266132464200252350ustar00rootroot00000000000000extern void justSomeFunction(); int main() { justSomeFunction(); return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/fileDependencies/000077500000000000000000000000001266132464200240375ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/fileDependencies/awesomelib/000077500000000000000000000000001266132464200261665ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/fileDependencies/awesomelib/awesome.h000066400000000000000000000001471266132464200300010ustar00rootroot00000000000000#include #include "magnificent.h" void doAwesomeStuff() { printf(magnificentMessage); } qbs-src-1.4.5/tests/auto/blackbox/testdata/fileDependencies/awesomelib/magnificent.h000066400000000000000000000001661266132464200306260ustar00rootroot00000000000000#ifndef MAGNIFICENT_H #define MAGNIFICENT_H const char magnificentMessage[] = "Just. Wow."; #endif // MAGNIFICENT_H qbs-src-1.4.5/tests/auto/blackbox/testdata/fileDependencies/fileDependencies.qbs000066400000000000000000000004131266132464200277720ustar00rootroot00000000000000import qbs 1.0 Project { Product { type: "application" consoleApplication: true name: "myapp" Depends { name: "cpp" } cpp.includePaths: ["awesomelib"] files: ["src/narf.h", "src/narf.cpp", "src/zort.cpp"] } } qbs-src-1.4.5/tests/auto/blackbox/testdata/fileDependencies/src/000077500000000000000000000000001266132464200246265ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/fileDependencies/src/narf.cpp000066400000000000000000000001001266132464200262470ustar00rootroot00000000000000#include void doStuff() { doAwesomeStuff(); } qbs-src-1.4.5/tests/auto/blackbox/testdata/fileDependencies/src/narf.h000066400000000000000000000000211266132464200257160ustar00rootroot00000000000000void doStuff(); qbs-src-1.4.5/tests/auto/blackbox/testdata/fileDependencies/src/zort.cpp000066400000000000000000000001001266132464200263170ustar00rootroot00000000000000#include "narf.h" int main() { doStuff(); return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/find-java/000077500000000000000000000000001266132464200224505ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/find-java/find-jar.qbs000066400000000000000000000002761266132464200246560ustar00rootroot00000000000000import qbs Product { Depends { name: "java"; required: false } Probe { configure: { if (java.present) print(java.jarFilePath); } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/frameworkStructure/000077500000000000000000000000001266132464200245275ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/frameworkStructure/BaseResource000066400000000000000000000000001266132464200270220ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/frameworkStructure/Widget.cpp000066400000000000000000000000301266132464200264470ustar00rootroot00000000000000int foo() { return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/frameworkStructure/Widget.h000066400000000000000000000000131266132464200261150ustar00rootroot00000000000000int foo(); qbs-src-1.4.5/tests/auto/blackbox/testdata/frameworkStructure/WidgetPrivate.h000066400000000000000000000000001266132464200274440ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/frameworkStructure/en.lproj/000077500000000000000000000000001266132464200262565ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/frameworkStructure/en.lproj/EnglishResource000066400000000000000000000000001266132464200312700ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/frameworkStructure/frameworkStructure.qbs000066400000000000000000000007701266132464200311600ustar00rootroot00000000000000import qbs Project { property bool includeHeaders: true Library { Depends { name: "cpp" } name: "Widget" bundle.isBundle: true bundle.publicHeaders: project.includeHeaders ? ["Widget.h"] : undefined bundle.privateHeaders: project.includeHeaders ? ["WidgetPrivate.h"] : base bundle.resources: ["BaseResource", "en.lproj/EnglishResource"] files: ["Widget.cpp"].concat(bundle.publicHeaders || []).concat(bundle.privateHeaders || []) } } qbs-src-1.4.5/tests/auto/blackbox/testdata/group-condition-change/000077500000000000000000000000001266132464200251545ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/group-condition-change/group-condition-change.qbs000066400000000000000000000011451266132464200322270ustar00rootroot00000000000000import qbs Project { property bool kaputt: true Product { type: ["kaputt"] Group { name: "kaputt" condition: project.kaputt files: "input_kaputt.txt" fileTags: "input.kaputt" } Rule { inputs: "input.kaputt" Artifact { filePath: "output.kaputt" fileTags: "kaputt" } prepare: { var cmd = new Command("jibbetnich", [output.filePath]); cmd.silent = true; return cmd; } } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/group-condition-change/input_kaputt.txt000066400000000000000000000000001266132464200304320ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/000077500000000000000000000000001266132464200242025ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/groups-in-modules.qbs000066400000000000000000000005751266132464200303110ustar00rootroot00000000000000import qbs Project { Product { Depends { name: "dep" } Depends { name: "helper" } Depends { name: "helper3" required: false } type: ["diamond"] files: [ "rock.coal" ] } Product { name: "dep" Export { Depends { name: "helper4" } } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/modules/000077500000000000000000000000001266132464200256525ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/modules/helper/000077500000000000000000000000001266132464200271315ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/modules/helper/chunk.coal000066400000000000000000000000061266132464200310750ustar00rootroot00000000000000chunk qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/modules/helper/diamondc.c000066400000000000000000000036541266132464200310630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include int main(int argc, char *argv[]) { if (argc < 3) { fprintf(stderr, "usage: diamondc input.coal output.diamond"); return 1; } FILE *in = fopen(argv[1], "r"); if (in) { fclose(in); } else { return 1; } FILE *out = fopen(argv[2], "w"); if (out) { fprintf(out, "diamond\n"); fclose(out); } else { return 1; } return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/modules/helper/helper.qbs000066400000000000000000000021331266132464200311160ustar00rootroot00000000000000import qbs import qbs.FileInfo Module { Depends { name: "cpp" } Depends { name: "helper2" } additionalProductTypes: ["diamond"] Group { name: "Helper Sources" prefix: path + "/" files: ["diamondc.c"] } Group { name: "Additional Chunk" prefix: path + "/" files: ["chunk.coal"] } Group { name: "some other file from helper" prefix: project.sourceDirectory + '/' files: ["someotherfile2.txt"] } FileTagger { patterns: ["*.coal"] fileTags: ["coal"] } Rule { inputs: ["coal"] explicitlyDependsOn: ["application"] Artifact { filePath: FileInfo.joinPaths(product.destinationDirectory, input.baseName + ".diamond") fileTags: ["diamond"] } prepare: { var cmd = new Command(FileInfo.joinPaths(product.buildDirectory, product.targetName), [input.filePath, output.filePath]); cmd.description = "compile " + input.fileName + " => " + output.fileName; return [cmd]; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/modules/helper2/000077500000000000000000000000001266132464200272135ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/modules/helper2/helper2.c000066400000000000000000000000221266132464200307120ustar00rootroot00000000000000void helper2() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/modules/helper2/helper2.qbs000066400000000000000000000004611266132464200312640ustar00rootroot00000000000000import qbs Module { Depends { name: "cpp" } Group { name: "Helper2 Sources" prefix: path + "/" files: ["helper2.c"] } Group { name: "some other file from helper2" prefix: product.sourceDirectory + '/' files: ["someotherfile.txt"] } } qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/modules/helper3/000077500000000000000000000000001266132464200272145ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/modules/helper3/helper3.c000066400000000000000000000000221266132464200307140ustar00rootroot00000000000000void helper3() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/modules/helper3/helper3.qbs000066400000000000000000000003001266132464200312560ustar00rootroot00000000000000import qbs Module { Depends { name: "cpp" } Group { name: "Helper3 Sources" prefix: path + "/" files: ["helper3.c"] } validate: { throw "Nope."; } } qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/modules/helper4/000077500000000000000000000000001266132464200272155ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/modules/helper4/helper4.c000066400000000000000000000000221266132464200307160ustar00rootroot00000000000000void helper4() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/modules/helper4/helper4.qbs000066400000000000000000000002761266132464200312740ustar00rootroot00000000000000import qbs Module { Depends { name: "cpp" } Depends { name: "helper5" } Group { name: "Helper4 Sources" prefix: path + "/" files: ["helper4.c"] } } qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/modules/helper5/000077500000000000000000000000001266132464200272165ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/modules/helper5/helper5.c000066400000000000000000000001011266132464200307160ustar00rootroot00000000000000void helper5() { #ifndef COMPILE_FIX nothatcantwork #endif } qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/modules/helper5/helper5.qbs000066400000000000000000000004071266132464200312720ustar00rootroot00000000000000import qbs Module { Depends { name: "cpp" } Depends { name: "helper6" required: false } Group { name: "Helper5 Sources" prefix: path + "/" files: ["helper5.c"] cpp.defines: ["COMPILE_FIX"] } } qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/modules/helper6/000077500000000000000000000000001266132464200272175ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/modules/helper6/helper6.c000066400000000000000000000000221266132464200307220ustar00rootroot00000000000000void helper6() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/modules/helper6/helper6.qbs000066400000000000000000000003031266132464200312670ustar00rootroot00000000000000import qbs Module { Depends { name: "cpp" } Group { name: "Helper6 Sources" prefix: path + "/" files: ["helper6.c"] } validate: { throw "Go away."; } } qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/rock.coal000066400000000000000000000000051266132464200257730ustar00rootroot00000000000000coal qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/someotherfile.txt000066400000000000000000000000001266132464200275760ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/groups-in-modules/someotherfile2.txt000066400000000000000000000000001266132464200276600ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/000077500000000000000000000000001266132464200212035ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/assetcatalog/000077500000000000000000000000001266132464200236555ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/assetcatalog/MainMenu.xib000066400000000000000000001407211266132464200260770ustar00rootroot00000000000000 Default Left to Right Right to Left Default Left to Right Right to Left qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/assetcatalog/Storyboard.storyboard000066400000000000000000000007311266132464200301200ustar00rootroot00000000000000 qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/assetcatalog/assetcatalogempty.qbs000066400000000000000000000010031266132464200301070ustar00rootroot00000000000000import qbs Project { property bool includeIconset CppApplication { Depends { name: "ib" } files: { var filez = ["main.c", "MainMenu.xib"]; if (project.includeIconset) filez.push("empty.xcassets/empty.iconset"); else filez.push("empty.xcassets"); if (qbs.hostOSVersionMinor >= 10) // need OS X 10.10 to build SBs filez.push("Storyboard.storyboard"); return filez; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/assetcatalog/empty.xcassets/000077500000000000000000000000001266132464200266475ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/assetcatalog/empty.xcassets/empty.iconset/000077500000000000000000000000001266132464200314505ustar00rootroot00000000000000icon_16x16.png000066400000000000000000000063471266132464200337060ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/assetcatalog/empty.xcassets/empty.iconsetPNG  IHDRh6 iCCPICC ProfileH wTS{izW5A`#$BHP+ VTD(@ւb[{_EA] 6T~/=~s|wsߜs."G,BUERIL?kzR2HeP}7O>DxF_@T^7cX?K8ϕcKj9a9qM\Lfs@H`:+š1"0 8>4l &egy'pR19t m(gq F?Cv ;f4$4ؙUg+X:5j\b4Yh8sqY7 Fq(⋲h>[q=MBA\8 s^f"BABb9Iy/c/ .t\ƙ/W#+∳FhJz'L~_Ghř@, )A"ϓb#.RJ,k;`g srwo ѼCp?~19k2IXx{Cx.>_ߏoķo{:A`M 鄹bB9a/8<6H$j͉Pb18@l%v{C$IdM"E8$)tttGDU2PrP VJV)-S*W:tZsa*ٔA"u=5ryF1xQ( J=<J5SQ% aEj3MfE ͤhkihwt:݌KOKks'O e[e2Oyrr *dS?***GUR%rTVP:PWRV[v@Z:IL=H^[z/0f0=>&id33CN栆F<*Sݚ8M3Mf:#w4LЛ7?aՄ 7&|Ԛ*jкEAI^Jg\:u^MdNȝX2n|ݺWuBz[ߤZam 4dpKbUY2]FFFˌS݌ӌ7D,03y`J6u3n10hfnh¬ɬ\˜m^h^gȂnckQcq˒hfijl%fZX YwM"Lr$T3 &ߦΦV6vm&'o1]a[:X9pn9;6;qv;mwpt^ER2jZz׍;}I.R#yxfzb>?eϔ^/#/.nowNnCOS_c_^~~~^K X , R zl\<2?5!.[eײ\c+ßFXEH"Z"ȰȍNMm(vƨѹѿN#NV5Y}̂XF=ŷ%$LMX=}ӯ$$ I {f~>w~K,[k(uQbE,ٿ4so얕-{8^҈446 Nhkl9N:qji#g [_M?6nOk<~ ::\xǥ.7]qxߜ;xZu-]SNqf طܞzN{wgǻ?.yDxTXq'5[}'ا{/k_3kO\1EKWY|:8}{m(zɇK>isǗ/χ~%}f{G###b3Z MKx@QG-:cy=/_ 4 4 3IDAT(c?)  PUm, IENDB`icon_16x16@2x.png000066400000000000000000000064101266132464200342470ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/assetcatalog/empty.xcassets/empty.iconsetPNG  IHDR  iCCPICC ProfileH wTS{izW5A`#$BHP+ VTD(@ւb[{_EA] 6T~/=~s|wsߜs."G,BUERIL?kzR2HeP}7O>DxF_@T^7cX?K8ϕcKj9a9qM\Lfs@H`:+š1"0 8>4l &egy'pR19t m(gq F?Cv ;f4$4ؙUg+X:5j\b4Yh8sqY7 Fq(⋲h>[q=MBA\8 s^f"BABb9Iy/c/ .t\ƙ/W#+∳FhJz'L~_Ghř@, )A"ϓb#.RJ,k;`g srwo ѼCp?~19k2IXx{Cx.>_ߏoķo{:A`M 鄹bB9a/8<6H$j͉Pb18@l%v{C$IdM"E8$)tttGDU2PrP VJV)-S*W:tZsa*ٔA"u=5ryF1xQ( J=<J5SQ% aEj3MfE ͤhkihwt:݌KOKks'O e[e2Oyrr *dS?***GUR%rTVP:PWRV[v@Z:IL=H^[z/0f0=>&id33CN栆F<*Sݚ8M3Mf:#w4LЛ7?aՄ 7&|Ԛ*jкEAI^Jg\:u^MdNȝX2n|ݺWuBz[ߤZam 4dpKbUY2]FFFˌS݌ӌ7D,03y`J6u3n10hfnh¬ɬ\˜m^h^gȂnckQcq˒hfijl%fZX YwM"Lr$T3 &ߦΦV6vm&'o1]a[:X9pn9;6;qv;mwpt^ER2jZz׍;}I.R#yxfzb>?eϔ^/#/.nowNnCOS_c_^~~~^K X , R zl\<2?5!.[eײ\c+ßFXEH"Z"ȰȍNMm(vƨѹѿN#NV5Y}̂XF=ŷ%$LMX=}ӯ$$ I {f~>w~K,[k(uQbE,ٿ4so얕-{8^҈446 Nhkl9N:qji#g [_M?6nOk<~ ::\xǥ.7]qxߜ;xZu-]SNqf طܞzN{wgǻ?.yDxTXq'5[}'ا{/k_3kO\1EKWY|:8}{m(zɇK>isǗ/χ~%}f{G###b3Z MKx@QG-:cy=/_ 4 4 3@IDATH ұ Au#N[G:I}|_PX"PH"+0$B "$Z=.DIENDB`qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/assetcatalog/empty.xcassets/other.imageset/000077500000000000000000000000001266132464200315655ustar00rootroot00000000000000Contents.json000066400000000000000000000005331266132464200341770ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/assetcatalog/empty.xcassets/other.imageset{ "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "icon_16x16.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "icon_16x16@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } }icon_16x16.png000066400000000000000000000063471266132464200340230ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/assetcatalog/empty.xcassets/other.imagesetPNG  IHDRh6 iCCPICC ProfileH wTS{izW5A`#$BHP+ VTD(@ւb[{_EA] 6T~/=~s|wsߜs."G,BUERIL?kzR2HeP}7O>DxF_@T^7cX?K8ϕcKj9a9qM\Lfs@H`:+š1"0 8>4l &egy'pR19t m(gq F?Cv ;f4$4ؙUg+X:5j\b4Yh8sqY7 Fq(⋲h>[q=MBA\8 s^f"BABb9Iy/c/ .t\ƙ/W#+∳FhJz'L~_Ghř@, )A"ϓb#.RJ,k;`g srwo ѼCp?~19k2IXx{Cx.>_ߏoķo{:A`M 鄹bB9a/8<6H$j͉Pb18@l%v{C$IdM"E8$)tttGDU2PrP VJV)-S*W:tZsa*ٔA"u=5ryF1xQ( J=<J5SQ% aEj3MfE ͤhkihwt:݌KOKks'O e[e2Oyrr *dS?***GUR%rTVP:PWRV[v@Z:IL=H^[z/0f0=>&id33CN栆F<*Sݚ8M3Mf:#w4LЛ7?aՄ 7&|Ԛ*jкEAI^Jg\:u^MdNȝX2n|ݺWuBz[ߤZam 4dpKbUY2]FFFˌS݌ӌ7D,03y`J6u3n10hfnh¬ɬ\˜m^h^gȂnckQcq˒hfijl%fZX YwM"Lr$T3 &ߦΦV6vm&'o1]a[:X9pn9;6;qv;mwpt^ER2jZz׍;}I.R#yxfzb>?eϔ^/#/.nowNnCOS_c_^~~~^K X , R zl\<2?5!.[eײ\c+ßFXEH"Z"ȰȍNMm(vƨѹѿN#NV5Y}̂XF=ŷ%$LMX=}ӯ$$ I {f~>w~K,[k(uQbE,ٿ4so얕-{8^҈446 Nhkl9N:qji#g [_M?6nOk<~ ::\xǥ.7]qxߜ;xZu-]SNqf طܞzN{wgǻ?.yDxTXq'5[}'ا{/k_3kO\1EKWY|:8}{m(zɇK>isǗ/χ~%}f{G###b3Z MKx@QG-:cy=/_ 4 4 3IDAT(c?)  PUm, IENDB`icon_16x16@2x.png000066400000000000000000000064101266132464200343640ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/assetcatalog/empty.xcassets/other.imagesetPNG  IHDR  iCCPICC ProfileH wTS{izW5A`#$BHP+ VTD(@ւb[{_EA] 6T~/=~s|wsߜs."G,BUERIL?kzR2HeP}7O>DxF_@T^7cX?K8ϕcKj9a9qM\Lfs@H`:+š1"0 8>4l &egy'pR19t m(gq F?Cv ;f4$4ؙUg+X:5j\b4Yh8sqY7 Fq(⋲h>[q=MBA\8 s^f"BABb9Iy/c/ .t\ƙ/W#+∳FhJz'L~_Ghř@, )A"ϓb#.RJ,k;`g srwo ѼCp?~19k2IXx{Cx.>_ߏoķo{:A`M 鄹bB9a/8<6H$j͉Pb18@l%v{C$IdM"E8$)tttGDU2PrP VJV)-S*W:tZsa*ٔA"u=5ryF1xQ( J=<J5SQ% aEj3MfE ͤhkihwt:݌KOKks'O e[e2Oyrr *dS?***GUR%rTVP:PWRV[v@Z:IL=H^[z/0f0=>&id33CN栆F<*Sݚ8M3Mf:#w4LЛ7?aՄ 7&|Ԛ*jкEAI^Jg\:u^MdNȝX2n|ݺWuBz[ߤZam 4dpKbUY2]FFFˌS݌ӌ7D,03y`J6u3n10hfnh¬ɬ\˜m^h^gȂnckQcq˒hfijl%fZX YwM"Lr$T3 &ߦΦV6vm&'o1]a[:X9pn9;6;qv;mwpt^ER2jZz׍;}I.R#yxfzb>?eϔ^/#/.nowNnCOS_c_^~~~^K X , R zl\<2?5!.[eײ\c+ßFXEH"Z"ȰȍNMm(vƨѹѿN#NV5Y}̂XF=ŷ%$LMX=}ӯ$$ I {f~>w~K,[k(uQbE,ٿ4so얕-{8^҈446 Nhkl9N:qji#g [_M?6nOk<~ ::\xǥ.7]qxߜ;xZu-]SNqf طܞzN{wgǻ?.yDxTXq'5[}'ا{/k_3kO\1EKWY|:8}{m(zɇK>isǗ/χ~%}f{G###b3Z MKx@QG-:cy=/_ 4 4 3@IDATH ұ Au#N[G:I}|_PX"PH"+0$B "$Z=.DIENDB`qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/assetcatalog/main.c000066400000000000000000000000351266132464200247430ustar00rootroot00000000000000int main() { return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/empty-asset-catalogs/000077500000000000000000000000001266132464200252515ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/empty-asset-catalogs/assetcatalog1.xcassets/000077500000000000000000000000001266132464200316405ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/empty-asset-catalogs/assetcatalog1.xcassets/.keep000066400000000000000000000000001266132464200325530ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/empty-asset-catalogs/assetcatalog2.xcassets/000077500000000000000000000000001266132464200316415ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/empty-asset-catalogs/assetcatalog2.xcassets/.keep000066400000000000000000000000001266132464200325540ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/empty-asset-catalogs/main.c000066400000000000000000000000311266132464200263330ustar00rootroot00000000000000int main() { return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/empty-asset-catalogs/multiple-asset-catalogs.qbs000066400000000000000000000002421266132464200325210ustar00rootroot00000000000000import qbs CppApplication { Depends { name: "ib" } files: [ "main.c", "assetcatalog1.xcassets", "assetcatalog2.xcassets" ] } qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/iconset/000077500000000000000000000000001266132464200226475ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/iconset/iconset.qbs000066400000000000000000000001431266132464200250200ustar00rootroot00000000000000import qbs Product { Depends { name: "ib" } type: ["icns"] files: ["white.iconset"] } qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/iconset/white.iconset/000077500000000000000000000000001266132464200254325ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/iconset/white.iconset/icon_16x16.png000066400000000000000000000063471266132464200277470ustar00rootroot00000000000000PNG  IHDRh6 iCCPICC ProfileH wTS{izW5A`#$BHP+ VTD(@ւb[{_EA] 6T~/=~s|wsߜs."G,BUERIL?kzR2HeP}7O>DxF_@T^7cX?K8ϕcKj9a9qM\Lfs@H`:+š1"0 8>4l &egy'pR19t m(gq F?Cv ;f4$4ؙUg+X:5j\b4Yh8sqY7 Fq(⋲h>[q=MBA\8 s^f"BABb9Iy/c/ .t\ƙ/W#+∳FhJz'L~_Ghř@, )A"ϓb#.RJ,k;`g srwo ѼCp?~19k2IXx{Cx.>_ߏoķo{:A`M 鄹bB9a/8<6H$j͉Pb18@l%v{C$IdM"E8$)tttGDU2PrP VJV)-S*W:tZsa*ٔA"u=5ryF1xQ( J=<J5SQ% aEj3MfE ͤhkihwt:݌KOKks'O e[e2Oyrr *dS?***GUR%rTVP:PWRV[v@Z:IL=H^[z/0f0=>&id33CN栆F<*Sݚ8M3Mf:#w4LЛ7?aՄ 7&|Ԛ*jкEAI^Jg\:u^MdNȝX2n|ݺWuBz[ߤZam 4dpKbUY2]FFFˌS݌ӌ7D,03y`J6u3n10hfnh¬ɬ\˜m^h^gȂnckQcq˒hfijl%fZX YwM"Lr$T3 &ߦΦV6vm&'o1]a[:X9pn9;6;qv;mwpt^ER2jZz׍;}I.R#yxfzb>?eϔ^/#/.nowNnCOS_c_^~~~^K X , R zl\<2?5!.[eײ\c+ßFXEH"Z"ȰȍNMm(vƨѹѿN#NV5Y}̂XF=ŷ%$LMX=}ӯ$$ I {f~>w~K,[k(uQbE,ٿ4so얕-{8^҈446 Nhkl9N:qji#g [_M?6nOk<~ ::\xǥ.7]qxߜ;xZu-]SNqf طܞzN{wgǻ?.yDxTXq'5[}'ا{/k_3kO\1EKWY|:8}{m(zɇK>isǗ/χ~%}f{G###b3Z MKx@QG-:cy=/_ 4 4 3IDAT(c?)  PUm, IENDB`qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/iconset/white.iconset/icon_16x16@2x.png000066400000000000000000000064101266132464200303100ustar00rootroot00000000000000PNG  IHDR  iCCPICC ProfileH wTS{izW5A`#$BHP+ VTD(@ւb[{_EA] 6T~/=~s|wsߜs."G,BUERIL?kzR2HeP}7O>DxF_@T^7cX?K8ϕcKj9a9qM\Lfs@H`:+š1"0 8>4l &egy'pR19t m(gq F?Cv ;f4$4ؙUg+X:5j\b4Yh8sqY7 Fq(⋲h>[q=MBA\8 s^f"BABb9Iy/c/ .t\ƙ/W#+∳FhJz'L~_Ghř@, )A"ϓb#.RJ,k;`g srwo ѼCp?~19k2IXx{Cx.>_ߏoķo{:A`M 鄹bB9a/8<6H$j͉Pb18@l%v{C$IdM"E8$)tttGDU2PrP VJV)-S*W:tZsa*ٔA"u=5ryF1xQ( J=<J5SQ% aEj3MfE ͤhkihwt:݌KOKks'O e[e2Oyrr *dS?***GUR%rTVP:PWRV[v@Z:IL=H^[z/0f0=>&id33CN栆F<*Sݚ8M3Mf:#w4LЛ7?aՄ 7&|Ԛ*jкEAI^Jg\:u^MdNȝX2n|ݺWuBz[ߤZam 4dpKbUY2]FFFˌS݌ӌ7D,03y`J6u3n10hfnh¬ɬ\˜m^h^gȂnckQcq˒hfijl%fZX YwM"Lr$T3 &ߦΦV6vm&'o1]a[:X9pn9;6;qv;mwpt^ER2jZz׍;}I.R#yxfzb>?eϔ^/#/.nowNnCOS_c_^~~~^K X , R zl\<2?5!.[eײ\c+ßFXEH"Z"ȰȍNMm(vƨѹѿN#NV5Y}̂XF=ŷ%$LMX=}ӯ$$ I {f~>w~K,[k(uQbE,ٿ4so얕-{8^҈446 Nhkl9N:qji#g [_M?6nOk<~ ::\xǥ.7]qxߜ;xZu-]SNqf طܞzN{wgǻ?.yDxTXq'5[}'ا{/k_3kO\1EKWY|:8}{m(zɇK>isǗ/χ~%}f{G###b3Z MKx@QG-:cy=/_ 4 4 3@IDATH ұ Au#N[G:I}|_PX"PH"+0$B "$Z=.DIENDB`qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/iconsetapp/000077500000000000000000000000001266132464200233505ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/iconsetapp/iconsetapp.qbs000066400000000000000000000001411266132464200262200ustar00rootroot00000000000000import qbs CppApplication { Depends { name: "ib" } files: ["main.c", "white.iconset"] } qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/iconsetapp/main.c000066400000000000000000000000351266132464200244360ustar00rootroot00000000000000int main() { return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/iconsetapp/white.iconset/000077500000000000000000000000001266132464200261335ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/iconsetapp/white.iconset/icon_16x16.png000066400000000000000000000063471266132464200304500ustar00rootroot00000000000000PNG  IHDRh6 iCCPICC ProfileH wTS{izW5A`#$BHP+ VTD(@ւb[{_EA] 6T~/=~s|wsߜs."G,BUERIL?kzR2HeP}7O>DxF_@T^7cX?K8ϕcKj9a9qM\Lfs@H`:+š1"0 8>4l &egy'pR19t m(gq F?Cv ;f4$4ؙUg+X:5j\b4Yh8sqY7 Fq(⋲h>[q=MBA\8 s^f"BABb9Iy/c/ .t\ƙ/W#+∳FhJz'L~_Ghř@, )A"ϓb#.RJ,k;`g srwo ѼCp?~19k2IXx{Cx.>_ߏoķo{:A`M 鄹bB9a/8<6H$j͉Pb18@l%v{C$IdM"E8$)tttGDU2PrP VJV)-S*W:tZsa*ٔA"u=5ryF1xQ( J=<J5SQ% aEj3MfE ͤhkihwt:݌KOKks'O e[e2Oyrr *dS?***GUR%rTVP:PWRV[v@Z:IL=H^[z/0f0=>&id33CN栆F<*Sݚ8M3Mf:#w4LЛ7?aՄ 7&|Ԛ*jкEAI^Jg\:u^MdNȝX2n|ݺWuBz[ߤZam 4dpKbUY2]FFFˌS݌ӌ7D,03y`J6u3n10hfnh¬ɬ\˜m^h^gȂnckQcq˒hfijl%fZX YwM"Lr$T3 &ߦΦV6vm&'o1]a[:X9pn9;6;qv;mwpt^ER2jZz׍;}I.R#yxfzb>?eϔ^/#/.nowNnCOS_c_^~~~^K X , R zl\<2?5!.[eײ\c+ßFXEH"Z"ȰȍNMm(vƨѹѿN#NV5Y}̂XF=ŷ%$LMX=}ӯ$$ I {f~>w~K,[k(uQbE,ٿ4so얕-{8^҈446 Nhkl9N:qji#g [_M?6nOk<~ ::\xǥ.7]qxߜ;xZu-]SNqf طܞzN{wgǻ?.yDxTXq'5[}'ا{/k_3kO\1EKWY|:8}{m(zɇK>isǗ/χ~%}f{G###b3Z MKx@QG-:cy=/_ 4 4 3IDAT(c?)  PUm, IENDB`qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/iconsetapp/white.iconset/icon_16x16@2x.png000066400000000000000000000064101266132464200310110ustar00rootroot00000000000000PNG  IHDR  iCCPICC ProfileH wTS{izW5A`#$BHP+ VTD(@ւb[{_EA] 6T~/=~s|wsߜs."G,BUERIL?kzR2HeP}7O>DxF_@T^7cX?K8ϕcKj9a9qM\Lfs@H`:+š1"0 8>4l &egy'pR19t m(gq F?Cv ;f4$4ؙUg+X:5j\b4Yh8sqY7 Fq(⋲h>[q=MBA\8 s^f"BABb9Iy/c/ .t\ƙ/W#+∳FhJz'L~_Ghř@, )A"ϓb#.RJ,k;`g srwo ѼCp?~19k2IXx{Cx.>_ߏoķo{:A`M 鄹bB9a/8<6H$j͉Pb18@l%v{C$IdM"E8$)tttGDU2PrP VJV)-S*W:tZsa*ٔA"u=5ryF1xQ( J=<J5SQ% aEj3MfE ͤhkihwt:݌KOKks'O e[e2Oyrr *dS?***GUR%rTVP:PWRV[v@Z:IL=H^[z/0f0=>&id33CN栆F<*Sݚ8M3Mf:#w4LЛ7?aՄ 7&|Ԛ*jкEAI^Jg\:u^MdNȝX2n|ݺWuBz[ߤZam 4dpKbUY2]FFFˌS݌ӌ7D,03y`J6u3n10hfnh¬ɬ\˜m^h^gȂnckQcq˒hfijl%fZX YwM"Lr$T3 &ߦΦV6vm&'o1]a[:X9pn9;6;qv;mwpt^ER2jZz׍;}I.R#yxfzb>?eϔ^/#/.nowNnCOS_c_^~~~^K X , R zl\<2?5!.[eײ\c+ßFXEH"Z"ȰȍNMm(vƨѹѿN#NV5Y}̂XF=ŷ%$LMX=}ӯ$$ I {f~>w~K,[k(uQbE,ٿ4so얕-{8^҈446 Nhkl9N:qji#g [_M?6nOk<~ ::\xǥ.7]qxߜ;xZu-]SNqf طܞzN{wgǻ?.yDxTXq'5[}'ا{/k_3kO\1EKWY|:8}{m(zɇK>isǗ/χ~%}f{G###b3Z MKx@QG-:cy=/_ 4 4 3@IDATH ұ Au#N[G:I}|_PX"PH"+0$B "$Z=.DIENDB`qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/multiple-asset-catalogs/000077500000000000000000000000001266132464200257465ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/multiple-asset-catalogs/assetcatalog1.xcassets/000077500000000000000000000000001266132464200323355ustar00rootroot00000000000000other.imageset/000077500000000000000000000000001266132464200351745ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/multiple-asset-catalogs/assetcatalog1.xcassetsContents.json000066400000000000000000000005331266132464200376650ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/multiple-asset-catalogs/assetcatalog1.xcassets/other.imageset{ "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "icon_16x16.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "icon_16x16@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } }icon_16x16.png000066400000000000000000000063471266132464200375110ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/multiple-asset-catalogs/assetcatalog1.xcassets/other.imagesetPNG  IHDRh6 iCCPICC ProfileH wTS{izW5A`#$BHP+ VTD(@ւb[{_EA] 6T~/=~s|wsߜs."G,BUERIL?kzR2HeP}7O>DxF_@T^7cX?K8ϕcKj9a9qM\Lfs@H`:+š1"0 8>4l &egy'pR19t m(gq F?Cv ;f4$4ؙUg+X:5j\b4Yh8sqY7 Fq(⋲h>[q=MBA\8 s^f"BABb9Iy/c/ .t\ƙ/W#+∳FhJz'L~_Ghř@, )A"ϓb#.RJ,k;`g srwo ѼCp?~19k2IXx{Cx.>_ߏoķo{:A`M 鄹bB9a/8<6H$j͉Pb18@l%v{C$IdM"E8$)tttGDU2PrP VJV)-S*W:tZsa*ٔA"u=5ryF1xQ( J=<J5SQ% aEj3MfE ͤhkihwt:݌KOKks'O e[e2Oyrr *dS?***GUR%rTVP:PWRV[v@Z:IL=H^[z/0f0=>&id33CN栆F<*Sݚ8M3Mf:#w4LЛ7?aՄ 7&|Ԛ*jкEAI^Jg\:u^MdNȝX2n|ݺWuBz[ߤZam 4dpKbUY2]FFFˌS݌ӌ7D,03y`J6u3n10hfnh¬ɬ\˜m^h^gȂnckQcq˒hfijl%fZX YwM"Lr$T3 &ߦΦV6vm&'o1]a[:X9pn9;6;qv;mwpt^ER2jZz׍;}I.R#yxfzb>?eϔ^/#/.nowNnCOS_c_^~~~^K X , R zl\<2?5!.[eײ\c+ßFXEH"Z"ȰȍNMm(vƨѹѿN#NV5Y}̂XF=ŷ%$LMX=}ӯ$$ I {f~>w~K,[k(uQbE,ٿ4so얕-{8^҈446 Nhkl9N:qji#g [_M?6nOk<~ ::\xǥ.7]qxߜ;xZu-]SNqf طܞzN{wgǻ?.yDxTXq'5[}'ا{/k_3kO\1EKWY|:8}{m(zɇK>isǗ/χ~%}f{G###b3Z MKx@QG-:cy=/_ 4 4 3IDAT(c?)  PUm, IENDB`icon_16x16@2x.png000066400000000000000000000064101266132464200400520ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/multiple-asset-catalogs/assetcatalog1.xcassets/other.imagesetPNG  IHDR  iCCPICC ProfileH wTS{izW5A`#$BHP+ VTD(@ւb[{_EA] 6T~/=~s|wsߜs."G,BUERIL?kzR2HeP}7O>DxF_@T^7cX?K8ϕcKj9a9qM\Lfs@H`:+š1"0 8>4l &egy'pR19t m(gq F?Cv ;f4$4ؙUg+X:5j\b4Yh8sqY7 Fq(⋲h>[q=MBA\8 s^f"BABb9Iy/c/ .t\ƙ/W#+∳FhJz'L~_Ghř@, )A"ϓb#.RJ,k;`g srwo ѼCp?~19k2IXx{Cx.>_ߏoķo{:A`M 鄹bB9a/8<6H$j͉Pb18@l%v{C$IdM"E8$)tttGDU2PrP VJV)-S*W:tZsa*ٔA"u=5ryF1xQ( J=<J5SQ% aEj3MfE ͤhkihwt:݌KOKks'O e[e2Oyrr *dS?***GUR%rTVP:PWRV[v@Z:IL=H^[z/0f0=>&id33CN栆F<*Sݚ8M3Mf:#w4LЛ7?aՄ 7&|Ԛ*jкEAI^Jg\:u^MdNȝX2n|ݺWuBz[ߤZam 4dpKbUY2]FFFˌS݌ӌ7D,03y`J6u3n10hfnh¬ɬ\˜m^h^gȂnckQcq˒hfijl%fZX YwM"Lr$T3 &ߦΦV6vm&'o1]a[:X9pn9;6;qv;mwpt^ER2jZz׍;}I.R#yxfzb>?eϔ^/#/.nowNnCOS_c_^~~~^K X , R zl\<2?5!.[eײ\c+ßFXEH"Z"ȰȍNMm(vƨѹѿN#NV5Y}̂XF=ŷ%$LMX=}ӯ$$ I {f~>w~K,[k(uQbE,ٿ4so얕-{8^҈446 Nhkl9N:qji#g [_M?6nOk<~ ::\xǥ.7]qxߜ;xZu-]SNqf طܞzN{wgǻ?.yDxTXq'5[}'ا{/k_3kO\1EKWY|:8}{m(zɇK>isǗ/χ~%}f{G###b3Z MKx@QG-:cy=/_ 4 4 3@IDATH ұ Au#N[G:I}|_PX"PH"+0$B "$Z=.DIENDB`qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/multiple-asset-catalogs/assetcatalog2.xcassets/000077500000000000000000000000001266132464200323365ustar00rootroot00000000000000other.imageset/000077500000000000000000000000001266132464200351755ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/multiple-asset-catalogs/assetcatalog2.xcassetsContents.json000066400000000000000000000005331266132464200376660ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/multiple-asset-catalogs/assetcatalog2.xcassets/other.imageset{ "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "icon_16x16.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "icon_16x16@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } }icon_16x16.png000066400000000000000000000063471266132464200375120ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/multiple-asset-catalogs/assetcatalog2.xcassets/other.imagesetPNG  IHDRh6 iCCPICC ProfileH wTS{izW5A`#$BHP+ VTD(@ւb[{_EA] 6T~/=~s|wsߜs."G,BUERIL?kzR2HeP}7O>DxF_@T^7cX?K8ϕcKj9a9qM\Lfs@H`:+š1"0 8>4l &egy'pR19t m(gq F?Cv ;f4$4ؙUg+X:5j\b4Yh8sqY7 Fq(⋲h>[q=MBA\8 s^f"BABb9Iy/c/ .t\ƙ/W#+∳FhJz'L~_Ghř@, )A"ϓb#.RJ,k;`g srwo ѼCp?~19k2IXx{Cx.>_ߏoķo{:A`M 鄹bB9a/8<6H$j͉Pb18@l%v{C$IdM"E8$)tttGDU2PrP VJV)-S*W:tZsa*ٔA"u=5ryF1xQ( J=<J5SQ% aEj3MfE ͤhkihwt:݌KOKks'O e[e2Oyrr *dS?***GUR%rTVP:PWRV[v@Z:IL=H^[z/0f0=>&id33CN栆F<*Sݚ8M3Mf:#w4LЛ7?aՄ 7&|Ԛ*jкEAI^Jg\:u^MdNȝX2n|ݺWuBz[ߤZam 4dpKbUY2]FFFˌS݌ӌ7D,03y`J6u3n10hfnh¬ɬ\˜m^h^gȂnckQcq˒hfijl%fZX YwM"Lr$T3 &ߦΦV6vm&'o1]a[:X9pn9;6;qv;mwpt^ER2jZz׍;}I.R#yxfzb>?eϔ^/#/.nowNnCOS_c_^~~~^K X , R zl\<2?5!.[eײ\c+ßFXEH"Z"ȰȍNMm(vƨѹѿN#NV5Y}̂XF=ŷ%$LMX=}ӯ$$ I {f~>w~K,[k(uQbE,ٿ4so얕-{8^҈446 Nhkl9N:qji#g [_M?6nOk<~ ::\xǥ.7]qxߜ;xZu-]SNqf طܞzN{wgǻ?.yDxTXq'5[}'ا{/k_3kO\1EKWY|:8}{m(zɇK>isǗ/χ~%}f{G###b3Z MKx@QG-:cy=/_ 4 4 3IDAT(c?)  PUm, IENDB`icon_16x16@2x.png000066400000000000000000000064101266132464200400530ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/multiple-asset-catalogs/assetcatalog2.xcassets/other.imagesetPNG  IHDR  iCCPICC ProfileH wTS{izW5A`#$BHP+ VTD(@ւb[{_EA] 6T~/=~s|wsߜs."G,BUERIL?kzR2HeP}7O>DxF_@T^7cX?K8ϕcKj9a9qM\Lfs@H`:+š1"0 8>4l &egy'pR19t m(gq F?Cv ;f4$4ؙUg+X:5j\b4Yh8sqY7 Fq(⋲h>[q=MBA\8 s^f"BABb9Iy/c/ .t\ƙ/W#+∳FhJz'L~_Ghř@, )A"ϓb#.RJ,k;`g srwo ѼCp?~19k2IXx{Cx.>_ߏoķo{:A`M 鄹bB9a/8<6H$j͉Pb18@l%v{C$IdM"E8$)tttGDU2PrP VJV)-S*W:tZsa*ٔA"u=5ryF1xQ( J=<J5SQ% aEj3MfE ͤhkihwt:݌KOKks'O e[e2Oyrr *dS?***GUR%rTVP:PWRV[v@Z:IL=H^[z/0f0=>&id33CN栆F<*Sݚ8M3Mf:#w4LЛ7?aՄ 7&|Ԛ*jкEAI^Jg\:u^MdNȝX2n|ݺWuBz[ߤZam 4dpKbUY2]FFFˌS݌ӌ7D,03y`J6u3n10hfnh¬ɬ\˜m^h^gȂnckQcq˒hfijl%fZX YwM"Lr$T3 &ߦΦV6vm&'o1]a[:X9pn9;6;qv;mwpt^ER2jZz׍;}I.R#yxfzb>?eϔ^/#/.nowNnCOS_c_^~~~^K X , R zl\<2?5!.[eײ\c+ßFXEH"Z"ȰȍNMm(vƨѹѿN#NV5Y}̂XF=ŷ%$LMX=}ӯ$$ I {f~>w~K,[k(uQbE,ٿ4so얕-{8^҈446 Nhkl9N:qji#g [_M?6nOk<~ ::\xǥ.7]qxߜ;xZu-]SNqf طܞzN{wgǻ?.yDxTXq'5[}'ا{/k_3kO\1EKWY|:8}{m(zɇK>isǗ/χ~%}f{G###b3Z MKx@QG-:cy=/_ 4 4 3@IDATH ұ Au#N[G:I}|_PX"PH"+0$B "$Z=.DIENDB`qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/multiple-asset-catalogs/main.c000066400000000000000000000000311266132464200270300ustar00rootroot00000000000000int main() { return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/ib/multiple-asset-catalogs/multiple-asset-catalogs.qbs000066400000000000000000000002421266132464200332160ustar00rootroot00000000000000import qbs CppApplication { Depends { name: "ib" } files: [ "main.c", "assetcatalog1.xcassets", "assetcatalog2.xcassets" ] } qbs-src-1.4.5/tests/auto/blackbox/testdata/inputs-from-dependencies/000077500000000000000000000000001266132464200255205ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/inputs-from-dependencies/file1.txt000066400000000000000000000000001266132464200272470ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/inputs-from-dependencies/file2.txt000066400000000000000000000000001266132464200272500ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/inputs-from-dependencies/file3.txt000066400000000000000000000000001266132464200272510ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/inputs-from-dependencies/file4.txt000066400000000000000000000000001266132464200272520ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/inputs-from-dependencies/project.qbs000066400000000000000000000023471266132464200277030ustar00rootroot00000000000000import qbs Project { Product { name: "TextFileContainer1" type: "txt_container" Group { files: ["file1.txt", "file2.txt"] fileTags: "txt" } } Product { name: "TextFileContainer2" Group { files: ["file3.txt"] fileTags: "txt" } } Product { name: "TextFileContainer3" Group { files: ["file4.txt"] fileTags: "txt" } } Product { name: "TextFileGatherer" type: "printed_txt" Depends { name: "TextFileContainer1" } Depends { name: "TextFileContainer2" } Rule { inputsFromDependencies: "txt" multiplex: true Artifact { filePath: "blubb" fileTags: "printed_txt" alwaysUpdated: false } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Gathering text files"; cmd.sourceCode = function() { for (i in inputs.txt) print("\t" + inputs.txt[i].filePath); }; return cmd; } } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/install-tree/000077500000000000000000000000001266132464200232145ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/install-tree/data/000077500000000000000000000000001266132464200241255ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/install-tree/data/foo.txt000066400000000000000000000000001266132464200254370ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/install-tree/data/subdir1/000077500000000000000000000000001266132464200254765ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/install-tree/data/subdir1/bar.txt000066400000000000000000000000001266132464200267710ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/install-tree/data/subdir2/000077500000000000000000000000001266132464200254775ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/install-tree/data/subdir2/baz.txt000066400000000000000000000000001266132464200270020ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/install-tree/main.cpp000066400000000000000000000000311266132464200246360ustar00rootroot00000000000000int main() { return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/install-tree/project.qbs000066400000000000000000000003141266132464200253670ustar00rootroot00000000000000import qbs CppApplication { files: ["main.cpp"] Group { files: ["data/**/*.txt"] qbs.install: true qbs.installDir: "content" qbs.installSourceBase: "data" } } qbs-src-1.4.5/tests/auto/blackbox/testdata/installable/000077500000000000000000000000001266132464200231035ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/installable/installable.qbs000066400000000000000000000022051266132464200261030ustar00rootroot00000000000000import qbs import qbs.TextFile Project { CppApplication { type: ["application"] name: "app" Group { files: ["main.cpp"] qbs.install: true } Group { fileTagsFilter: product.type qbs.install: true } } Product { name: "install-list" type: ["install-list"] Depends { name: "app" } Rule { multiplex: true inputsFromDependencies: ["installable"] Artifact { filePath: "installed-files.txt" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating " + output.fileName; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.WriteOnly); for (var i = 0; i < inputs.installable.length; ++i) file.writeLine(inputs.installable[i].filePath); file.close(); }; return [cmd]; } } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/installable/main.cpp000066400000000000000000000000161266132464200245300ustar00rootroot00000000000000int main() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/installed-source-files/000077500000000000000000000000001266132464200251665ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/installed-source-files/main.cpp000066400000000000000000000000311266132464200266100ustar00rootroot00000000000000int main() { return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/installed-source-files/project.qbs000066400000000000000000000006111266132464200273410ustar00rootroot00000000000000import qbs CppApplication { consoleApplication: true files: ["main.cpp"] Group { fileTagsFilter: ["cpp"] qbs.install: true } Group { // this overwrites the properties of the group below fileTagsFilter: ["text"] qbs.install: true } Group { files: ["readme.txt"] fileTags: ["text"] qbs.install: false } } qbs-src-1.4.5/tests/auto/blackbox/testdata/installed-source-files/readme.txt000066400000000000000000000000261266132464200271620ustar00rootroot00000000000000important information qbs-src-1.4.5/tests/auto/blackbox/testdata/installed-transformer-output/000077500000000000000000000000001266132464200264665ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/installed-transformer-output/qbs668.qbs000066400000000000000000000013331266132464200302260ustar00rootroot00000000000000import qbs 1.0 import qbs.TextFile Product { name: "install-test" Group { qbs.install: true qbs.installDir: "textfiles" fileTagsFilter: "text" } Transformer { Artifact { filePath: "HelloWorld.txt" fileTags: ["text"] } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating file:'" + output.fileName + "'"; cmd.highlight = "codegen"; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.WriteOnly); file.writeLine("Hello World!") file.close(); } return cmd; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/installed_artifact/000077500000000000000000000000001266132464200244455ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/installed_artifact/installed_artifact.qbs000066400000000000000000000005741266132464200310160ustar00rootroot00000000000000import qbs 1.0 Application { name: "installedApp" type: "application" consoleApplication: true Depends { name: "cpp" } Group { files: "main.cpp" qbs.install: true qbs.installDir: "src" } qbs.installPrefix: "/usr" Group { fileTagsFilter: "application" qbs.install: true qbs.installDir: "bin" } } qbs-src-1.4.5/tests/auto/blackbox/testdata/installed_artifact/main.cpp000066400000000000000000000000161266132464200260720ustar00rootroot00000000000000int main() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/installpackage/000077500000000000000000000000001266132464200235735ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/installpackage/installpackage.qbs000066400000000000000000000017221266132464200272660ustar00rootroot00000000000000import qbs Project { QtApplication { name: "public_tool" Depends { name: "mylib" } files: ["main.cpp"] Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "bin" } } QtApplication { name: "internal_tool" Depends { name: "mylib" } files: ["main.cpp"] } DynamicLibrary { name: "mylib" Depends { name: "Qt.core" } files: ["lib.cpp"] Group { name: "public headers" files: ["lib.h"] qbs.install: true qbs.installDir: "include" } Group { fileTagsFilter: product.type qbs.install: true qbs.installDir: "lib" } } InstallPackage { archiver.type: "tar" builtByDefault: true name: "tar-package" Depends { name: "public_tool" } Depends { name: "mylib" } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/installpackage/lib.cpp000066400000000000000000000000361266132464200250440ustar00rootroot00000000000000#include "lib.h" void f() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/installpackage/lib.h000066400000000000000000000002151266132464200245100ustar00rootroot00000000000000#include #ifdef MYLIB #define MYLIB_EXPORT Q_DECL_EXPORT #else #define MYLIB_EXPORT Q_DECL_IMPORT #endif MYLIB_EXPORT void f(); qbs-src-1.4.5/tests/auto/blackbox/testdata/installpackage/main.cpp000066400000000000000000000000521266132464200252200ustar00rootroot00000000000000#include "lib.h" int main() { f(); } qbs-src-1.4.5/tests/auto/blackbox/testdata/java/000077500000000000000000000000001266132464200215325ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/java/Car.java000066400000000000000000000005221266132464200231010ustar00rootroot00000000000000class Car implements Vehicle { private InternalCombustionEngine engine; public Car() { engine = new InternalCombustionEngine(); } public void go() { System.out.println("Driving!"); engine.run(); } public class InternalCombustionEngine { public native void run(); } } qbs-src-1.4.5/tests/auto/blackbox/testdata/java/HelloWorld.java000066400000000000000000000002141266132464200244450ustar00rootroot00000000000000package io.qt.qbs; public class HelloWorld { public static void main(String[] args) { System.out.println("Tach."); } } qbs-src-1.4.5/tests/auto/blackbox/testdata/java/Jet.java000066400000000000000000000001511266132464200231140ustar00rootroot00000000000000class Jet implements Vehicle { public void go() { System.out.println("Flying!"); } } qbs-src-1.4.5/tests/auto/blackbox/testdata/java/NoPackage.java000066400000000000000000000001461266132464200242260ustar00rootroot00000000000000// package this.should.not.be.parsed; public class NoPackage { public static void doSomething() {} } qbs-src-1.4.5/tests/auto/blackbox/testdata/java/RandomStuff.java000066400000000000000000000001211266132464200246170ustar00rootroot00000000000000package glob; public class RandomStuff { public static void bar() { } } qbs-src-1.4.5/tests/auto/blackbox/testdata/java/Ship.java000066400000000000000000000003641266132464200233030ustar00rootroot00000000000000class Ship implements Vehicle { public boolean isInSpace; public void go() { if (isInSpace) System.out.println("Flying (this is a space ship)!"); else System.out.println("Sailing!"); } } qbs-src-1.4.5/tests/auto/blackbox/testdata/java/Vehicle.java000066400000000000000000000000541266132464200237530ustar00rootroot00000000000000interface Vehicle { public void go(); } qbs-src-1.4.5/tests/auto/blackbox/testdata/java/Vehicles.java000066400000000000000000000014231266132464200241370ustar00rootroot00000000000000import java.util.ArrayList; import glob.RandomStuff; class Vehicles { public static void main(String[] args) { System.loadLibrary("native"); RandomStuff.bar(); ArrayList vehicles = new ArrayList(); for (int i = 0; i < 3; i++) { vehicles.add(new Car()); } for (int i = 0; i < 3; i++) { vehicles.add(new Jet()); } for (int i = 0; i < 4; i++) { Ship ship = new Ship(); ship.isInSpace = i % 2 == 0; vehicles.add(ship); } for (int i = 0; i < vehicles.size(); i++) { vehicles.get(i).go(); } // doesn't compile, must be a bug // delete vehicles; } } qbs-src-1.4.5/tests/auto/blackbox/testdata/java/engine.c000066400000000000000000000005171266132464200231460ustar00rootroot00000000000000#include // javac 1.8 is required to generate native headers #ifdef JNI_VERSION_1_8 #include "Car_InternalCombustionEngine.h" #endif JNIEXPORT void JNICALL Java_Car_00024InternalCombustionEngine_run(JNIEnv *env, jobject obj) { printf("Native code performing complex internal combustion process (%p, %p)!\n", env, obj); } qbs-src-1.4.5/tests/auto/blackbox/testdata/java/vehicles.qbs000066400000000000000000000041131266132464200240420ustar00rootroot00000000000000import qbs import qbs.FileInfo Project { DynamicLibrary { Depends { name: "cpp" } Depends { name: "car_jar" } bundle.isBundle: false name: "native" files: ["engine.c"] Group { fileTagsFilter: ["dynamiclibrary"] qbs.install: true } } JavaClassCollection { Depends { name: "random_stuff" } name: "class_collection" java.additionalCompilerFlags: ["-Xlint:all"] files: [ "Car.java", "HelloWorld.java", "Jet.java", "NoPackage.java", "Ship.java", "Vehicle.java", "Vehicles.java" ] Export { Depends { name: "java" } java.manifestClassPath: [product.targetName + ".jar"] } } JavaJarFile { name: "random_stuff" files: ["RandomStuff.java"] Group { fileTagsFilter: ["java.jar"] qbs.install: true } Export { Depends { name: "java" } java.manifestClassPath: [product.targetName + ".jar"] } } JavaJarFile { name: "car_jar" files: ["Car.java", "Vehicle.java"] property stringList cppIncludePaths: { var paths = java.jdkIncludePaths; if (java.compilerVersionMinor >= 8) { paths.push(buildDirectory); // generated JNI headers } return paths; } Export { Depends { name: "cpp" } cpp.systemIncludePaths: product.cppIncludePaths Depends { name: "java" } java.manifestClassPath: [product.targetName + ".jar"] } Group { fileTagsFilter: ["java.jar"] qbs.install: true } } JavaJarFile { Depends { name: "random_stuff" } Depends { name: "car_jar" } Depends { name: "native" } name: "jar_file" entryPoint: "Vehicles" files: ["Jet.java", "Ship.java", "Vehicles.java"] Group { fileTagsFilter: ["java.jar"] qbs.install: true } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/jsextensions-file/000077500000000000000000000000001266132464200242625ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/jsextensions-file/file.qbs000066400000000000000000000031721266132464200257130ustar00rootroot00000000000000import qbs import qbs.File import qbs.FileInfo import qbs.TextFile Product { type: ["dummy"] Transformer { Artifact { filePath: "dummy.txt" fileTags: ["dummy"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var origPath = FileInfo.joinPaths(product.sourceDirectory, "original.txt"); var copyPath = FileInfo.joinPaths(product.sourceDirectory, "copy.txt"); print("copy path: "+copyPath); var original = new TextFile(origPath, TextFile.WriteOnly); original.close(); File.copy(origPath, copyPath); var origTimestamp = File.lastModified(origPath); var copyTimestamp = File.lastModified(copyPath); if (origTimestamp > copyTimestamp) throw new Error("Older file has newer timestamp."); File.remove(origPath); var copy = new TextFile(copyPath, TextFile.WriteOnly); copy.writeLine(File.exists(origPath)); copy.writeLine(File.exists(copyPath)); copy.close(); var zePath = FileInfo.joinPaths(product.sourceDirectory, "zePath"); if (File.exists(zePath)) throw new Error(zePath + " already exists."); var created = File.makePath(zePath); if (!created || !File.exists(zePath)) throw new Error("zePath was not created."); }; return [cmd]; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/jsextensions-fileinfo/000077500000000000000000000000001266132464200251365ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/jsextensions-fileinfo/fileinfo.qbs000066400000000000000000000040131266132464200274360ustar00rootroot00000000000000import qbs import qbs.FileInfo import qbs.TextFile Product { type: ["dummy"] Transformer { Artifact { filePath: "dummy.txt" fileTags: ["dummy"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var output = new TextFile(FileInfo.joinPaths(product.sourceDirectory, "output.txt"), TextFile.WriteOnly); output.writeLine(FileInfo.baseName("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.completeBaseName("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.fileName("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.fromWindowsSeparators("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.fromWindowsSeparators("c:\\tmp\\blubb.tar.gz")); output.writeLine(FileInfo.isAbsolutePath("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.isAbsolutePath("c:\\tmp\\blubb.tar.gz")); output.writeLine(FileInfo.isAbsolutePath("blubb.tar.gz")); output.writeLine(FileInfo.isAbsolutePath("../blubb.tar.gz")); output.writeLine(FileInfo.joinPaths("/", "tmp", "blubb.tar.gz")); output.writeLine(FileInfo.path("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.path("/tmp/")); output.writeLine(FileInfo.path("/")); output.writeLine(FileInfo.path("d:/")); output.writeLine(FileInfo.relativePath("/tmp", "/tmp/blubb.tar.gz")); output.writeLine(FileInfo.relativePath("/", "/tmp/blubb.tar.gz")); output.writeLine(FileInfo.relativePath("/tmp", "/blubb.tar.gz")); output.writeLine(FileInfo.toWindowsSeparators("/tmp/blubb.tar.gz")); output.writeLine(FileInfo.toWindowsSeparators("c:\\tmp\\blubb.tar.gz")); output.close(); }; return [cmd]; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/jsextensions-process/000077500000000000000000000000001266132464200250215ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/jsextensions-process/process.qbs000066400000000000000000000037421266132464200272140ustar00rootroot00000000000000import qbs import qbs.FileInfo import qbs.Process import qbs.TextFile Project { property string qbsFilePath Product { Depends { name: "Qt.core" } type: ["dummy"] Transformer { Artifact { filePath: "dummy.txt" fileTags: ["dummy"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { // Synchronous run, successful. var process = new Process(); var pathVal = [process.getEnv("PATH"), product.moduleProperty("Qt.core", "binPath")] .join(product.moduleProperty("qbs", "pathListSeparator")); process.setEnv("PATH", pathVal); process.exec(project.qbsFilePath, ["help"], true); var output = new TextFile("output.txt", TextFile.WriteOnly); output.writeLine(process.exitCode()); output.writeLine(process.readLine()); process.close(); // Asynchronous run, successful. process = new Process(); process.setEnv("PATH", pathVal); output.writeLine(process.start(project.qbsFilePath, ["help"])); output.writeLine(process.waitForFinished()); output.writeLine(process.exitCode()); output.writeLine(process.readLine()); process.close(); // Asynchronous run, unsuccessful. process = new Process(); output.writeLine(process.start("blubb", [])); process.close(); // TODO: Test all the other Process methods as well. output.close(); }; return [cmd]; } } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/jsextensions-propertylist/000077500000000000000000000000001266132464200261235ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/jsextensions-propertylist/propertylist.qbs000066400000000000000000000111151266132464200314110ustar00rootroot00000000000000import qbs import qbs.Process import qbs.PropertyList import qbs.TextFile Product { type: { var plistobj = new PropertyList(); if (!plistobj.isEmpty()) { throw "newly created PropertyList was not empty!"; } if (plistobj.format() !== undefined) { throw "newly created PropertyList did not have an undefined format"; } plistobj.clear(); if (!plistobj.isEmpty() || plistobj.format() !== undefined) { throw "clear() somehow had an effect on an empty PropertyList"; } plistobj.readFromString('{"key":["value"]}'); if (plistobj.isEmpty() || plistobj.format() !== "json") { throw "readFromString did not set format to JSON or object thinks it is empty"; } plistobj.clear(); if (!plistobj.isEmpty() || plistobj.format() !== undefined) { throw "clear() had no effect on a non-empty PropertyList"; } var obj = { "Array": ["ListItem1", "ListItem2", "ListItem3"], "Integer": 1, "Boolean": true, "String": "otherString" }; var infoplist = new TextFile("test.xml", TextFile.WriteOnly); infoplist.write(JSON.stringify(obj)); infoplist.close(); var process = new Process(); process.exec("plutil", ["-convert", "xml1", "test.xml"]); process.close(); var xmlfile = new TextFile("test.xml", TextFile.ReadOnly); var propertyList = new PropertyList(); propertyList.readFromString(xmlfile.readAll()); xmlfile.close(); var jsontextfile = new TextFile("test.json", TextFile.WriteOnly); jsontextfile.write(propertyList.toJSON()); jsontextfile.close(); propertyList.writeToFile("test2.json", "json-compact"); propertyList.writeToFile("test3.json", "json-pretty"); process = new Process(); process.exec("plutil", ["-convert", "json", "test.xml"]); process.close(); propertyList = new PropertyList(); propertyList.readFromFile("test.xml"); if (propertyList.format() !== "json") { // yes, JSON -- ignore the file extension throw "expected property list format json but got " + propertyList.format(); } if (propertyList.isEmpty()) { throw "PropertyList was 'empty' after being loaded with data"; } var opensteptextfile = new TextFile("test.openstep.plist", TextFile.WriteOnly); opensteptextfile.write('{ rootObject = ( "val1", "val3", "val5", /* comment */ "val7", "val9", ); }'); opensteptextfile.close(); propertyList = new PropertyList(); propertyList.readFromFile("test.openstep.plist"); if (propertyList.format() !== "openstep") { throw "expected property list format openstep but got " + propertyList.format(); } var jsonObj = JSON.parse(propertyList.toJSON()); if (jsonObj["rootObject"].length != 5) { throw "going from OpenStep to a JSON string to a JSON object somehow broke"; } propertyList.clear(); propertyList.readFromString('foobarz'); jsonObj = JSON.parse(propertyList.toJSON()); if (jsonObj["foo"] !== "barz") { throw "the XML plist did not get parsed properly"; } propertyList.writeToFile("woof.xml", "xml1"); propertyList.readFromFile("woof.xml"); if (propertyList.format() !== "xml1") { throw "round trip writing and reading XML failed"; } propertyList.writeToFile("woof.plist", "binary1"); propertyList.readFromFile("woof.plist"); if (propertyList.format() !== "binary1") { throw "round trip writing and reading binary failed"; } if (jsonObj["foo"] !== "barz") { throw "the binary plist did not get parsed properly"; } if (propertyList.toString("json") !== propertyList.toString("json-compact") || propertyList.toJSON() !== propertyList.toJSON("compact")) { throw "json and json-compact formats were not equivalent"; } if (propertyList.toString("json") === propertyList.toString("json-pretty") || propertyList.toJSON() === propertyList.toJSON("pretty")) { throw "json and json-pretty formats were not different"; } if (propertyList.toString("xml1") !== propertyList.toXMLString()) { throw 'toString("xml1") and toXMLString() were not equivalent'; } return "Pineapple Steve"; } } qbs-src-1.4.5/tests/auto/blackbox/testdata/jsextensions-temporarydir/000077500000000000000000000000001266132464200260645ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/jsextensions-temporarydir/jsextensions-temporarydir.qbs000066400000000000000000000011471266132464200340510ustar00rootroot00000000000000import qbs import qbs.File import qbs.TemporaryDir Product { targetName: { var dir; var dirPath; try { dir = new TemporaryDir(); dirPath = dir.path(); if (!dirPath) throw "path is empty"; if (!dir.isValid()) throw "dir is not valid"; if (!File.exists(dirPath)) throw "dir does not exist"; } finally { if (!dir.remove()) throw "could not remove"; } if (File.exists(dirPath)) throw "dir was not removed"; } } qbs-src-1.4.5/tests/auto/blackbox/testdata/jsextensions-textfile/000077500000000000000000000000001266132464200251675ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/jsextensions-textfile/textfile.qbs000066400000000000000000000021271266132464200275240ustar00rootroot00000000000000import qbs import qbs.TextFile Product { type: ["dummy"] Transformer { Artifact { filePath: "dummy.txt" fileTags: ["dummy"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var file1 = new TextFile("file1.txt", TextFile.WriteOnly); file1.write("First line.\nSecond line.\nThird line."); file1.close(); file1 = new TextFile("file1.txt", TextFile.ReadWrite); var file2 = new TextFile("file2.txt", TextFile.WriteOnly); file2.writeLine(file1.atEof()); while (true) { var line = file1.readLine(); if (!line || line.length == 0) break; file2.writeLine(line); } file1.truncate(); file2.writeLine(file1.atEof()); file1.close(); file2.close(); }; return [cmd]; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/list-properties-with-outer/000077500000000000000000000000001266132464200260635ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/list-properties-with-outer/dummy.txt000066400000000000000000000000001266132464200277450ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/list-properties-with-outer/modules/000077500000000000000000000000001266132464200275335ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/list-properties-with-outer/modules/higher/000077500000000000000000000000001266132464200310015ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/list-properties-with-outer/modules/higher/higher.qbs000066400000000000000000000001241266132464200327530ustar00rootroot00000000000000import qbs Module { Depends { name: "lower" } lower.listProp: ["higher"] } qbs-src-1.4.5/tests/auto/blackbox/testdata/list-properties-with-outer/modules/lower/000077500000000000000000000000001266132464200306635ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/list-properties-with-outer/modules/lower/lower.qbs000066400000000000000000000010151266132464200325170ustar00rootroot00000000000000import qbs Module { property stringList listProp Rule { inputs: ["intype"] Artifact { filePath: "dummy.out" fileTags: ["outtype"] } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { var listProp = input.moduleProperty("lower", "listProp"); print("listProp: " + JSON.stringify(listProp)); } return [cmd]; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/list-properties-with-outer/project.qbs000066400000000000000000000003511266132464200302370ustar00rootroot00000000000000import qbs Product { type: ["outtype"] Depends { name: "higher" } lower.listProp: ["product"] Group { files: ["dummy.txt"] fileTags: ["intype"] lower.listProp: outer.concat(["group"]) } } qbs-src-1.4.5/tests/auto/blackbox/testdata/list-property-order/000077500000000000000000000000001266132464200245575ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/list-property-order/dummy.txt000066400000000000000000000000001266132464200264410ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/list-property-order/modules/000077500000000000000000000000001266132464200262275ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/list-property-order/modules/higher1/000077500000000000000000000000001266132464200275565ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/list-property-order/modules/higher1/higher1.qbs000066400000000000000000000001251266132464200316120ustar00rootroot00000000000000import qbs Module { Depends { name: "lower" } lower.listProp: ["higher1"] } qbs-src-1.4.5/tests/auto/blackbox/testdata/list-property-order/modules/higher2/000077500000000000000000000000001266132464200275575ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/list-property-order/modules/higher2/higher2.qbs000066400000000000000000000001251266132464200316140ustar00rootroot00000000000000import qbs Module { Depends { name: "lower" } lower.listProp: ["higher2"] } qbs-src-1.4.5/tests/auto/blackbox/testdata/list-property-order/modules/higher3/000077500000000000000000000000001266132464200275605ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/list-property-order/modules/higher3/higher3.qbs000066400000000000000000000001251266132464200316160ustar00rootroot00000000000000import qbs Module { Depends { name: "lower" } lower.listProp: ["higher3"] } qbs-src-1.4.5/tests/auto/blackbox/testdata/list-property-order/modules/lower/000077500000000000000000000000001266132464200273575ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/list-property-order/modules/lower/lower.qbs000066400000000000000000000011011266132464200312070ustar00rootroot00000000000000import qbs Module { property stringList listProp Rule { inputs: ["intype"] Artifact { filePath: "dummy.out" fileTags: "outtype" } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = function() { print("listProp = " + JSON.stringify(product.moduleProperty("lower", "listProp"))); }; var prop = product.moduleProperty("lowerlevel", "prop"); cmd.silent = true; return [cmd]; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/list-property-order/product.qbs000066400000000000000000000003551266132464200267510ustar00rootroot00000000000000import qbs Product { type: "outtype" name: "toplevel" Depends { name: "higher1" } Depends { name: "higher2" } Depends { name: "higher3" } Group { files: ["dummy.txt"] fileTags: ["intype"] } } qbs-src-1.4.5/tests/auto/blackbox/testdata/loadablemodule/000077500000000000000000000000001266132464200235625ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/loadablemodule/exported.cpp000066400000000000000000000001171266132464200261170ustar00rootroot00000000000000#include "exported.h" extern "C" { int foo() { return 42; } } qbs-src-1.4.5/tests/auto/blackbox/testdata/loadablemodule/exported.h000066400000000000000000000001101266132464200255550ustar00rootroot00000000000000#include extern "C" { Q_DECL_EXPORT int foo(); } qbs-src-1.4.5/tests/auto/blackbox/testdata/loadablemodule/loadablemodule.qbs000066400000000000000000000013031266132464200272370ustar00rootroot00000000000000import qbs Project { LoadableModule { Depends { name: "cpp" } Depends { name: "bundle" } Depends { name: "Qt.core" } bundle.isBundle: false name: "CoolPlugIn" files: ["exported.cpp", "exported.h"] Group { fileTagsFilter: product.type qbs.install: true } } CppApplication { Depends { name: "cpp" } Depends { name: "CoolPlugIn" } Depends { name: "bundle" } Depends { name: "Qt.core" } bundle.isBundle: false name: "CoolApp" files: ["main.cpp"] Group { fileTagsFilter: product.type qbs.install: true } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/loadablemodule/main.cpp000066400000000000000000000043211266132464200252120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 Jake Petroules. ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the examples of the Qt Build Suite. ** ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of The Qt Company Ltd and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ****************************************************************************/ #include #include int main() { QLibrary lib("CoolPlugIn"); if (lib.load()) { QFunctionPointer fptr = lib.resolve("foo"); if (fptr) { qDebug() << "foo =" << ((int (*)(void))fptr)(); } } return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/mixed-build-variants/000077500000000000000000000000001266132464200246415ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/mixed-build-variants/main.cpp000066400000000000000000000000701266132464200262660ustar00rootroot00000000000000#include int main() { qDebug("Tach."); } qbs-src-1.4.5/tests/auto/blackbox/testdata/mixed-build-variants/mixed-build-variants.qbs000066400000000000000000000001341266132464200313760ustar00rootroot00000000000000import qbs QtApplication { Qt.core.qtBuildVariant: "release" files: ["main.cpp"] } qbs-src-1.4.5/tests/auto/blackbox/testdata/multiple-changes/000077500000000000000000000000001266132464200240525ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/multiple-changes/dummy.txt000066400000000000000000000000001266132464200257340ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/multiple-changes/project.qbs000066400000000000000000000014061266132464200262300ustar00rootroot00000000000000import qbs Project { property bool prop: false Product { name: "test" type: ["out-type"] Group { name: "Rule input" files: ["dummy.txt"] fileTags: ["in-type"] } Group { name: "irrelevant" files: ["*.blubb"] } Rule { inputs: ["in-type"] Artifact { filePath: "dummy.out" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { print("prop: " + project.prop); } return [cmd]; } } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/nested-properties/000077500000000000000000000000001266132464200242655ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/nested-properties/dummy.txt000066400000000000000000000000001266132464200261470ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/nested-properties/modules/000077500000000000000000000000001266132464200257355ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/nested-properties/modules/higherlevel/000077500000000000000000000000001266132464200302335ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/nested-properties/modules/higherlevel/higher-level.qbs000066400000000000000000000001601266132464200333120ustar00rootroot00000000000000import qbs Module { Depends { name: "lowerlevel" } lowerlevel.propDependency: "value in higherlevel" } qbs-src-1.4.5/tests/auto/blackbox/testdata/nested-properties/modules/lowerlevel/000077500000000000000000000000001266132464200301155ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/nested-properties/modules/lowerlevel/lower-level.qbs000066400000000000000000000011171266132464200330610ustar00rootroot00000000000000import qbs Module { property string propDependency: "value in lowerlevel module" property string prop: propDependency property string someOtherProp Rule { inputs: ["dummy-input"] Artifact { filePath: "dummy.out" fileTags: "mytype" } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = function() { }; var prop = product.moduleProperty("lowerlevel", "prop"); cmd.description = "lowerlevel.prop is '" + prop + "'."; return [cmd]; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/nested-properties/product.qbs000066400000000000000000000007101266132464200264520ustar00rootroot00000000000000import qbs Project { Product { name: "dep" Export { Depends { name: "lowerlevel" } lowerlevel.someOtherProp: "blubb" } } Product { type: "mytype" name: "toplevel" Depends { name: "higherlevel" } Depends { name: "lowerlevel" } Depends { name: "dep" } Group { files: ["dummy.txt"] fileTags: ["dummy-input"] } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/nodejs/000077500000000000000000000000001266132464200220735ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/nodejs/hello.js000066400000000000000000000000611266132464200235310ustar00rootroot00000000000000if (console) { console.log("hello world"); } qbs-src-1.4.5/tests/auto/blackbox/testdata/nodejs/hello.qbs000066400000000000000000000001611266132464200237030ustar00rootroot00000000000000import qbs NodeJSApplication { nodejs.applicationFile: "hello.js" name: "hello" files: "hello.js" } qbs-src-1.4.5/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/000077500000000000000000000000001266132464200273215ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/broken.cpp000066400000000000000000000000071266132464200313020ustar00rootroot00000000000000broken qbs-src-1.4.5/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/fine.cpp000066400000000000000000000000161266132464200307430ustar00rootroot00000000000000int main() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/project.qbs000066400000000000000000000001421266132464200314730ustar00rootroot00000000000000import qbs CppApplication { consoleApplication: true files: ["fine.cpp", "broken.cpp"] } qbs-src-1.4.5/tests/auto/blackbox/testdata/non-default-product/000077500000000000000000000000001266132464200245035ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/non-default-product/main.cpp000066400000000000000000000000161266132464200261300ustar00rootroot00000000000000int main() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/non-default-product/project.qbs000066400000000000000000000005071266132464200266620ustar00rootroot00000000000000import qbs Project { CppApplication { name: "default app" consoleApplication: true files: "main.cpp" } CppApplication { name: "non-default app" Depends { name: "default app" } consoleApplication: true builtByDefault: false files: "main.cpp" } } qbs-src-1.4.5/tests/auto/blackbox/testdata/nsis/000077500000000000000000000000001266132464200215655ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/nsis/hello.bat000066400000000000000000000000221266132464200233520ustar00rootroot00000000000000echo Hello world! qbs-src-1.4.5/tests/auto/blackbox/testdata/nsis/hello.nsi000066400000000000000000000005611266132464200234050ustar00rootroot00000000000000SetCompressor zlib !ifdef Win64 Name "Qbs Hello - ${qbs.architecture} (64-bit)" !else Name "Qbs Hello - ${qbs.architecture} (32-bit)" !endif OutFile "you-should-not-see-a-file-with-this-name.exe" InstallDir "$DESKTOP\Qbs Hello" RequestExecutionLevel user Page directory Page instfiles Section "" SetOutPath "$INSTDIR" File "${batchFile}" SectionEnd qbs-src-1.4.5/tests/auto/blackbox/testdata/nsis/hello.qbs000066400000000000000000000004021266132464200233730ustar00rootroot00000000000000import qbs NSISSetup { condition: qbs.targetOS.contains("windows") name: "Qbs Hello" targetName: "qbs-hello-" + qbs.architecture files: ["hello.nsi", "hello.bat"] nsis.defines: ["batchFile=hello.bat"] nsis.compressor: "lzma-solid" } qbs-src-1.4.5/tests/auto/blackbox/testdata/objc-arc/000077500000000000000000000000001266132464200222715ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/objc-arc/arc.m000066400000000000000000000001071266132464200232120ustar00rootroot00000000000000#if !__has_feature(objc_arc) #error Not using ARC but should be #endif qbs-src-1.4.5/tests/auto/blackbox/testdata/objc-arc/arc.mm000066400000000000000000000001071266132464200233670ustar00rootroot00000000000000#if !__has_feature(objc_arc) #error Not using ARC but should be #endif qbs-src-1.4.5/tests/auto/blackbox/testdata/objc-arc/main.m000066400000000000000000000001361266132464200233730ustar00rootroot00000000000000#if __has_feature(objc_arc) #error Using ARC but shouldn't be #endif int main() { return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/objc-arc/mrc.m000066400000000000000000000001051266132464200232240ustar00rootroot00000000000000#if __has_feature(objc_arc) #error Using ARC but shouldn't be #endif qbs-src-1.4.5/tests/auto/blackbox/testdata/objc-arc/mrc.mm000066400000000000000000000001051266132464200234010ustar00rootroot00000000000000#if __has_feature(objc_arc) #error Using ARC but shouldn't be #endif qbs-src-1.4.5/tests/auto/blackbox/testdata/objc-arc/objc-arc.qbs000066400000000000000000000006301266132464200244570ustar00rootroot00000000000000import qbs Product { Depends { name: "cpp" } consoleApplication: true type: ["application"] condition: qbs.targetOS.contains("darwin") Group { cpp.automaticReferenceCounting: true files: ["arc.m", "arc.mm"] } Group { cpp.automaticReferenceCounting: false files: ["mrc.m", "mrc.mm"] } files: "main.m" cpp.minimumOsxVersion: "10.6" } qbs-src-1.4.5/tests/auto/blackbox/testdata/overrideProjectProperties/000077500000000000000000000000001266132464200260345ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/overrideProjectProperties/helper_lib.qbs000066400000000000000000000002071266132464200306470ustar00rootroot00000000000000import qbs DynamicLibrary { name: "helperLib" files: "helperlib.cpp" Depends { name: "cpp" } bundle.isBundle: false } qbs-src-1.4.5/tests/auto/blackbox/testdata/overrideProjectProperties/helperlib.cpp000066400000000000000000000001711266132464200305050ustar00rootroot00000000000000#if defined(_WIN32) # define EXPORT __declspec(dllexport) #else # define EXPORT #endif void EXPORT helperFunc() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/overrideProjectProperties/main.cpp000066400000000000000000000000351266132464200274620ustar00rootroot00000000000000int main() { return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/overrideProjectProperties/main2.cpp000066400000000000000000000002471266132464200275510ustar00rootroot00000000000000#if defined(_WIN32) # define IMPORT __declspec(dllimport) #else # define IMPORT #endif void IMPORT helperFunc(); int main() { helperFunc(); return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/overrideProjectProperties/project.qbs000066400000000000000000000023151266132464200302120ustar00rootroot00000000000000import qbs 1.0 Project { property string nameSuffix: "" property bool someBool property int someInt property stringList someStringList Product { consoleApplication: true type: "application" property string mainFile: "" name: "MyApp" + nameSuffix Depends { name: "cpp" } files: { // Check types of the project's custom properties here. // Provoke a build error if the expected types do not match. var wrongFile = "doesnotexist.cpp"; if (typeof project.someBool != "boolean") { print("someBool has a wrong type: " + typeof project.someBool); return wrongFile; } if (typeof project.someInt != "number") { print("someInt has a wrong type: " + typeof project.someInt); return wrongFile; } if (typeof project.someStringList != "object") { print("someStringList has a wrong type: " + typeof project.someStringList); return wrongFile; } // Return the mainFile property that is set on the command line. return [mainFile]; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/overrideProjectProperties/project_using_helper_lib.qbs000066400000000000000000000005021266132464200336000ustar00rootroot00000000000000import qbs 1.0 Project { property bool linkSuccessfully: false references: linkSuccessfully ? ["helper_lib.qbs"] : [] CppApplication { consoleApplication: true Depends { condition: project.linkSuccessfully name: "helperLib" } files: "main2.cpp" } } qbs-src-1.4.5/tests/auto/blackbox/testdata/probes-in-nested-modules/000077500000000000000000000000001266132464200254355ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/probes-in-nested-modules/modules/000077500000000000000000000000001266132464200271055ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/probes-in-nested-modules/modules/inner/000077500000000000000000000000001266132464200302205ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/probes-in-nested-modules/modules/inner/inner.qbs000066400000000000000000000006201266132464200320400ustar00rootroot00000000000000import qbs import qbs.Probes Module { property bool alt: false Probe { id: foo property string baz property bool useAlt: alt property string named: product.name configure: { print("running probe " + named); baz = useAlt ? "hahaha" : "hello"; found = true; } } property string something: foo.baz } qbs-src-1.4.5/tests/auto/blackbox/testdata/probes-in-nested-modules/modules/outer/000077500000000000000000000000001266132464200302435ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/probes-in-nested-modules/modules/outer/outer.qbs000066400000000000000000000006121266132464200321070ustar00rootroot00000000000000import qbs Module { Depends { name: "inner" } Probe { id: foo2 property string barz property string named: product.name configure: { print("running second probe " + named); barz = "goodbye"; found = true; } } property string something: inner.something property string somethingElse: foo2.barz } qbs-src-1.4.5/tests/auto/blackbox/testdata/probes-in-nested-modules/probes-in-nested-modules.qbs000066400000000000000000000015721266132464200327750ustar00rootroot00000000000000import qbs Project { Product { name: "a" Depends { name: "outer" } inner.alt: true type: { print("product " + name + ", inner.something = " + inner.something); print("product " + name + ", outer.something = " + outer.something); print("product " + name + ", outer.somethingElse = " + outer.somethingElse); return ["foo"]; } } Product { name: "b" Depends { name: "inner" } inner.alt: true type: { print("product " + name + ", inner.something = " + inner.something); return ["foo"]; } } Product { name: "c" Depends { name: "inner" } inner.alt: false type: { print("product " + name + ", inner.something = " + inner.something); return ["foo"]; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/product-dependencies-by-type/000077500000000000000000000000001266132464200263045ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/product-dependencies-by-type/main.cpp000066400000000000000000000000161266132464200277310ustar00rootroot00000000000000int main() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/product-dependencies-by-type/project.qbs000066400000000000000000000034351266132464200304660ustar00rootroot00000000000000import qbs import qbs.TextFile Project { CppApplication { consoleApplication: true name: "no-match" files: "main.cpp" } Project { CppApplication { consoleApplication: true name: "app1" files: "main.cpp" } CppApplication { consoleApplication: true name: "app2" files: "main.cpp" } CppApplication { consoleApplication: true name: "app3" files: "main.cpp" } DynamicLibrary { Depends { name: "cpp" } name: "lib-product" files: "main.cpp" bundle.isBundle: false } CppApplication { type: base.concat(["app-list"]) consoleApplication: true name: "app list" Depends { productTypes: ["application"] limitToSubProject: true } files: ["main.cpp"] Rule { multiplex: true inputsFromDependencies: "application" Artifact { filePath: "app-list.txt" fileTags: "app-list" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Collecting apps"; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.WriteOnly); for (var i = 0; i < inputs["application"].length; ++i) file.writeLine(inputs["application"][i].filePath); file.close(); }; return cmd; } } } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/productproperties/000077500000000000000000000000001266132464200244065ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/productproperties/app.qbs000066400000000000000000000003011266132464200256670ustar00rootroot00000000000000import qbs 1.0 Product { consoleApplication: true type: "application" name: "blubb_user" files: "main.cpp" Depends { name: "blubb_header" } Depends { name: "cpp" } } qbs-src-1.4.5/tests/auto/blackbox/testdata/productproperties/blubb_header.h.in000066400000000000000000000000001266132464200275500ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/productproperties/header.qbs000066400000000000000000000015741266132464200263540ustar00rootroot00000000000000import qbs 1.0 import qbs.TextFile Product { name: "blubb_header" type: "hpp" files: "blubb_header.h.in" property string blubbProp: project.blubbProp Transformer { Artifact { filePath: "blubb_header.h" fileTags: "hpp" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating blubb_header.h"; cmd.highlight = "codegen"; cmd.blubbProp = product.blubbProp; cmd.sourceCode = function() { file = new TextFile(output.filePath, TextFile.WriteOnly); file.truncate(); file.write("#define BLUBB_PROP " + blubbProp); file.close(); } return cmd; } } Export { Depends { name: "cpp" } cpp.includePaths: product.buildDirectory } } qbs-src-1.4.5/tests/auto/blackbox/testdata/productproperties/main.cpp000066400000000000000000000001221266132464200260310ustar00rootroot00000000000000#include "blubb_header.h" int main() { #if BLUBB_PROP != 5 blubb(); #endif } qbs-src-1.4.5/tests/auto/blackbox/testdata/productproperties/project.qbs000066400000000000000000000001471266132464200265650ustar00rootroot00000000000000import qbs 1.0 Project { property string blubbProp: 5 references: ["header.qbs", "app.qbs"] } qbs-src-1.4.5/tests/auto/blackbox/testdata/project_filepath_check/000077500000000000000000000000001266132464200252705ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/project_filepath_check/main.cpp000066400000000000000000000000161266132464200267150ustar00rootroot00000000000000int main() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/project_filepath_check/project1.qbs000066400000000000000000000000711266132464200275240ustar00rootroot00000000000000import qbs 1.0 CppApplication { files: "main.cpp" } qbs-src-1.4.5/tests/auto/blackbox/testdata/project_filepath_check/project2.qbs000066400000000000000000000000711266132464200275250ustar00rootroot00000000000000import qbs 1.0 CppApplication { files: "main.cpp" } qbs-src-1.4.5/tests/auto/blackbox/testdata/proper quoting/000077500000000000000000000000001266132464200235675ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/proper quoting/main.cpp000066400000000000000000000032671266132464200252270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include int bla(); int main() { printf(DEFINE"\n"); printf(DEFINEWITHSPACE"\n"); printf(DEFINEWITHTAB"\n"); printf(DEFINEWITHBACKSLASH"\n"); return bla(); } qbs-src-1.4.5/tests/auto/blackbox/testdata/proper quoting/my static lib helper.cpp000066400000000000000000000000531266132464200301550ustar00rootroot00000000000000int helper_function() { return 156; } qbs-src-1.4.5/tests/auto/blackbox/testdata/proper quoting/my static lib.cpp000066400000000000000000000032251266132464200267210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #include int bla() { int n = getSomeNumber(); printf("Hello World! The magic number is %d.", n); return n; } qbs-src-1.4.5/tests/auto/blackbox/testdata/proper quoting/proper quoting.qbs000066400000000000000000000017611266132464200272610ustar00rootroot00000000000000import qbs 1.0 Project { Product { type: "application" consoleApplication: true name: "Hello World" files : [ "main.cpp" ] Depends { name: "cpp" } Depends { name: "my static lib" } cpp.defines: [ 'DEFINE="whitespaceless"', 'DEFINEWITHSPACE="contains space"', 'DEFINEWITHTAB="contains\ttab"', 'DEFINEWITHBACKSLASH="backslash\\\\"', ] } Product { type: "staticlibrary" name : "my static lib" files : [ "my static lib.cpp" ] Depends { name: "cpp" } Depends { name: "helper lib" } } Product { type: "staticlibrary" name : "helper lib" files : [ "some helper/some helper.h", "some helper/some helper.cpp" ] Depends { name: "cpp" } Export { Depends { name: "cpp" } cpp.includePaths: [product.sourceDirectory + '/some helper'] } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/proper quoting/some helper/000077500000000000000000000000001266132464200257725ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/proper quoting/some helper/some helper.cpp000066400000000000000000000030731266132464200307040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "some helper.h" int getSomeNumber() { return 156; } qbs-src-1.4.5/tests/auto/blackbox/testdata/proper quoting/some helper/some helper.h000066400000000000000000000031001266132464200303400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef HELPER_H #define HELPER_H extern int getSomeNumber(); #endif qbs-src-1.4.5/tests/auto/blackbox/testdata/property-precedence/000077500000000000000000000000001266132464200245705ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/property-precedence/dep.qbs000066400000000000000000000003121266132464200260430ustar00rootroot00000000000000import qbs Product { name: "dep" Export { Depends { name: "leaf" } Depends { name: "nonleaf" } // leaf.scalarProp: "export" // leaf.listProp: ["export"] } } qbs-src-1.4.5/tests/auto/blackbox/testdata/property-precedence/dummy.txt000066400000000000000000000000001266132464200264520ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/property-precedence/modules/000077500000000000000000000000001266132464200262405ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/property-precedence/modules/leaf/000077500000000000000000000000001266132464200271475ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/property-precedence/modules/leaf/leaf.qbs000066400000000000000000000012251266132464200305650ustar00rootroot00000000000000import qbs Module { property string scalarProp: "leaf" property stringList listProp: ["leaf"] Rule { inputs: ["rule-input"] Artifact { filePath: "dummy" fileTags: ["rule-output"] alwaysUpdated: false } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { print("scalar prop: " + product.moduleProperty("leaf", "scalarProp")); print("list prop: " + JSON.stringify(product.moduleProperties("leaf", "listProp"))); } return [cmd]; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/property-precedence/modules/nonleaf/000077500000000000000000000000001266132464200276625ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/property-precedence/modules/nonleaf/nonleaf.qbs000066400000000000000000000001711266132464200320120ustar00rootroot00000000000000import qbs Module { Depends { name: "leaf" } // leaf.scalarProp: "nonleaf" // leaf.listProp: ["nonleaf"] } qbs-src-1.4.5/tests/auto/blackbox/testdata/property-precedence/project.qbs000066400000000000000000000006201266132464200267430ustar00rootroot00000000000000import qbs Project { references: ["dep.qbs"] Product { name: "toplevel" type: ["rule-output"] Depends { name: "leaf" } Depends { name: "nonleaf" } Depends { name: "dep" } Group { files: ["dummy.txt"] fileTags: ["rule-input"] } // leaf.scalarProp: "product" // leaf.listProp: ["product"] } } qbs-src-1.4.5/tests/auto/blackbox/testdata/propertyChanges/000077500000000000000000000000001266132464200237665ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/propertyChanges/lib.cpp000066400000000000000000000000571266132464200252420ustar00rootroot00000000000000#include Q_DECL_EXPORT void f() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/propertyChanges/modules/000077500000000000000000000000001266132464200254365ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/propertyChanges/modules/TestModule/000077500000000000000000000000001266132464200275235ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/propertyChanges/modules/TestModule/module.qbs000066400000000000000000000011751266132464200315230ustar00rootroot00000000000000import qbs import qbs.File Module { FileTagger { patterns: ["*.in"] fileTags: "test-input" } Rule { inputs: ['test-input'] Artifact { fileTags: "test-output" filePath: input.fileName + ".out" } prepare: { var cmd = new JavaScriptCommand(); cmd.highlight = "codegen"; cmd.description = "Making output from input"; cmd.sourceCode = function() { // print('Change in source code'); File.copy(input.filePath, output.filePath); } return cmd; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/propertyChanges/project.qbs000066400000000000000000000047231266132464200261510ustar00rootroot00000000000000import qbs 1.0 import qbs.File import qbs.TextFile Project { property var projectDefines: ["blubb2"] property string fileContentSuffix: "suffix 1" CppApplication { name: qbs.enableDebugCode ? "product 1.debug" : "product 1.release" cpp.defines: ["blubb1"] files: "source1.cpp" } CppApplication { Depends { name: 'library' } name: "product 2" cpp.defines: project.projectDefines files: "source2.cpp" } CppApplication { name: "product 3" cpp.defines: qbs.getEnv("QBS_BLACKBOX_DEFINE") files: "source3.cpp" } DynamicLibrary { name: "library" Depends { name: "Qt.core" } files: "lib.cpp" bundle.isBundle: false } Product { name: "generated text file" property string fileContentPrefix: "prefix 1" Transformer { Artifact { filePath: "nothing" } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { print(product.fileContentPrefix); } return cmd; } } Transformer { Artifact { filePath: "generated.txt" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.filePath; cmd.highlight = "codegen"; cmd.sourceCode = function() { file = new TextFile(output.filePath, TextFile.WriteOnly); file.truncate(); file.write(product.fileContentPrefix + "contents 1" + project.fileContentSuffix); file.close(); } return cmd; } } } Product { Depends { name: "ruletest" } type: ["test-output2"] Rule { inputsFromDependencies: ['test-output'] Artifact { fileTags: "test-output2" filePath: input.fileName + ".out2" } prepare: { var cmd = new JavaScriptCommand(); cmd.highlight = "codegen"; cmd.description = "Making output from other output"; cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); } return cmd; } } } references: "ruletest.qbs" qbsSearchPaths: "." } qbs-src-1.4.5/tests/auto/blackbox/testdata/propertyChanges/ruletest.qbs000066400000000000000000000001751266132464200263470ustar00rootroot00000000000000import qbs Product { name: "ruletest" type: "test-output" Depends { name: "TestModule" } files: "test.in" } qbs-src-1.4.5/tests/auto/blackbox/testdata/propertyChanges/source1.cpp000066400000000000000000000000161266132464200260500ustar00rootroot00000000000000int main() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/propertyChanges/source2.cpp000066400000000000000000000000171266132464200260520ustar00rootroot00000000000000int main() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/propertyChanges/source3.cpp000066400000000000000000000000171266132464200260530ustar00rootroot00000000000000int main() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/propertyChanges/test.in000066400000000000000000000000061266132464200252710ustar00rootroot00000000000000blubb qbs-src-1.4.5/tests/auto/blackbox/testdata/qbsVersion/000077500000000000000000000000001266132464200227445ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/qbsVersion/qbs-version.qbs000066400000000000000000000013001266132464200257150ustar00rootroot00000000000000import qbs Project { property string qbsVersion property int qbsVersionMajor property int qbsVersionMinor property int qbsVersionPatch Product { name: { if (qbsVersion !== qbs.version || qbsVersionMajor !== qbs.versionMajor || qbsVersionMinor !== qbs.versionMinor || qbsVersionPatch !== qbs.versionPatch) throw("expected " + [qbsVersion, qbsVersionMajor, qbsVersionMinor, qbsVersionPatch].join(", ") + ", got " + [qbs.version, qbs.versionMajor, qbs.versionMinor, qbs.versionPatch].join(", ")); return "foo"; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/qml-debugging/000077500000000000000000000000001266132464200233335ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/qml-debugging/main.cpp000066400000000000000000000011231266132464200247600ustar00rootroot00000000000000#include #include #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) #include #include typedef QGuiApplication Application; #define AH_SO_THIS_IS_QT5 #else #include #include #define AH_SO_THIS_IS_QT4 typedef QApplication Application; #endif int main(int argc, char *argv[]) { Application app(argc, argv); #ifdef AH_SO_THIS_IS_QT5 QQmlApplicationEngine engine; engine.load(QUrl("blubb")); #else QDeclarativeView view; view.setSource(QUrl("blubb")); #endif return app.exec(); } qbs-src-1.4.5/tests/auto/blackbox/testdata/qml-debugging/project.qbs000066400000000000000000000002551266132464200255120ustar00rootroot00000000000000import qbs QtApplication { name: "debuggable-app" consoleApplication: true Depends { name: "Qt.quick" } Qt.quick.qmlDebugging: true files: "main.cpp" } qbs-src-1.4.5/tests/auto/blackbox/testdata/qobject-in-mm/000077500000000000000000000000001266132464200232535ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/qobject-in-mm/main.mm000066400000000000000000000001741266132464200245340ustar00rootroot00000000000000#include class Foo : public QObject { Q_OBJECT }; int main() { Foo foo; return 0; } #include "main.moc" qbs-src-1.4.5/tests/auto/blackbox/testdata/qobject-in-mm/project.qbs000066400000000000000000000001261266132464200254270ustar00rootroot00000000000000import qbs CppApplication { Depends { name: "Qt.core" } files: ["main.mm"] } qbs-src-1.4.5/tests/auto/blackbox/testdata/qrc/000077500000000000000000000000001266132464200213765ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/qrc/bla.cpp000066400000000000000000000030261266132464200226410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ int main() { return 3; } qbs-src-1.4.5/tests/auto/blackbox/testdata/qrc/bla.qrc000066400000000000000000000001301266132464200226350ustar00rootroot00000000000000 stuff.txt qbs-src-1.4.5/tests/auto/blackbox/testdata/qrc/i.qbs000066400000000000000000000004331266132464200223350ustar00rootroot00000000000000import qbs 1.0 Project { Product { consoleApplication: true type: "application" name: "i" Depends { name: "Qt.core" } files: [ "bla.cpp", "bla.qrc", "stuff.txt" ] } } qbs-src-1.4.5/tests/auto/blackbox/testdata/qrc/stuff.txt000066400000000000000000000000201266132464200232560ustar00rootroot00000000000000a resource file qbs-src-1.4.5/tests/auto/blackbox/testdata/rad-after-incomplete-build/000077500000000000000000000000001266132464200257105ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/rad-after-incomplete-build/dummy.txt000066400000000000000000000000001266132464200275720ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/rad-after-incomplete-build/project_with_rule.qbs000066400000000000000000000010741266132464200321510ustar00rootroot00000000000000import qbs import qbs.TextFile Product { type: "custom" Group { files: "dummy.txt" fileTags: "input" } Rule { inputs: "input" Artifact { fileTags: "custom" filePath: "oldfile" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating file"; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); } return cmd; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/rad-after-incomplete-build/project_with_transformer.qbs000066400000000000000000000007441266132464200335470ustar00rootroot00000000000000import qbs import qbs.TextFile Product { type: "custom" Transformer { Artifact { fileTags: "custom" filePath: "oldfile" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "creating file"; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); } return cmd; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/recursive_renaming/000077500000000000000000000000001266132464200245005ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/recursive_renaming/dir/000077500000000000000000000000001266132464200252565ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/recursive_renaming/dir/subdir/000077500000000000000000000000001266132464200265465ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/recursive_renaming/dir/subdir/blubb.txt000066400000000000000000000000001266132464200303630ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/recursive_renaming/dir/wasser.txt000066400000000000000000000000001266132464200273110ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/recursive_renaming/recursive_renaming.qbs000066400000000000000000000001351266132464200310750ustar00rootroot00000000000000import qbs 1.0 Product { Group { qbs.install: true files: "dir" } } qbs-src-1.4.5/tests/auto/blackbox/testdata/recursive_wildcards/000077500000000000000000000000001266132464200246545ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/recursive_wildcards/dir/000077500000000000000000000000001266132464200254325ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/recursive_wildcards/dir/file1.txt000066400000000000000000000000001266132464200271610ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/recursive_wildcards/dir/subdir/000077500000000000000000000000001266132464200267225ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/recursive_wildcards/dir/subdir/file2.txt000066400000000000000000000000001266132464200304520ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/recursive_wildcards/recursive_wildcards.qbs000066400000000000000000000001561266132464200314300ustar00rootroot00000000000000Product { Group { files: "dir/**" qbs.install: true qbs.installDir: "dir" } } qbs-src-1.4.5/tests/auto/blackbox/testdata/renameDependency/000077500000000000000000000000001266132464200240575ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/renameDependency/after/000077500000000000000000000000001266132464200251605ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/renameDependency/after/lib2.cpp000066400000000000000000000002361266132464200265150ustar00rootroot00000000000000#include "lib2.h" #include void print_two_numbers(int a, int b, int c) { std::cout << "a=" << a << ", b=" << b << ", c=" << c << std::endl; } qbs-src-1.4.5/tests/auto/blackbox/testdata/renameDependency/after/lib2.h000066400000000000000000000000551266132464200261610ustar00rootroot00000000000000void print_two_numbers(int a, int b, int c); qbs-src-1.4.5/tests/auto/blackbox/testdata/renameDependency/before/000077500000000000000000000000001266132464200253215ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/renameDependency/before/lib.cpp000066400000000000000000000002461266132464200265750ustar00rootroot00000000000000#include "lib.h" #include void print_two_numbers(int a, int b/*, int c*/) { std::cout << "a=" << a << ", b=" << b /*<< ", c=" << c */ << std::endl; } qbs-src-1.4.5/tests/auto/blackbox/testdata/renameDependency/before/lib.h000066400000000000000000000000611266132464200262350ustar00rootroot00000000000000void print_two_numbers(int a, int b/*, int c*/); qbs-src-1.4.5/tests/auto/blackbox/testdata/renameDependency/before/main.cpp000066400000000000000000000001401266132464200267440ustar00rootroot00000000000000#include #include "lib.h" int main() { print_two_numbers(2, 3); return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/renameDependency/before/renameDependency.qbs000066400000000000000000000000731266132464200312760ustar00rootroot00000000000000import qbs CppApplication { files: ["*.cpp", "*.h"] } qbs-src-1.4.5/tests/auto/blackbox/testdata/ruleConditions/000077500000000000000000000000001266132464200236125ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ruleConditions/foo.narf000066400000000000000000000000001266132464200252330ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ruleConditions/main.cpp000066400000000000000000000000311266132464200252340ustar00rootroot00000000000000int main() { return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/ruleConditions/modules/000077500000000000000000000000001266132464200252625ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ruleConditions/modules/narfzort/000077500000000000000000000000001266132464200271275ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ruleConditions/modules/narfzort/narfzort.qbs000066400000000000000000000015301266132464200315020ustar00rootroot00000000000000import qbs 1.0 import qbs.FileInfo import qbs.TextFile Module { property bool buildZort: true FileTagger { patterns: "*.narf" fileTags: ["narf"] } Rule { condition: product.moduleProperty("narfzort", "buildZort"); inputs: ["narf"] outputFileTags: ["zort"] outputArtifacts: [{ filePath: product.name + "." + input.fileName + ".zort", fileTags: ["zort"] }] prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + FileInfo.fileName(output.filePath); cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.write("NARF! ZORT!"); f.close(); } return cmd; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/ruleConditions/ruleConditions.qbs000066400000000000000000000003001266132464200273130ustar00rootroot00000000000000import qbs 1.0 import "templates/zorduct.qbs" as Zorduct Project { Zorduct { narfzort.buildZort: false name: "unzorted" } Zorduct { name: "zorted" } } qbs-src-1.4.5/tests/auto/blackbox/testdata/ruleConditions/templates/000077500000000000000000000000001266132464200256105ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ruleConditions/templates/zorduct.qbs000066400000000000000000000003221266132464200300060ustar00rootroot00000000000000import qbs 1.0 Product { type: ["application", "zort"] consoleApplication: true Depends { name: "cpp" } Depends { name: "narfzort" } files: [ "main.cpp", "foo.narf" ] } qbs-src-1.4.5/tests/auto/blackbox/testdata/ruleCycle/000077500000000000000000000000001266132464200225405ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/ruleCycle/happy.grass000066400000000000000000000000301266132464200247130ustar00rootroot00000000000000happy! happy! joy! joy! qbs-src-1.4.5/tests/auto/blackbox/testdata/ruleCycle/ruleCycle.qbs000066400000000000000000000024601266132464200252000ustar00rootroot00000000000000import qbs 1.0 Project { Product { name: "the cycle of life" type: "cow" Group { files: ["happy.grass"] fileTags: ["grass"] } Rule { inputs: ["grass"] outputFileTags: ["cow"] outputArtifacts: [{ filePath: input.completeBaseName + ".cow", fileTags: ["cow"] }] prepare: { print("The cow feeds on grass."); } } Rule { inputs: ["cow"] Artifact { filePath: input.completeBaseName + ".cow_pat" fileTags: ["cow_pat"] } prepare: { print("The cow pat falls out of the cow."); } } Rule { inputs: ["cow_pat"] Artifact { filePath: input.completeBaseName + ".fertilizer" fileTags: ["fertilizer"] } prepare: { print("The cow pat is used as fertilizer."); } } Rule { inputs: ["fertilizer"] outputFileTags: ["grass"] outputArtifacts: [{ filePath: input.completeBaseName + ".grass", fileTags: ["grass"] }] prepare: { print("The fertilizer lets the grass grow."); } } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/separate-debug-info/000077500000000000000000000000001266132464200244325ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/separate-debug-info/foo.cpp000066400000000000000000000002241266132464200257170ustar00rootroot00000000000000#if defined(_WIN32) || defined(WIN32) # define EXPORT __declspec(dllexport) #else # define EXPORT #endif EXPORT int getAnswer() { return 42; } qbs-src-1.4.5/tests/auto/blackbox/testdata/separate-debug-info/main.cpp000066400000000000000000000000311266132464200260540ustar00rootroot00000000000000int main() { return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/separate-debug-info/project.qbs000066400000000000000000000012621266132464200266100ustar00rootroot00000000000000import qbs Project { CppApplication { name: "app1" type: ["application"] files: ["main.cpp"] cpp.separateDebugInformation: true } DynamicLibrary { Depends { name: "cpp" } name: "foo1" type: ["dynamiclibrary"] files: ["foo.cpp"] cpp.separateDebugInformation: true } CppApplication { name: "app2" type: ["application"] files: ["main.cpp"] cpp.separateDebugInformation: false } DynamicLibrary { Depends { name: "cpp" } name: "foo2" type: ["dynamiclibrary"] files: ["foo.cpp"] cpp.separateDebugInformation: false } } qbs-src-1.4.5/tests/auto/blackbox/testdata/subprofile-change-tracking/000077500000000000000000000000001266132464200260065ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/subprofile-change-tracking/main1.cpp000066400000000000000000000000161266132464200275140ustar00rootroot00000000000000int main() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/subprofile-change-tracking/main2.cpp000066400000000000000000000000161266132464200275150ustar00rootroot00000000000000int main() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/subprofile-change-tracking/subprofile-change-tracking.qbs000066400000000000000000000002531266132464200337120ustar00rootroot00000000000000import qbs Project { CppApplication { files: ["main1.cpp"] } CppApplication { profiles: ["qbs-autotests-subprofile"] files: ["main2.cpp"] } } qbs-src-1.4.5/tests/auto/blackbox/testdata/symlink-removal/000077500000000000000000000000001266132464200237425ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/symlink-removal/symlink-removal.qbs000066400000000000000000000006601266132464200276040ustar00rootroot00000000000000import qbs import qbs.File Product { type: "removal" Transformer { Artifact { filePath: "dummy" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { File.remove(product.sourceDirectory + "/dir1"); }; return [cmd]; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackAddFile/000077500000000000000000000000001266132464200231265ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/trackAddFile/after/000077500000000000000000000000001266132464200242275ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/trackAddFile/after/main.cpp000066400000000000000000000033011266132464200256540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "narf.h" #include "zort.h" #include int main(int argc, char **argv) { printf("Hello World!\n"); Narf narf; narf.shout(); Zort zort; zort.shout(); return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackAddFile/after/project.qbs000066400000000000000000000004341266132464200264050ustar00rootroot00000000000000import qbs 1.0 Project { Product { name: 'someapp' type: 'application' consoleApplication: true Depends { name: 'cpp' } files: [ "main.cpp", "narf.h", "narf.cpp", "zort.h", "zort.cpp" ] } } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackAddFile/after/zort.cpp000066400000000000000000000031131266132464200257270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "zort.h" #include void Zort::shout() { printf("ZORT!\n"); } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackAddFile/after/zort.h000066400000000000000000000031111266132464200253720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef ZORT_H #define ZORT_H class Zort { public: void shout(); }; #endif qbs-src-1.4.5/tests/auto/blackbox/testdata/trackAddFile/before/000077500000000000000000000000001266132464200243705ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/trackAddFile/before/main.cpp000066400000000000000000000032161266132464200260220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "narf.h" #include int main(int argc, char **argv) { printf("Hello World!\n"); Narf narf; narf.shout(); return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackAddFile/before/narf.cpp000066400000000000000000000031131266132464200260200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "narf.h" #include void Narf::shout() { printf("NARF!\n"); } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackAddFile/before/narf.h000066400000000000000000000031111266132464200254630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef NARF_H #define NARF_H class Narf { public: void shout(); }; #endif qbs-src-1.4.5/tests/auto/blackbox/testdata/trackAddFile/before/project.qbs000066400000000000000000000003321266132464200265430ustar00rootroot00000000000000import qbs 1.0 Project { Product { name: 'someapp' type: 'application' consoleApplication: true Depends { name: 'cpp' } files: [ "main.cpp", "narf.h", "narf.cpp" ] } } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackAddMocInclude/000077500000000000000000000000001266132464200242715ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/trackAddMocInclude/after/000077500000000000000000000000001266132464200253725ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/trackAddMocInclude/after/main.cpp000066400000000000000000000004771266132464200270320ustar00rootroot00000000000000#include class MyObject : public QObject { Q_OBJECT public: MyObject(QObject *parent = 0) : QObject(parent) { } }; int main(int argc, char **argv) { QCoreApplication app(argc, argv); MyObject *obj = new MyObject(&app); return app.exec(); } #include qbs-src-1.4.5/tests/auto/blackbox/testdata/trackAddMocInclude/before/000077500000000000000000000000001266132464200255335ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/trackAddMocInclude/before/main.cpp000066400000000000000000000004521266132464200271640ustar00rootroot00000000000000#include class MyObject : public QObject { Q_OBJECT public: MyObject(QObject *parent = 0) : QObject(parent) { } }; int main(int argc, char **argv) { QCoreApplication app(argc, argv); MyObject *obj = new MyObject(&app); return app.exec(); } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackAddMocInclude/before/test.qbs000066400000000000000000000001311266132464200272140ustar00rootroot00000000000000import qbs 1.0 Application { Depends { name: "Qt.core" } files: ["main.cpp"] } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackExternalProductChanges/000077500000000000000000000000001266132464200262525ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/trackExternalProductChanges/environmentChange.cpp000066400000000000000000000000351266132464200324260ustar00rootroot00000000000000void environmentChange() { } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackExternalProductChanges/fileList.js000066400000000000000000000002131266132464200303570ustar00rootroot00000000000000function fileList() { return []; } function filesFromFs(qbs) { return File.exists(path + "/fileExists.cpp") ? ["fileExists.cpp"] : []; } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackExternalProductChanges/hidden/000077500000000000000000000000001266132464200275055ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/trackExternalProductChanges/hidden/hiddenheaderqbs.h000066400000000000000000000000001266132464200327560ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/trackExternalProductChanges/including.cpp000066400000000000000000000000521266132464200307270ustar00rootroot00000000000000#include void f() {} qbs-src-1.4.5/tests/auto/blackbox/testdata/trackExternalProductChanges/jsFileChange.cpp000066400000000000000000000000301266132464200312710ustar00rootroot00000000000000void jsFileChange() { } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackExternalProductChanges/main.cpp000066400000000000000000000000171266132464200277000ustar00rootroot00000000000000int main() { } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackExternalProductChanges/project.qbs000066400000000000000000000010041266132464200304220ustar00rootroot00000000000000import qbs import qbs.File import "fileList.js" as FileList CppApplication { property stringList filesFromEnv: qbs.getEnv("QBS_TEST_PULL_IN_FILE_VIA_ENV") ? ["environmentChange.cpp"] : [] files: ["main.cpp"].concat(FileList.fileList()).concat(filesFromEnv).concat(FileList.filesFromFs(qbs)) Group { condition: qbs.getEnv("INCLUDE_PATH_TEST") name: "file that needs help from the environment to find a header" files: "including.cpp" } } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackFileTags/000077500000000000000000000000001266132464200233345ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/trackFileTags/after/000077500000000000000000000000001266132464200244355ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/trackFileTags/after/main.cpp000066400000000000000000000031651266132464200260720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include int foo(); int main(int argc, char **argv) { printf("there's %d foo here\n", foo()); return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackFileTags/after/project.qbs000066400000000000000000000027661266132464200266250ustar00rootroot00000000000000import qbs 1.0 import qbs.TextFile Project { Product { name: 'someapp' type: 'application' consoleApplication: true Depends { name: 'cpp' } Group { files: [ "main.cpp" ] fileTags: [ "foosource", "cpp" ] } } Rule { inputs: ["foosource"] Artifact { filePath: input.baseName + ".foo" fileTags: ["foo"] } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = "var file = new TextFile(output.filePath, TextFile.WriteOnly);"; cmd.sourceCode += "file.truncate();" cmd.sourceCode += "file.write(\"There's nothing to see here!\");" cmd.sourceCode += "file.close();" cmd.description = "generating something"; return cmd; } } Rule { inputs: ["foo"] Artifact { filePath: input.baseName + "_foo.cpp" fileTags: ["cpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = "var file = new TextFile(output.filePath, TextFile.WriteOnly);"; cmd.sourceCode += "file.truncate();"; cmd.sourceCode += "file.write(\"// There's nothing to see here!\\n\");"; cmd.sourceCode += "file.write(\"int foo() { return 15; }\\n\");"; cmd.sourceCode += "file.close();"; cmd.description = "generating something"; return cmd; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackFileTags/before/000077500000000000000000000000001266132464200245765ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/trackFileTags/before/main.cpp000066400000000000000000000031421266132464200262260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include int main(int argc, char **argv) { printf("there's no foo here\n"); return 0; } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackFileTags/before/project.qbs000066400000000000000000000027511266132464200267600ustar00rootroot00000000000000import qbs 1.0 import qbs.TextFile Project { Product { name: 'someapp' type: 'application' consoleApplication: true Depends { name: 'cpp' } Group { files: [ "main.cpp" ] fileTags: [ "cpp" ] } } Rule { inputs: ["foosource"] Artifact { filePath: input.baseName + ".foo" fileTags: ["foo"] } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = "var file = new TextFile(output.filePath, TextFile.WriteOnly);"; cmd.sourceCode += "file.truncate();" cmd.sourceCode += "file.write(\"There's nothing to see here!\");" cmd.sourceCode += "file.close();" cmd.description = "generating something"; return cmd; } } Rule { inputs: ["foo"] Artifact { filePath: input.baseName + "_foo.cpp" fileTags: ["cpp"] } prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = "var file = new TextFile(output.filePath, TextFile.WriteOnly);"; cmd.sourceCode += "file.truncate();"; cmd.sourceCode += "file.write(\"// There's nothing to see here!\\n\");"; cmd.sourceCode += "file.write(\"int foo() { return 15; }\\n\");"; cmd.sourceCode += "file.close();"; cmd.description = "generating something"; return cmd; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackProducts/000077500000000000000000000000001266132464200234415ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/trackProducts/after/000077500000000000000000000000001266132464200245425ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/trackProducts/after/product3.qbs000066400000000000000000000002041266132464200270100ustar00rootroot00000000000000import qbs 1.0 Product { Depends { name: "cpp" } type: "application" consoleApplication: true files: ["zoo.cpp"] } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackProducts/after/trackProducts.qbs000066400000000000000000000001671266132464200301050ustar00rootroot00000000000000import qbs 1.0 Project { name: "trackProducts" references: ["product1.qbs", "product2.qbs", "product3.qbs"] } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackProducts/after/zoo.cpp000066400000000000000000000000671266132464200260600ustar00rootroot00000000000000#include int main() { printf("zoo\n"); } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackProducts/before/000077500000000000000000000000001266132464200247035ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/trackProducts/before/bar.cpp000066400000000000000000000000671266132464200261560ustar00rootroot00000000000000#include int main() { printf("bar\n"); } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackProducts/before/foo.cpp000066400000000000000000000000671266132464200261750ustar00rootroot00000000000000#include int main() { printf("foo\n"); } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackProducts/before/product1.qbs000066400000000000000000000002041266132464200271470ustar00rootroot00000000000000import qbs 1.0 Product { Depends { name: "cpp" } type: "application" consoleApplication: true files: ["foo.cpp"] } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackProducts/before/product2.qbs000066400000000000000000000002041266132464200271500ustar00rootroot00000000000000import qbs 1.0 Product { Depends { name: "cpp" } type: "application" consoleApplication: true files: ["bar.cpp"] } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackProducts/before/trackProducts.qbs000066400000000000000000000001471266132464200302440ustar00rootroot00000000000000import qbs 1.0 Project { name: "trackProducts" references: ["product1.qbs", "product2.qbs"] } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackQObjChange/000077500000000000000000000000001266132464200235775ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/trackQObjChange/bla.cpp000066400000000000000000000031261266132464200250430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "bla.h" int main() { MyObject obj; obj.setObjectName("I am the object!"); } qbs-src-1.4.5/tests/auto/blackbox/testdata/trackQObjChange/bla_noqobject.h000066400000000000000000000030621266132464200265530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include class MyObject : public QObject { }; qbs-src-1.4.5/tests/auto/blackbox/testdata/trackQObjChange/bla_qobject.h000066400000000000000000000030771266132464200262240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include class MyObject : public QObject { Q_OBJECT }; qbs-src-1.4.5/tests/auto/blackbox/testdata/trackQObjChange/i.qbs000066400000000000000000000004001266132464200245300ustar00rootroot00000000000000import qbs 1.0 Project { Product { type: "application" consoleApplication: true name: "i" Depends { name: "Qt.core" } files: [ "bla.cpp", "bla.h" ] } } qbs-src-1.4.5/tests/auto/blackbox/testdata/transitive-optional-dependencies/000077500000000000000000000000001266132464200272505ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/transitive-optional-dependencies/modules/000077500000000000000000000000001266132464200307205ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/transitive-optional-dependencies/modules/a/000077500000000000000000000000001266132464200311405ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/transitive-optional-dependencies/modules/a/a.qbs000066400000000000000000000001021266132464200320600ustar00rootroot00000000000000import qbs Module { Depends { name: "b"; required: false } } qbs-src-1.4.5/tests/auto/blackbox/testdata/transitive-optional-dependencies/modules/b/000077500000000000000000000000001266132464200311415ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/transitive-optional-dependencies/modules/b/b.qbs000066400000000000000000000000541266132464200320700ustar00rootroot00000000000000import qbs Module { condition: false } transitive-optional-dependencies.qbs000066400000000000000000000000621266132464200363350ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/transitive-optional-dependenciesimport qbs Product { Depends { name: "a" } } qbs-src-1.4.5/tests/auto/blackbox/testdata/typescript/000077500000000000000000000000001266132464200230175ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/typescript/animals.ts000066400000000000000000000005501266132464200250130ustar00rootroot00000000000000export interface Mammal { speak(): string; } export class Cat implements Mammal { public speak() { return "Meow"; // a cat says meow } } export class Dog implements Mammal { public speak() { return "Woof"; // a dog says woof } } export class Human implements Mammal { public speak() { return "Hello"; } } qbs-src-1.4.5/tests/auto/blackbox/testdata/typescript/extra.js000066400000000000000000000001061266132464200244750ustar00rootroot00000000000000if (console) { console.log("This doesn't do anything useful!"); } qbs-src-1.4.5/tests/auto/blackbox/testdata/typescript/foo.ts000066400000000000000000000001371266132464200241530ustar00rootroot00000000000000export class Greeter { public getGreeting(): string { return "guten Tag!"; } } qbs-src-1.4.5/tests/auto/blackbox/testdata/typescript/foo2.ts000066400000000000000000000000011266132464200242230ustar00rootroot00000000000000 qbs-src-1.4.5/tests/auto/blackbox/testdata/typescript/hello.ts000066400000000000000000000000351266132464200244700ustar00rootroot00000000000000console.log("Hello world!"); qbs-src-1.4.5/tests/auto/blackbox/testdata/typescript/main.ts000066400000000000000000000010151266132464200243100ustar00rootroot00000000000000import Animals = require("animals"); import Foo = require("foo"); import Extra = require("woosh/extra"); function main() { var mammals: Animals.Mammal[] = []; mammals.push(new Animals.Human()); mammals.push(new Animals.Dog()); mammals.push(new Animals.Cat()); // Make everyone speak for (var i = 0; i < mammals.length; ++i) { console.log(mammals[i].speak()); } (new Extra.Boom()); var greeting: string = (new Foo.Greeter()).getGreeting(); console.log(greeting); } main(); qbs-src-1.4.5/tests/auto/blackbox/testdata/typescript/typescript.qbs000066400000000000000000000020521266132464200257330ustar00rootroot00000000000000import qbs Project { NodeJSApplication { Depends { name: "typescript" } Depends { name: "lib" } typescript.warningLevel: ["pedantic"] typescript.generateDeclarations: true typescript.moduleLoader: "commonjs" nodejs.applicationFile: "main.ts" name: "animals" files: [ "animals.ts", "extra.js", "woosh/extra.ts", "main.ts" ] } Product { Depends { name: "typescript" } typescript.generateDeclarations: true typescript.moduleLoader: "commonjs" name: "lib" files: [ "foo.ts" ] } Product { Depends { name: "typescript" } typescript.generateDeclarations: true name: "lib2" files: [ "foo2.ts" ] } NodeJSApplication { Depends { name: "typescript" } Depends { name: "lib2" } typescript.singleFile: true nodejs.applicationFile: "hello.ts" name: "single" } } qbs-src-1.4.5/tests/auto/blackbox/testdata/typescript/woosh/000077500000000000000000000000001266132464200241565ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/typescript/woosh/extra.ts000066400000000000000000000000261266132464200256470ustar00rootroot00000000000000export class Boom { } qbs-src-1.4.5/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/000077500000000000000000000000001266132464200301245ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/custom1.in000066400000000000000000000000001266132464200320350ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/custom2.in000066400000000000000000000000001266132464200320360ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/project.qbs000066400000000000000000000030341266132464200323010ustar00rootroot00000000000000import qbs import qbs.FileInfo import qbs.TextFile Project { Product { name: "p1" type: "custom" Group { files: "custom1.in" fileTags: "custom.in" } } Product { name: "p2" type: "custom" Group { files: "custom2.in" fileTags: "custom.in" } } Rule { inputs: "custom.in" Artifact { filePath: FileInfo.baseName(input.filePath) + ".out" fileTags: "custom" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); } return cmd; } } Product { name: "p3" type: "custom-plus" Depends { name: "p1" } Depends { name: "p2" } Rule { inputsFromDependencies: "custom" Artifact { filePath: FileInfo.fileName(input.filePath) + ".plus" fileTags: "custom-plus" } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "generating " + output.fileName; cmd.sourceCode = function() { var f = new TextFile(output.filePath, TextFile.WriteOnly); f.close(); } return cmd; } } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/wildcard_renaming/000077500000000000000000000000001266132464200242625ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/wildcard_renaming/pioniere.txt000066400000000000000000000000001266132464200266230ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/wildcard_renaming/wildcard_renaming.qbs000066400000000000000000000001331266132464200304370ustar00rootroot00000000000000import qbs 1.0 Product { Group { qbs.install: true files: "*" } } qbs-src-1.4.5/tests/auto/blackbox/testdata/wildcards-and-rules/000077500000000000000000000000001266132464200244555ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/wildcards-and-rules/input1.inp000066400000000000000000000000001266132464200263730ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/wildcards-and-rules/project.qbs000066400000000000000000000016761266132464200266440ustar00rootroot00000000000000import qbs import qbs.TextFile Product { name: "wildcards-and-rules" type: "mytype" files: ["*.inp", "*.dep"] FileTagger { patterns: "*.inp" fileTags: ["inp"] } FileTagger { patterns: "*.dep" fileTags: ["dep"] } Rule { multiplex: true inputs: ["inp"] explicitlyDependsOn: ["dep"] Artifact { filePath: "test.mytype" fileTags: product.type } prepare: { var cmd = new JavaScriptCommand(); cmd.description = "Creating output artifact"; cmd.highlight = "codegen"; cmd.sourceCode = function() { var file = new TextFile(output.filePath, TextFile.WriteOnly); for (var i = 0; i < inputs.inp.length; ++i) file.writeLine(inputs.inp[i].fileName); file.close(); } return cmd; } } } qbs-src-1.4.5/tests/auto/blackbox/testdata/wix/000077500000000000000000000000001266132464200214205ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/blackbox/testdata/wix/ExampleScript.bat000066400000000000000000000000221266132464200246620ustar00rootroot00000000000000echo Hello world! qbs-src-1.4.5/tests/auto/blackbox/testdata/wix/QbsBootstrapper.wxs000066400000000000000000000006511266132464200253170ustar00rootroot00000000000000 qbs-src-1.4.5/tests/auto/blackbox/testdata/wix/QbsSetup.wxs000066400000000000000000000025441266132464200237360ustar00rootroot00000000000000 qbs-src-1.4.5/tests/auto/blackbox/testdata/wix/Qt.wxs000066400000000000000000000002041266132464200225430ustar00rootroot00000000000000 qbs-src-1.4.5/tests/auto/blackbox/testdata/wix/WiXInstallers.qbs000066400000000000000000000020451266132464200247000ustar00rootroot00000000000000import qbs import qbs.FileInfo Project { WindowsInstallerPackage { name: "QbsSetup" targetName: "qbs-" + qbs.architecture files: ["QbsSetup.wxs", "ExampleScript.bat"] wix.defines: ["scriptName=ExampleScript.bat"] wix.extensions: ["WixBalExtension", "WixUIExtension"] Export { Depends { name: "wix" } wix.defines: base.concat(["msiName=" + FileInfo.joinPaths(product.buildDirectory, product.targetName + wix.windowsInstallerSuffix)]) } } WindowsSetupPackage { Depends { name: "QbsSetup" } condition: qbs.hostOS.contains("windows") // currently does not work in Wine with WiX 3.9 name: "QbsBootstrapper" targetName: "qbs-setup-" + qbs.architecture files: ["QbsBootstrapper.wxs"] } WindowsInstallerPackage { name: "RegressionBuster9000" files: ["QbsSetup.wxs", "Qt.wxs", "de.wxl"] wix.defines: ["scriptName=ExampleScript.bat"] wix.cultures: [] } } qbs-src-1.4.5/tests/auto/blackbox/testdata/wix/de.wxl000066400000000000000000000001161266132464200225420ustar00rootroot00000000000000 qbs-src-1.4.5/tests/auto/blackbox/tst_blackbox.cpp000066400000000000000000003532301266132464200221710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "tst_blackbox.h" #include "../shared.h" #include #include #include #include #include #include #include #include #include #include #include #define WAIT_FOR_NEW_TIMESTAMP() waitForNewTimestamp(testDataDir) using qbs::InstallOptions; using qbs::Internal::HostOsInfo; using qbs::Internal::removeDirectoryWithContents; using qbs::Profile; using qbs::Settings; class OsXTarHealer { public: OsXTarHealer() { if (HostOsInfo::hostOs() == HostOsInfo::HostOsOsx) { // work around absurd tar behavior on OS X qputenv("COPY_EXTENDED_ATTRIBUTES_DISABLE", "true"); qputenv("COPYFILE_DISABLE", "true"); } } ~OsXTarHealer() { if (HostOsInfo::hostOs() == HostOsInfo::HostOsOsx) { qunsetenv("COPY_EXTENDED_ATTRIBUTES_DISABLE"); qunsetenv("COPYFILE_DISABLE"); } } }; static QString initQbsExecutableFilePath() { QString filePath = QCoreApplication::applicationDirPath() + QLatin1String("/qbs"); filePath = HostOsInfo::appendExecutableSuffix(QDir::cleanPath(filePath)); return filePath; } static bool supportsBuildDirectoryOption(const QString &command) { return !(QStringList() << "help" << "config" << "config-ui" << "qmltypes" << "setup-android" << "setup-qt" << "setup-toolchains").contains(command); } TestBlackbox::TestBlackbox() : testDataDir(testWorkDir(QStringLiteral("blackbox"))), testSourceDir(QDir::cleanPath(SRCDIR "/testdata")), qbsExecutableFilePath(initQbsExecutableFilePath()), defaultInstallRoot(relativeBuildDir() + QLatin1Char('/') + InstallOptions::defaultInstallRoot()) { QLocale::setDefault(QLocale::c()); } int TestBlackbox::runQbs(const QbsRunParameters ¶ms) { QStringList args; if (!params.command.isEmpty()) args << params.command; if (supportsBuildDirectoryOption(params.command)) { args.append(QStringList(QLatin1String("-d")) << QLatin1String(".")); } args << params.arguments; if (params.useProfile) args.append(QLatin1String("profile:") + profileName()); QProcess process; process.setProcessEnvironment(params.environment); process.start(qbsExecutableFilePath, args); const int waitTime = 10 * 60000; if (!process.waitForStarted() || !process.waitForFinished(waitTime)) { m_qbsStderr = process.readAllStandardError(); if (!params.expectFailure) qDebug("%s", qPrintable(process.errorString())); return -1; } m_qbsStderr = process.readAllStandardError(); m_qbsStdout = process.readAllStandardOutput(); sanitizeOutput(&m_qbsStderr); sanitizeOutput(&m_qbsStdout); if ((process.exitStatus() != QProcess::NormalExit || process.exitCode() != 0) && !params.expectFailure) { if (!m_qbsStderr.isEmpty()) qDebug("%s", m_qbsStderr.constData()); if (!m_qbsStdout.isEmpty()) qDebug("%s", m_qbsStdout.constData()); } return process.exitStatus() == QProcess::NormalExit ? process.exitCode() : -1; } /*! Recursive copy from directory to another. Note that this updates the file stamps on Linux but not on Windows. */ static void ccp(const QString &sourceDirPath, const QString &targetDirPath) { QDir currentDir; QDirIterator dit(sourceDirPath, QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden); while (dit.hasNext()) { dit.next(); const QString targetPath = targetDirPath + QLatin1Char('/') + dit.fileName(); currentDir.mkpath(targetPath); ccp(dit.filePath(), targetPath); } QDirIterator fit(sourceDirPath, QDir::Files | QDir::Hidden); while (fit.hasNext()) { fit.next(); const QString targetPath = targetDirPath + QLatin1Char('/') + fit.fileName(); QFile::remove(targetPath); // allowed to fail QVERIFY(QFile::copy(fit.filePath(), targetPath)); } } void TestBlackbox::rmDirR(const QString &dir) { QString errorMessage; removeDirectoryWithContents(dir, &errorMessage); } QByteArray TestBlackbox::unifiedLineEndings(const QByteArray &ba) { if (HostOsInfo::isWindowsHost()) { QByteArray result; result.reserve(ba.size()); for (int i = 0; i < ba.size(); ++i) { char c = ba.at(i); if (c != '\r') result.append(c); } return result; } else { return ba; } } void TestBlackbox::sanitizeOutput(QByteArray *ba) { if (HostOsInfo::isWindowsHost()) ba->replace('\r', ""); } void TestBlackbox::initTestCase() { QVERIFY(regularFileExists(qbsExecutableFilePath)); Settings settings((QString())); if (!settings.profiles().contains(profileName())) QFAIL(QByteArray("The build profile '" + profileName().toLocal8Bit() + "' could not be found. Please set it up on your machine.")); Profile buildProfile(profileName(), &settings); QVariant qtBinPath = buildProfile.value(QLatin1String("Qt.core.binPath")); if (!qtBinPath.isValid()) QFAIL(QByteArray("The build profile '" + profileName().toLocal8Bit() + "' is not a valid Qt profile.")); if (!QFile::exists(qtBinPath.toString())) QFAIL(QByteArray("The build profile '" + profileName().toLocal8Bit() + "' points to an invalid Qt path.")); // Initialize the test data directory. QVERIFY(testDataDir != testSourceDir); rmDirR(testDataDir); QDir().mkpath(testDataDir); ccp(testSourceDir, testDataDir); } static QString findExecutable(const QStringList &fileNames) { const QStringList path = QString::fromLocal8Bit(qgetenv("PATH")) .split(HostOsInfo::pathListSeparator(), QString::SkipEmptyParts); foreach (const QString &fileName, fileNames) { QFileInfo fi(fileName); if (fi.isAbsolute()) return fi.exists() ? fileName : QString(); foreach (const QString &ppath, path) { const QString fullPath = HostOsInfo::appendExecutableSuffix(ppath + QLatin1Char('/') + fileName); if (QFileInfo(fullPath).exists()) return QDir::cleanPath(fullPath); } } return QString(); } QString TestBlackbox::findArchiver(const QString &fileName, int *status) { if (fileName == "jar") { QDir::setCurrent(testDataDir + "/find-java"); const int res = runQbs(QbsRunParameters(QStringList() << "-f" << "find-jar.qbs" << "--dry-run")); if (status) *status = res; return QString::fromUtf8(m_qbsStderr).trimmed(); } QString binary = findExecutable(QStringList(fileName)); if (binary.isEmpty()) { Settings s((QString())); Profile p(profileName(), &s); binary = findExecutable(p.value("archiver.command").toStringList()); } return binary; } void TestBlackbox::sevenZip() { QDir::setCurrent(testDataDir + "/archiver"); QString binary = findArchiver("7z"); if (binary.isEmpty()) QSKIP("7zip not found"); QCOMPARE(runQbs(QbsRunParameters(QStringList() << "archiver.type:7zip")), 0); const QString outputFile = relativeProductBuildDir("archivable") + "/archivable.7z"; QVERIFY2(regularFileExists(outputFile), qPrintable(outputFile)); QProcess listContents; listContents.start(binary, QStringList() << "t" << outputFile); QVERIFY2(listContents.waitForStarted(), qPrintable(listContents.errorString())); QVERIFY2(listContents.waitForFinished(), qPrintable(listContents.errorString())); QVERIFY2(listContents.exitCode() == 0, listContents.readAllStandardError().constData()); const QByteArray output = listContents.readAllStandardOutput(); if (output.count("Testing") != 2) qDebug("%s", output.constData()); QCOMPARE(output.count("Testing"), 2); QVERIFY2(output.contains("test.txt"), output.constData()); QVERIFY2(output.contains("archivable.qbs"), output.constData()); } void TestBlackbox::tar() { if (HostOsInfo::hostOs() == HostOsInfo::HostOsWindows) QSKIP("Beware of the msys tar"); OsXTarHealer tarHealer; QDir::setCurrent(testDataDir + "/archiver"); QString binary = findArchiver("tar"); if (binary.isEmpty()) QSKIP("tar not found"); QCOMPARE(runQbs(QbsRunParameters(QStringList() << "archiver.type:tar")), 0); const QString outputFile = relativeProductBuildDir("archivable") + "/archivable.tar.gz"; QVERIFY2(regularFileExists(outputFile), qPrintable(outputFile)); QProcess listContents; listContents.start(binary, QStringList() << "tf" << outputFile); QVERIFY2(listContents.waitForStarted(), qPrintable(listContents.errorString())); QVERIFY2(listContents.waitForFinished(), qPrintable(listContents.errorString())); QVERIFY2(listContents.exitCode() == 0, listContents.readAllStandardError().constData()); QFile listFile("list.txt"); QVERIFY2(listFile.open(QIODevice::ReadOnly), qPrintable(listFile.errorString())); QCOMPARE(listContents.readAllStandardOutput(), listFile.readAll()); } static QStringList sortedFileList(const QByteArray &ba) { auto list = QString::fromUtf8(ba).split(QRegExp("[\r\n]"), QString::SkipEmptyParts); std::sort(list.begin(), list.end()); return list; } void TestBlackbox::zip() { QFETCH(QString, binaryName); int status = 0; const QString binary = findArchiver(binaryName, &status); QCOMPARE(status, 0); if (binary.isEmpty()) QSKIP("zip tool not found"); QDir::setCurrent(testDataDir + "/archiver"); QbsRunParameters params(QStringList() << "archiver.type:zip" << "archiver.command:" + binary); QCOMPARE(runQbs(params), 0); const QString outputFile = relativeProductBuildDir("archivable") + "/archivable.zip"; QVERIFY2(regularFileExists(outputFile), qPrintable(outputFile)); QProcess listContents; if (binaryName == "zip") { // zipinfo is part of Info-Zip listContents.start("zipinfo", QStringList() << "-1" << outputFile); } else { listContents.start(binary, QStringList() << "tf" << outputFile); } QVERIFY2(listContents.waitForStarted(), qPrintable(listContents.errorString())); QVERIFY2(listContents.waitForFinished(), qPrintable(listContents.errorString())); QVERIFY2(listContents.exitCode() == 0, listContents.readAllStandardError().constData()); QFile listFile("list.txt"); QVERIFY2(listFile.open(QIODevice::ReadOnly), qPrintable(listFile.errorString())); QCOMPARE(sortedFileList(listContents.readAllStandardOutput()), sortedFileList(listFile.readAll())); // Make sure the module is still loaded when the java/jar fallback is not available params.arguments << "java.jdkPath:/blubb"; QCOMPARE(runQbs(params), 0); } void TestBlackbox::zip_data() { QTest::addColumn("binaryName"); QTest::newRow("zip") << "zip"; QTest::newRow("jar") << "jar"; } void TestBlackbox::zipInvalid() { QDir::setCurrent(testDataDir + "/archiver"); QbsRunParameters params(QStringList() << "archiver.type:zip" << "archiver.command:/bin/something"); params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("Unknown zip tool 'something'"), m_qbsStderr.constData()); } void TestBlackbox::android() { QFETCH(QString, projectDir); QFETCH(QStringList, productNames); QFETCH(QList, apkFileCounts); QDir::setCurrent(testDataDir + "/android/" + projectDir); Settings s((QString())); Profile p("qbs_autotests-android", &s); if (!p.exists() || !p.value("Android.sdk.ndkDir").isValid()) QSKIP("No suitable Android test profile"); QbsRunParameters params(QStringList("profile:" + p.name()) << "Android.ndk.platform:android-21"); params.useProfile = false; QCOMPARE(runQbs(params), 0); for (int i = 0; i < productNames.count(); ++i) { const QString productName = productNames.at(i); QVERIFY(m_qbsStdout.contains("Creating " + productName.toLocal8Bit() + ".apk")); const QString apkFilePath = relativeProductBuildDir(productName, p.name(), p.name()) + '/' + productName + ".apk"; QVERIFY2(regularFileExists(apkFilePath), qPrintable(apkFilePath)); const QString jarFilePath = findExecutable(QStringList("jar")); QVERIFY(!jarFilePath.isEmpty()); QProcess jar; jar.start(jarFilePath, QStringList() << "-tf" << apkFilePath); QVERIFY2(jar.waitForStarted(), qPrintable(jar.errorString())); QVERIFY2(jar.waitForFinished(), qPrintable(jar.errorString())); QVERIFY2(jar.exitCode() == 0, qPrintable(jar.readAllStandardError().constData())); QCOMPARE(jar.readAllStandardOutput().trimmed().split('\n').count(), apkFileCounts.at(i)); } } void TestBlackbox::android_data() { QTest::addColumn("projectDir"); QTest::addColumn("productNames"); QTest::addColumn>("apkFileCounts"); QTest::newRow("teapot") << "teapot" << QStringList("com.sample.teapot") << (QList() << 25); QTest::newRow("no native") << "no-native" << QStringList("com.example.android.basicmediadecoder") << (QList() << 23); QTest::newRow("multiple libs") << "multiple-libs-per-apk" << QStringList("twolibs") << (QList() << 10); QTest::newRow("multiple apks") << "multiple-apks-per-project" << (QStringList() << "twolibs1" << "twolibs2") << (QList() << 15 << 9); } void TestBlackbox::buildDirectories() { const QString projectDir = QDir::cleanPath(testDataDir + QLatin1String("/build-directories")); const QString projectBuildDir = projectDir + '/' + relativeBuildDir(); QDir::setCurrent(projectDir); QCOMPARE(runQbs(QStringList("-qq")), 0); const QStringList outputLines = QString::fromLocal8Bit(m_qbsStderr.trimmed()).split('\n', QString::SkipEmptyParts); QCOMPARE(outputLines.count(), 4); QCOMPARE(outputLines.at(0).trimmed(), projectDir + '/' + relativeProductBuildDir("p1")); QCOMPARE(outputLines.at(1).trimmed(), projectDir + '/' + relativeProductBuildDir("p2")); QCOMPARE(outputLines.at(2).trimmed(), projectBuildDir); QCOMPARE(outputLines.at(3).trimmed(), projectDir); } void TestBlackbox::changedFiles_data() { QTest::addColumn("useChangedFilesForInitialBuild"); QTest::newRow("initial build with changed files") << true; QTest::newRow("initial build without changed files") << false; } void TestBlackbox::changedFiles() { QFETCH(bool, useChangedFilesForInitialBuild); QDir::setCurrent(testDataDir + "/changed-files"); rmDirR(relativeBuildDir()); const QString changedFile = QDir::cleanPath(QDir::currentPath() + "/file1.cpp"); QbsRunParameters params1; if (useChangedFilesForInitialBuild) params1 = QbsRunParameters(QStringList("--changed-files") << changedFile); // Initial run: Build all files, even though only one of them was marked as changed // (if --changed-files was used). QCOMPARE(runQbs(params1), 0); QCOMPARE(m_qbsStdout.count("compiling"), 3); QCOMPARE(m_qbsStdout.count("creating"), 3); WAIT_FOR_NEW_TIMESTAMP(); touch(QDir::currentPath() + "/main.cpp"); // Now only the file marked as changed must be compiled, even though it hasn't really // changed and another one has. QbsRunParameters params2(QStringList("--changed-files") << changedFile); QCOMPARE(runQbs(params2), 0); QCOMPARE(m_qbsStdout.count("compiling"), 1); QCOMPARE(m_qbsStdout.count("creating"), 1); QVERIFY2(m_qbsStdout.contains("file1.cpp"), m_qbsStdout.constData()); } void TestBlackbox::changeInDisabledProduct() { QDir::setCurrent(testDataDir + "/change-in-disabled-product"); QCOMPARE(runQbs(), 0); WAIT_FOR_NEW_TIMESTAMP(); QFile projectFile("project.qbs"); QVERIFY2(projectFile.open(QIODevice::ReadWrite), qPrintable(projectFile.errorString())); QByteArray content = projectFile.readAll(); content.replace("// 'test2.txt'", "'test2.txt'"); projectFile.resize(0); projectFile.write(content); projectFile.close(); QCOMPARE(runQbs(), 0); } void TestBlackbox::dependenciesProperty() { QDir::setCurrent(testDataDir + QLatin1String("/dependenciesProperty")); QCOMPARE(runQbs(), 0); QFile depsFile(relativeProductBuildDir("product1") + QLatin1String("/product1.deps")); QVERIFY(depsFile.open(QFile::ReadOnly)); QString deps = QString::fromLatin1(depsFile.readAll()); QVERIFY(!deps.isEmpty()); QScriptEngine scriptEngine; QScriptValue scriptValue = scriptEngine.evaluate(deps); QScriptValue product2; QScriptValue qbs; int c = scriptValue.property(QLatin1String("length")).toInt32(); QCOMPARE(c, 2); for (int i = 0; i < c; ++i) { QScriptValue dep = scriptValue.property(i); QString name = dep.property(QLatin1String("name")).toVariant().toString(); if (name == QLatin1String("product2")) product2 = dep; else if (name == QLatin1String("qbs")) qbs = dep; } QVERIFY(qbs.isObject()); QVERIFY(product2.isObject()); QCOMPARE(product2.property(QLatin1String("type")).toString(), QLatin1String("application")); QCOMPARE(product2.property(QLatin1String("narf")).toString(), QLatin1String("zort")); QScriptValue product2_deps = product2.property(QLatin1String("dependencies")); QVERIFY(product2_deps.isObject()); c = product2_deps.property(QLatin1String("length")).toInt32(); QCOMPARE(c, 2); QScriptValue product2_qbs; QScriptValue product2_cpp; for (int i = 0; i < c; ++i) { QScriptValue dep = product2_deps.property(i); QString name = dep.property(QLatin1String("name")).toVariant().toString(); if (name == QLatin1String("cpp")) product2_cpp = dep; else if (name == QLatin1String("qbs")) product2_qbs = dep; } QVERIFY(product2_qbs.isObject()); QVERIFY(product2_cpp.isObject()); QCOMPARE(product2_cpp.property("defines").toString(), QLatin1String("SMURF")); } void TestBlackbox::symlinkRemoval() { if (HostOsInfo::isWindowsHost()) QSKIP("No symlink support on Windows."); QDir::setCurrent(testDataDir + "/symlink-removal"); QVERIFY(QDir::current().mkdir("dir1")); QVERIFY(QDir::current().mkdir("dir2")); QVERIFY(QFile::link("dir2", "dir1/broken-link")); QVERIFY(QFile::link(QFileInfo("dir2").absoluteFilePath(), "dir1/valid-link-to-dir")); QVERIFY(QFile::link(QFileInfo("symlink-removal.qbs").absoluteFilePath(), "dir1/valid-link-to-file")); QCOMPARE(runQbs(), 0); QVERIFY(!QFile::exists("dir1")); QVERIFY(QFile::exists("dir2")); QVERIFY(QFile::exists("symlink-removal.qbs")); } void TestBlackbox::usingsAsSoleInputsNonMultiplexed() { QDir::setCurrent(testDataDir + QLatin1String("/usings-as-sole-inputs-non-multiplexed")); QCOMPARE(runQbs(), 0); const QString p3BuildDir = relativeProductBuildDir("p3"); QVERIFY(regularFileExists(p3BuildDir + "/custom1.out.plus")); QVERIFY(regularFileExists(p3BuildDir + "/custom2.out.plus")); } static bool symlinkExists(const QString &linkFilePath) { return QFileInfo(linkFilePath).isSymLink(); } void TestBlackbox::clean() { const QString appObjectFilePath = relativeProductBuildDir("app") + "/.obj/" + inputDirHash(".") + objectFileName("/main.cpp", profileName()); const QString appExeFilePath = relativeExecutableFilePath("app"); const QString depObjectFilePath = relativeProductBuildDir("dep") + "/.obj/" + inputDirHash(".") + objectFileName("/dep.cpp", profileName()); const QString depLibBase = relativeProductBuildDir("dep") + '/' + QBS_HOST_DYNAMICLIB_PREFIX + "dep"; QString depLibFilePath; QStringList symlinks; if (qbs::Internal::HostOsInfo::isOsxHost()) { depLibFilePath = depLibBase + ".1.1.0" + QBS_HOST_DYNAMICLIB_SUFFIX; symlinks << depLibBase + ".1.1" + QBS_HOST_DYNAMICLIB_SUFFIX << depLibBase + ".1" + QBS_HOST_DYNAMICLIB_SUFFIX << depLibBase + QBS_HOST_DYNAMICLIB_SUFFIX; } else if (qbs::Internal::HostOsInfo::isAnyUnixHost()) { depLibFilePath = depLibBase + QBS_HOST_DYNAMICLIB_SUFFIX + ".1.1.0"; symlinks << depLibBase + QBS_HOST_DYNAMICLIB_SUFFIX + ".1.1" << depLibBase + QBS_HOST_DYNAMICLIB_SUFFIX + ".1" << depLibBase + QBS_HOST_DYNAMICLIB_SUFFIX; } else { depLibFilePath = depLibBase + QBS_HOST_DYNAMICLIB_SUFFIX; } QDir::setCurrent(testDataDir + "/clean"); // Default behavior: Remove only temporaries. QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QVERIFY(regularFileExists(depObjectFilePath)); QVERIFY(regularFileExists(depLibFilePath)); foreach (const QString &symLink, symlinks) QVERIFY2(regularFileExists(symLink), qPrintable(symLink)); QCOMPARE(runQbs(QbsRunParameters("clean")), 0); QVERIFY(!QFile(appObjectFilePath).exists()); QVERIFY(regularFileExists(appExeFilePath)); QVERIFY(!QFile(depObjectFilePath).exists()); QVERIFY(regularFileExists(depLibFilePath)); foreach (const QString &symLink, symlinks) QVERIFY2(symlinkExists(symLink), qPrintable(symLink)); // Remove all. QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QCOMPARE(runQbs(QbsRunParameters(QLatin1String("clean"), QStringList("--all-artifacts"))), 0); QVERIFY(!QFile(appObjectFilePath).exists()); QVERIFY(!QFile(appExeFilePath).exists()); QVERIFY(!QFile(depObjectFilePath).exists()); QVERIFY(!QFile(depLibFilePath).exists()); foreach (const QString &symLink, symlinks) QVERIFY2(!symlinkExists(symLink), qPrintable(symLink)); // Remove all, with a forced re-resolve in between. // This checks that rescuable artifacts are also removed. QCOMPARE(runQbs(QbsRunParameters(QStringList() << "cpp.optimization:none")), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList() << "cpp.optimization:fast")), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QCOMPARE(runQbs(QbsRunParameters(QLatin1String("clean"), QStringList("--all-artifacts"))), 0); QVERIFY(!QFile(appObjectFilePath).exists()); QVERIFY(!QFile(appExeFilePath).exists()); QVERIFY(!QFile(depObjectFilePath).exists()); QVERIFY(!QFile(depLibFilePath).exists()); foreach (const QString &symLink, symlinks) QVERIFY2(!symlinkExists(symLink), qPrintable(symLink)); // Dry run. QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QCOMPARE(runQbs(QbsRunParameters(QLatin1String("clean"), QStringList("--all-artifacts") << "-n")), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QVERIFY(regularFileExists(depObjectFilePath)); QVERIFY(regularFileExists(depLibFilePath)); foreach (const QString &symLink, symlinks) QVERIFY2(symlinkExists(symLink), qPrintable(symLink)); // Product-wise, dependency only. QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QVERIFY(regularFileExists(depObjectFilePath)); QVERIFY(regularFileExists(depLibFilePath)); QCOMPARE(runQbs(QbsRunParameters(QLatin1String("clean"), QStringList("--all-artifacts") << "-p" << "dep")), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QVERIFY(!QFile(depObjectFilePath).exists()); QVERIFY(!QFile(depLibFilePath).exists()); foreach (const QString &symLink, symlinks) QVERIFY2(!symlinkExists(symLink), qPrintable(symLink)); // Product-wise, dependent product only. QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(appObjectFilePath)); QVERIFY(regularFileExists(appExeFilePath)); QVERIFY(regularFileExists(depObjectFilePath)); QVERIFY(regularFileExists(depLibFilePath)); QCOMPARE(runQbs(QbsRunParameters(QLatin1String("clean"), QStringList("--all-artifacts") << "-p" << "app")), 0); QVERIFY(!QFile(appObjectFilePath).exists()); QVERIFY(!QFile(appExeFilePath).exists()); QVERIFY(regularFileExists(depObjectFilePath)); QVERIFY(regularFileExists(depLibFilePath)); foreach (const QString &symLink, symlinks) QVERIFY2(symlinkExists(symLink), qPrintable(symLink)); } void TestBlackbox::concurrentExecutor() { QDir::setCurrent(testDataDir + "/concurrent-executor"); QCOMPARE(runQbs(QStringList() << "-j" << "2"), 0); QVERIFY2(!m_qbsStderr.contains("ASSERT"), m_qbsStderr.constData()); } void TestBlackbox::renameDependency() { QDir::setCurrent(testDataDir + "/renameDependency"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); QDir::setCurrent(testDataDir + "/renameDependency/work"); QCOMPARE(runQbs(), 0); WAIT_FOR_NEW_TIMESTAMP(); QFile::remove("lib.h"); QFile::remove("lib.cpp"); ccp("../after", "."); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); } void TestBlackbox::separateDebugInfo() { QDir::setCurrent(testDataDir + "/separate-debug-info"); QCOMPARE(runQbs(), 0); Settings settings((QString())); Profile buildProfile(profileName(), &settings); QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList(); QStringList targetOS = buildProfile.value("qbs.targetOS").toStringList(); if (targetOS.contains("darwin") || (targetOS.isEmpty() && HostOsInfo::isOsxHost())) { QVERIFY(QFile::exists(relativeProductBuildDir("app1") + "/app1.app.dSYM")); QVERIFY(!QFile::exists(relativeProductBuildDir("app2") + "/app2.app.dSYM")); QVERIFY(QFile::exists(relativeProductBuildDir("foo1") + "/foo1.framework.dSYM")); QVERIFY(!QFile::exists(relativeProductBuildDir("foo2") + "/foo2.framework.dSYM")); } else if (toolchain.contains("gcc")) { QVERIFY(QFile::exists(relativeProductBuildDir("app1") + "/app1.debug")); QVERIFY(!QFile::exists(relativeProductBuildDir("app2") + "/app2.debug")); QVERIFY(QFile::exists(relativeProductBuildDir("foo1") + "/libfoo1.so.debug")); QVERIFY(!QFile::exists(relativeProductBuildDir("foo2") + "/libfoo2.so.debug")); } else if (toolchain.contains("msvc")) { QVERIFY(QFile::exists(relativeProductBuildDir("app1") + "/app1.pdb")); QVERIFY(QFile::exists(relativeProductBuildDir("foo1") + "/foo1.pdb")); // MSVC's linker even creates a pdb file if /Z7 is passed to the compiler. } else { QSKIP("Unsupported toolchain. Skipping."); } } void TestBlackbox::track_qrc() { QDir::setCurrent(testDataDir + "/qrc"); QCOMPARE(runQbs(), 0); const QString fileName = relativeExecutableFilePath("i"); QVERIFY2(regularFileExists(fileName), qPrintable(fileName)); QDateTime dt = QFileInfo(fileName).lastModified(); WAIT_FOR_NEW_TIMESTAMP(); { QFile f("stuff.txt"); f.remove(); QVERIFY(f.open(QFile::WriteOnly)); f.write("bla"); f.close(); } QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(fileName)); QVERIFY(dt < QFileInfo(fileName).lastModified()); } void TestBlackbox::track_qobject_change() { QDir::setCurrent(testDataDir + "/trackQObjChange"); copyFileAndUpdateTimestamp("bla_qobject.h", "bla.h"); QCOMPARE(runQbs(), 0); const QString productFilePath = relativeExecutableFilePath("i"); QVERIFY2(regularFileExists(productFilePath), qPrintable(productFilePath)); QString moc_bla_objectFileName = relativeProductBuildDir("i") + "/.obj/" + inputDirHash("GeneratedFiles") + objectFileName("/moc_bla.cpp", profileName()); QVERIFY2(regularFileExists(moc_bla_objectFileName), qPrintable(moc_bla_objectFileName)); WAIT_FOR_NEW_TIMESTAMP(); copyFileAndUpdateTimestamp("bla_noqobject.h", "bla.h"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(productFilePath)); QVERIFY(!QFile(moc_bla_objectFileName).exists()); } void TestBlackbox::trackAddFile() { QProcess process; QList output; QDir::setCurrent(testDataDir + "/trackAddFile"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); QDir::setCurrent(testDataDir + "/trackAddFile/work"); QCOMPARE(runQbs(), 0); process.start(relativeExecutableFilePath("someapp"), QStringList()); QVERIFY2(process.waitForStarted(), qPrintable(process.errorString())); QVERIFY2(process.waitForFinished(), qPrintable(process.errorString())); QCOMPARE(process.exitCode(), 0); output = process.readAllStandardOutput().split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "Hello World!"); QCOMPARE(output.takeFirst().trimmed().constData(), "NARF!"); QString unchangedObjectFile = relativeBuildDir() + objectFileName("/someapp/narf.cpp", profileName()); QDateTime unchangedObjectFileTime1 = QFileInfo(unchangedObjectFile).lastModified(); WAIT_FOR_NEW_TIMESTAMP(); ccp("../after", "."); touch("project.qbs"); touch("main.cpp"); QCOMPARE(runQbs(), 0); process.start(relativeExecutableFilePath("someapp"), QStringList()); QVERIFY(process.waitForStarted()); QVERIFY(process.waitForFinished()); QCOMPARE(process.exitCode(), 0); output = process.readAllStandardOutput().split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "Hello World!"); QCOMPARE(output.takeFirst().trimmed().constData(), "NARF!"); QCOMPARE(output.takeFirst().trimmed().constData(), "ZORT!"); // the object file of the untouched source should not have changed QDateTime unchangedObjectFileTime2 = QFileInfo(unchangedObjectFile).lastModified(); QCOMPARE(unchangedObjectFileTime1, unchangedObjectFileTime2); } void TestBlackbox::trackExternalProductChanges() { QDir::setCurrent(testDataDir + "/trackExternalProductChanges"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); QVERIFY(!m_qbsStdout.contains("compiling environmentChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling fileExists.cpp")); QbsRunParameters params; params.environment.insert("QBS_TEST_PULL_IN_FILE_VIA_ENV", "1"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling main.cpp")); QVERIFY(m_qbsStdout.contains("compiling environmentChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling fileExists.cpp")); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); QVERIFY(!m_qbsStdout.contains("compiling environmentChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling fileExists.cpp")); WAIT_FOR_NEW_TIMESTAMP(); QFile jsFile("fileList.js"); QVERIFY(jsFile.open(QIODevice::ReadWrite)); QByteArray jsCode = jsFile.readAll(); jsCode.replace("return []", "return ['jsFileChange.cpp']"); jsFile.resize(0); jsFile.write(jsCode); jsFile.close(); QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("compiling main.cpp")); QVERIFY(!m_qbsStdout.contains("compiling environmentChange.cpp")); QVERIFY(m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling fileExists.cpp")); rmDirR(relativeBuildDir()); QVERIFY(jsFile.open(QIODevice::ReadWrite)); jsCode = jsFile.readAll(); jsCode.replace("['jsFileChange.cpp']", "[]"); jsFile.resize(0); jsFile.write(jsCode); jsFile.close(); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); QVERIFY(!m_qbsStdout.contains("compiling environmentChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling fileExists.cpp")); QFile cppFile("fileExists.cpp"); QVERIFY(cppFile.open(QIODevice::WriteOnly)); cppFile.write("void fileExists() { }\n"); cppFile.close(); QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("compiling main.cpp")); QVERIFY(!m_qbsStdout.contains("compiling environmentChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(m_qbsStdout.contains("compiling fileExists.cpp")); rmDirR(relativeBuildDir()); Settings s((QString())); const Profile profile(profileName(), &s); const QStringList toolchainTypes = profile.value("qbs.toolchain").toStringList(); if (!toolchainTypes.contains("gcc")) QSKIP("Need GCC-like compiler to run this test"); params.environment = QProcessEnvironment::systemEnvironment(); params.environment.insert("INCLUDE_PATH_TEST", "1"); params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("hiddenheaderqbs.h"), m_qbsStderr.constData()); params.environment.insert("CPLUS_INCLUDE_PATH", QDir::toNativeSeparators(QDir::currentPath() + "/hidden")); params.expectFailure = false; QCOMPARE(runQbs(params), 0); } void TestBlackbox::trackGroupConditionChange() { QbsRunParameters params; params.expectFailure = true; QDir::setCurrent(testDataDir + "/group-condition-change"); QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStderr.contains("jibbetnich")); params.arguments = QStringList("project.kaputt:false"); params.expectFailure = false; QCOMPARE(runQbs(params), 0); } void TestBlackbox::trackRemoveFile() { QProcess process; QList output; QDir::setCurrent(testDataDir + "/trackAddFile"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); ccp("after", "work"); QDir::setCurrent(testDataDir + "/trackAddFile/work"); QCOMPARE(runQbs(), 0); process.start(relativeExecutableFilePath("someapp"), QStringList()); QVERIFY2(process.waitForStarted(), qPrintable(process.errorString())); QVERIFY2(process.waitForFinished(), qPrintable(process.errorString())); QCOMPARE(process.exitCode(), 0); output = process.readAllStandardOutput().split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "Hello World!"); QCOMPARE(output.takeFirst().trimmed().constData(), "NARF!"); QCOMPARE(output.takeFirst().trimmed().constData(), "ZORT!"); QString unchangedObjectFile = relativeBuildDir() + objectFileName("/someapp/narf.cpp", profileName()); QDateTime unchangedObjectFileTime1 = QFileInfo(unchangedObjectFile).lastModified(); WAIT_FOR_NEW_TIMESTAMP(); QFile::remove("project.qbs"); QFile::remove("main.cpp"); QFile::copy("../before/project.qbs", "project.qbs"); QFile::copy("../before/main.cpp", "main.cpp"); QVERIFY(QFile::remove("zort.h")); QVERIFY(QFile::remove("zort.cpp")); QCOMPARE(runQbs(QbsRunParameters(QLatin1String("resolve"))), 0); touch("main.cpp"); touch("project.qbs"); QCOMPARE(runQbs(), 0); process.start(relativeExecutableFilePath("someapp"), QStringList()); QVERIFY(process.waitForStarted()); QVERIFY(process.waitForFinished()); QCOMPARE(process.exitCode(), 0); output = process.readAllStandardOutput().split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "Hello World!"); QCOMPARE(output.takeFirst().trimmed().constData(), "NARF!"); // the object file of the untouched source should not have changed QDateTime unchangedObjectFileTime2 = QFileInfo(unchangedObjectFile).lastModified(); QCOMPARE(unchangedObjectFileTime1, unchangedObjectFileTime2); // the object file for the removed cpp file should have vanished too QVERIFY(!regularFileExists(relativeBuildDir() + objectFileName("/someapp/zort.cpp", profileName()))); } void TestBlackbox::trackAddFileTag() { QProcess process; QList output; QDir::setCurrent(testDataDir + "/trackFileTags"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); QDir::setCurrent(testDataDir + "/trackFileTags/work"); QCOMPARE(runQbs(), 0); process.start(relativeExecutableFilePath("someapp"), QStringList()); QVERIFY2(process.waitForStarted(), qPrintable(process.errorString())); QVERIFY2(process.waitForFinished(), qPrintable(process.errorString())); QCOMPARE(process.exitCode(), 0); output = process.readAllStandardOutput().split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "there's no foo here"); WAIT_FOR_NEW_TIMESTAMP(); ccp("../after", "."); touch("main.cpp"); touch("project.qbs"); QCOMPARE(runQbs(), 0); process.start(relativeExecutableFilePath("someapp"), QStringList()); QVERIFY(process.waitForStarted()); QVERIFY(process.waitForFinished()); QCOMPARE(process.exitCode(), 0); output = process.readAllStandardOutput().split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "there's 15 foo here"); } void TestBlackbox::trackRemoveFileTag() { QProcess process; QList output; QDir::setCurrent(testDataDir + "/trackFileTags"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("after", "work"); QDir::setCurrent(testDataDir + "/trackFileTags/work"); QCOMPARE(runQbs(), 0); // check if the artifacts are here that will become stale in the 2nd step QVERIFY(regularFileExists(relativeProductBuildDir("someapp") + "/.obj/" + inputDirHash(".") + objectFileName("/main_foo.cpp", profileName()))); QVERIFY(regularFileExists(relativeProductBuildDir("someapp") + "/main_foo.cpp")); QVERIFY(regularFileExists(relativeProductBuildDir("someapp") + "/main.foo")); process.start(relativeExecutableFilePath("someapp"), QStringList()); QVERIFY(process.waitForStarted()); QVERIFY(process.waitForFinished()); QCOMPARE(process.exitCode(), 0); output = process.readAllStandardOutput().split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "there's 15 foo here"); WAIT_FOR_NEW_TIMESTAMP(); ccp("../before", "."); touch("main.cpp"); touch("project.qbs"); QCOMPARE(runQbs(), 0); process.start(relativeExecutableFilePath("someapp"), QStringList()); QVERIFY(process.waitForStarted()); QVERIFY(process.waitForFinished()); QCOMPARE(process.exitCode(), 0); output = process.readAllStandardOutput().split('\n'); QCOMPARE(output.takeFirst().trimmed().constData(), "there's no foo here"); // check if stale artifacts have been removed QCOMPARE(regularFileExists(relativeProductBuildDir("someapp") + "/.obj/" + inputDirHash(".") + objectFileName("/main_foo.cpp", profileName())), false); QCOMPARE(regularFileExists(relativeProductBuildDir("someapp") + "/main_foo.cpp"), false); QCOMPARE(regularFileExists(relativeProductBuildDir("someapp") + "/main.foo"), false); } void TestBlackbox::trackAddMocInclude() { QDir::setCurrent(testDataDir + "/trackAddMocInclude"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); QDir::setCurrent(testDataDir + "/trackAddMocInclude/work"); // The build must fail because the main.moc include is missing. QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); WAIT_FOR_NEW_TIMESTAMP(); ccp("../after", "."); touch("main.cpp"); QCOMPARE(runQbs(), 0); } void TestBlackbox::trackAddProduct() { QDir::setCurrent(testDataDir + "/trackProducts"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); QDir::setCurrent(testDataDir + "/trackProducts/work"); QbsRunParameters params(QStringList() << "-f" << "trackProducts.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling foo.cpp")); QVERIFY(m_qbsStdout.contains("compiling bar.cpp")); QVERIFY(m_qbsStdout.contains("linking product1")); QVERIFY(m_qbsStdout.contains("linking product2")); WAIT_FOR_NEW_TIMESTAMP(); ccp("../after", "."); touch("trackProducts.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling zoo.cpp")); QVERIFY(m_qbsStdout.contains("linking product3")); QVERIFY(!m_qbsStdout.contains("compiling foo.cpp")); QVERIFY(!m_qbsStdout.contains("compiling bar.cpp")); QVERIFY(!m_qbsStdout.contains("linking product1")); QVERIFY(!m_qbsStdout.contains("linking product2")); } void TestBlackbox::trackRemoveProduct() { QDir::setCurrent(testDataDir + "/trackProducts"); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); ccp("after", "work"); QDir::setCurrent(testDataDir + "/trackProducts/work"); QbsRunParameters params(QStringList() << "-f" << "trackProducts.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling foo.cpp")); QVERIFY(m_qbsStdout.contains("compiling bar.cpp")); QVERIFY(m_qbsStdout.contains("compiling zoo.cpp")); QVERIFY(m_qbsStdout.contains("linking product1")); QVERIFY(m_qbsStdout.contains("linking product2")); QVERIFY(m_qbsStdout.contains("linking product3")); WAIT_FOR_NEW_TIMESTAMP(); QFile::remove("zoo.cpp"); QFile::remove("product3.qbs"); copyFileAndUpdateTimestamp("../before/trackProducts.qbs", "trackProducts.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling foo.cpp")); QVERIFY(!m_qbsStdout.contains("compiling bar.cpp")); QVERIFY(!m_qbsStdout.contains("compiling zoo.cpp")); QVERIFY(!m_qbsStdout.contains("linking product1")); QVERIFY(!m_qbsStdout.contains("linking product2")); QVERIFY(!m_qbsStdout.contains("linking product3")); } void TestBlackbox::wildcardRenaming() { QDir::setCurrent(testDataDir + "/wildcard_renaming"); QCOMPARE(runQbs(QbsRunParameters("install")), 0); QVERIFY(QFileInfo(defaultInstallRoot + "/pioniere.txt").exists()); QFile::rename(QDir::currentPath() + "/pioniere.txt", QDir::currentPath() + "/fdj.txt"); QCOMPARE(runQbs(QbsRunParameters(QLatin1String("install"), QStringList("--clean-install-root"))), 0); QVERIFY(!QFileInfo(defaultInstallRoot + "/pioniere.txt").exists()); QVERIFY(QFileInfo(defaultInstallRoot + "/fdj.txt").exists()); } void TestBlackbox::recursiveRenaming() { QDir::setCurrent(testDataDir + "/recursive_renaming"); QCOMPARE(runQbs(QbsRunParameters("install")), 0); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/wasser.txt").exists()); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/subdir/blubb.txt").exists()); WAIT_FOR_NEW_TIMESTAMP(); QVERIFY(QFile::rename(QDir::currentPath() + "/dir/wasser.txt", QDir::currentPath() + "/dir/wein.txt")); QCOMPARE(runQbs(QbsRunParameters(QLatin1String("install"), QStringList("--clean-install-root"))), 0); QVERIFY(!QFileInfo(defaultInstallRoot + "/dir/wasser.txt").exists()); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/wein.txt").exists()); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/subdir/blubb.txt").exists()); } void TestBlackbox::recursiveWildcards() { QDir::setCurrent(testDataDir + "/recursive_wildcards"); QCOMPARE(runQbs(QbsRunParameters("install")), 0); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/file1.txt").exists()); QVERIFY(QFileInfo(defaultInstallRoot + "/dir/file2.txt").exists()); } void TestBlackbox::ruleConditions() { QDir::setCurrent(testDataDir + "/ruleConditions"); QCOMPARE(runQbs(), 0); QVERIFY(QFileInfo(relativeExecutableFilePath("zorted")).exists()); QVERIFY(QFileInfo(relativeExecutableFilePath("unzorted")).exists()); QVERIFY(QFileInfo(relativeProductBuildDir("zorted") + "/zorted.foo.narf.zort").exists()); QVERIFY(!QFileInfo(relativeProductBuildDir("unzorted") + "/unzorted.foo.narf.zort").exists()); } void TestBlackbox::ruleCycle() { QDir::setCurrent(testDataDir + "/ruleCycle"); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStderr.contains("Cycle detected in rule dependencies")); } void TestBlackbox::overrideProjectProperties() { QDir::setCurrent(testDataDir + "/overrideProjectProperties"); QCOMPARE(runQbs(QbsRunParameters(QStringList() << QLatin1String("-f") << QLatin1String("project.qbs") << QLatin1String("project.nameSuffix:ForYou") << QLatin1String("project.someBool:false") << QLatin1String("project.someInt:156") << QLatin1String("project.someStringList:one") << QLatin1String("MyAppForYou.mainFile:main.cpp"))), 0); QVERIFY(regularFileExists(relativeExecutableFilePath("MyAppForYou"))); QVERIFY(QFile::remove(relativeBuildGraphFilePath())); QbsRunParameters params; params.arguments << QLatin1String("-f") << QLatin1String("project_using_helper_lib.qbs"); params.expectFailure = true; QVERIFY(runQbs(params) != 0); rmDirR(relativeBuildDir()); params.arguments = QStringList() << QLatin1String("-f") << QLatin1String("project_using_helper_lib.qbs") << QLatin1String("project.linkSuccessfully:true"); params.expectFailure = false; QCOMPARE(runQbs(params), 0); } void TestBlackbox::productProperties() { QDir::setCurrent(testDataDir + "/productproperties"); QCOMPARE(runQbs(QbsRunParameters(QStringList() << QLatin1String("-f") << QLatin1String("project.qbs"))), 0); QVERIFY(regularFileExists(relativeExecutableFilePath("blubb_user"))); } void TestBlackbox::propertyChanges() { QDir::setCurrent(testDataDir + "/propertyChanges"); QFile projectFile("project.qbs"); QbsRunParameters params(QStringList() << "-f" << "project.qbs"); // Initial build. QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(m_qbsStdout.contains("linking product 1.debug")); QVERIFY(m_qbsStdout.contains("generated.txt")); QVERIFY(m_qbsStdout.contains("Making output from input")); QVERIFY(m_qbsStdout.contains("Making output from other output")); QFile generatedFile(relativeProductBuildDir("generated text file") + "/generated.txt"); QVERIFY(generatedFile.open(QIODevice::ReadOnly)); QCOMPARE(generatedFile.readAll(), QByteArray("prefix 1contents 1suffix 1")); generatedFile.close(); // Incremental build with no changes. QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp.cpp")); QVERIFY(!m_qbsStdout.contains("linking")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); // Incremental build with no changes, but updated project file timestamp. WAIT_FOR_NEW_TIMESTAMP(); QVERIFY(projectFile.open(QIODevice::ReadWrite | QIODevice::Append)); projectFile.write("\n"); projectFile.close(); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(!m_qbsStdout.contains("linking")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); // Incremental build, input property changed for first product WAIT_FOR_NEW_TIMESTAMP(); QVERIFY(projectFile.open(QIODevice::ReadWrite)); QByteArray contents = projectFile.readAll(); contents.replace("blubb1", "blubb01"); projectFile.resize(0); projectFile.write(contents); projectFile.close(); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(m_qbsStdout.contains("linking product 1.debug")); QVERIFY(!m_qbsStdout.contains("linking product 2")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("linking library")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); // Incremental build, input property changed via project for second product. WAIT_FOR_NEW_TIMESTAMP(); QVERIFY(projectFile.open(QIODevice::ReadWrite)); contents = projectFile.readAll(); contents.replace("blubb2", "blubb02"); projectFile.resize(0); projectFile.write(contents); projectFile.close(); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); // Incremental build, input property changed via command line for second product. params.arguments << "project.projectDefines:blubb002"; QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("generated.txt")); params.arguments.removeLast(); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); // Incremental build, input property changed via environment for third product. params.environment.insert("QBS_BLACKBOX_DEFINE", "newvalue"); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(!m_qbsStdout.contains("linking product 2")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); params.environment.clear(); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(!m_qbsStdout.contains("linking product 2")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); // Incremental build, module property changed via command line. params.arguments << "qbs.enableDebugCode:false"; QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(m_qbsStdout.contains("linking product 1.release")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); params.arguments.removeLast(); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(m_qbsStdout.contains("linking product 1.debug")); QVERIFY(m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); // Incremental build, non-essential dependency removed. WAIT_FOR_NEW_TIMESTAMP(); QVERIFY(projectFile.open(QIODevice::ReadWrite)); contents = projectFile.readAll(); contents.replace("Depends { name: 'library' }", "// Depends { name: 'library' }"); projectFile.resize(0); projectFile.write(contents); projectFile.close(); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("linking product 1")); QVERIFY(m_qbsStdout.contains("linking product 2")); QVERIFY(!m_qbsStdout.contains("linking product 3")); QVERIFY(!m_qbsStdout.contains("linking library")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); // Incremental build, prepare script of a transformer changed. WAIT_FOR_NEW_TIMESTAMP(); QVERIFY(projectFile.open(QIODevice::ReadWrite)); contents = projectFile.readAll(); contents.replace("contents 1", "contents 2"); projectFile.resize(0); projectFile.write(contents); projectFile.close(); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); QVERIFY(generatedFile.open(QIODevice::ReadOnly)); QCOMPARE(generatedFile.readAll(), QByteArray("prefix 1contents 2suffix 1")); generatedFile.close(); // Incremental build, product property used in JavaScript command changed. WAIT_FOR_NEW_TIMESTAMP(); QVERIFY(projectFile.open(QIODevice::ReadWrite)); contents = projectFile.readAll(); contents.replace("prefix 1", "prefix 2"); projectFile.resize(0); projectFile.write(contents); projectFile.close(); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); QVERIFY(generatedFile.open(QIODevice::ReadOnly)); QCOMPARE(generatedFile.readAll(), QByteArray("prefix 2contents 2suffix 1")); generatedFile.close(); // Incremental build, project property used in JavaScript command changed. WAIT_FOR_NEW_TIMESTAMP(); QVERIFY(projectFile.open(QIODevice::ReadWrite)); contents = projectFile.readAll(); contents.replace("suffix 1", "suffix 2"); projectFile.resize(0); projectFile.write(contents); projectFile.close(); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(m_qbsStdout.contains("generated.txt")); QVERIFY(!m_qbsStdout.contains("Making output from input")); QVERIFY(!m_qbsStdout.contains("Making output from other output")); QVERIFY(generatedFile.open(QIODevice::ReadOnly)); QCOMPARE(generatedFile.readAll(), QByteArray("prefix 2contents 2suffix 2")); generatedFile.close(); // Incremental build, prepare script of a rule in a module changed. WAIT_FOR_NEW_TIMESTAMP(); QFile moduleFile("modules/TestModule/module.qbs"); QVERIFY(moduleFile.open(QIODevice::ReadWrite)); contents = moduleFile.readAll(); contents.replace("// print('Change in source code')", "print('Change in source code')"); moduleFile.resize(0); moduleFile.write(contents); moduleFile.close(); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling source1.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source2.cpp")); QVERIFY(!m_qbsStdout.contains("compiling source3.cpp")); QVERIFY(!m_qbsStdout.contains("compiling lib.cpp")); QVERIFY(!m_qbsStdout.contains("generated.txt")); QVERIFY(m_qbsStdout.contains("Making output from input")); QVERIFY(m_qbsStdout.contains("Making output from other output")); } void TestBlackbox::qobjectInObjectiveCpp() { if (!HostOsInfo::isOsxHost()) QSKIP("only applies on OS X"); const QString testDir = testDataDir + "/qobject-in-mm"; QDir::setCurrent(testDir); QCOMPARE(runQbs(), 0); } void TestBlackbox::dynamicMultiplexRule() { const QString testDir = testDataDir + "/dynamicMultiplexRule"; QDir::setCurrent(testDir); QCOMPARE(runQbs(), 0); const QString outputFilePath = relativeProductBuildDir("dynamicMultiplexRule") + "/stuff-from-3-inputs"; QVERIFY(regularFileExists(outputFilePath)); WAIT_FOR_NEW_TIMESTAMP(); touch("two.txt"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(outputFilePath)); } void TestBlackbox::dynamicRuleOutputs() { const QString testDir = testDataDir + "/dynamicRuleOutputs"; QDir::setCurrent(testDir); if (QFile::exists("work")) rmDirR("work"); QDir().mkdir("work"); ccp("before", "work"); QDir::setCurrent(testDir + "/work"); QCOMPARE(runQbs(), 0); const QString appFile = relativeExecutableFilePath("genlexer"); const QString headerFile1 = relativeProductBuildDir("genlexer") + "/GeneratedFiles/numberscanner.h"; const QString sourceFile1 = relativeProductBuildDir("genlexer") + "/GeneratedFiles/numberscanner.c"; const QString sourceFile2 = relativeProductBuildDir("genlexer") + "/GeneratedFiles/lex.yy.c"; // Check build #1: source and header file name are specified in numbers.l QVERIFY(regularFileExists(appFile)); QVERIFY(regularFileExists(headerFile1)); QVERIFY(regularFileExists(sourceFile1)); QVERIFY(!QFile::exists(sourceFile2)); QDateTime appFileTimeStamp1 = QFileInfo(appFile).lastModified(); WAIT_FOR_NEW_TIMESTAMP(); copyFileAndUpdateTimestamp("../after/numbers.l", "numbers.l"); QCOMPARE(runQbs(), 0); // Check build #2: no file names are specified in numbers.l // flex will default to lex.yy.c without header file. QDateTime appFileTimeStamp2 = QFileInfo(appFile).lastModified(); QVERIFY(appFileTimeStamp1 < appFileTimeStamp2); QVERIFY(!QFile::exists(headerFile1)); QVERIFY(!QFile::exists(sourceFile1)); QVERIFY(regularFileExists(sourceFile2)); WAIT_FOR_NEW_TIMESTAMP(); copyFileAndUpdateTimestamp("../before/numbers.l", "numbers.l"); QCOMPARE(runQbs(), 0); // Check build #3: source and header file name are specified in numbers.l QDateTime appFileTimeStamp3 = QFileInfo(appFile).lastModified(); QVERIFY(appFileTimeStamp2 < appFileTimeStamp3); QVERIFY(regularFileExists(appFile)); QVERIFY(regularFileExists(headerFile1)); QVERIFY(regularFileExists(sourceFile1)); QVERIFY(!QFile::exists(sourceFile2)); } void TestBlackbox::erroneousFiles_data() { QTest::addColumn("errorMessage"); QTest::newRow("nonexistentWorkingDir") << "The working directory '.does.not.exist' for process '.*ls' is invalid."; } void TestBlackbox::erroneousFiles() { QFETCH(QString, errorMessage); QDir::setCurrent(testDataDir + "/erroneous/" + QTest::currentDataTag()); QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QString err = QString::fromLocal8Bit(m_qbsStderr); if (!err.contains(QRegExp(errorMessage))) { qDebug() << "Output: " << err; qDebug() << "Expected: " << errorMessage; QFAIL("Unexpected error message."); } } void TestBlackbox::exportRule() { QDir::setCurrent(testDataDir + "/export-rule"); QbsRunParameters params; QCOMPARE(runQbs(params), 0); } void TestBlackbox::fileDependencies() { QDir::setCurrent(testDataDir + "/fileDependencies"); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling narf.cpp")); QVERIFY(m_qbsStdout.contains("compiling zort.cpp")); const QString productFileName = relativeExecutableFilePath("myapp"); QVERIFY2(regularFileExists(productFileName), qPrintable(productFileName)); // Incremental build without changes. QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("compiling")); QVERIFY(!m_qbsStdout.contains("linking")); // Incremental build with changed file dependency. WAIT_FOR_NEW_TIMESTAMP(); touch("awesomelib/awesome.h"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling narf.cpp")); QVERIFY(!m_qbsStdout.contains("compiling zort.cpp")); // Incremental build with changed 2nd level file dependency. WAIT_FOR_NEW_TIMESTAMP(); touch("awesomelib/magnificent.h"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("compiling narf.cpp")); QVERIFY(!m_qbsStdout.contains("compiling zort.cpp")); } void TestBlackbox::installedTransformerOutput() { QDir::setCurrent(testDataDir + "/installed-transformer-output"); QCOMPARE(runQbs(), 0); const QString installedFilePath = defaultInstallRoot + "/textfiles/HelloWorld.txt"; QVERIFY2(QFile::exists(installedFilePath), qPrintable(installedFilePath)); } void TestBlackbox::inputsFromDependencies() { QDir::setCurrent(testDataDir + "/inputs-from-dependencies"); QbsRunParameters params(QStringList("-qq")); QCOMPARE(runQbs(params), 0); const QList output = m_qbsStderr.trimmed().split('\n'); QVERIFY2(output.count() == 3, m_qbsStderr.constData()); } void TestBlackbox::installPackage() { if (HostOsInfo::hostOs() == HostOsInfo::HostOsWindows) QSKIP("Beware of the msys tar"); QString binary = findArchiver("tar"); if (binary.isEmpty()) QSKIP("tar not found"); OsXTarHealer tarHealer; QDir::setCurrent(testDataDir + "/installpackage"); QCOMPARE(runQbs(), 0); const QString tarFilePath = relativeProductBuildDir("tar-package") + "/tar-package.tar.gz"; QVERIFY2(regularFileExists(tarFilePath), qPrintable(tarFilePath)); QProcess tarList; tarList.start(binary, QStringList() << "tf" << tarFilePath); QVERIFY2(tarList.waitForStarted(), qPrintable(tarList.errorString())); QVERIFY2(tarList.waitForFinished(), qPrintable(tarList.errorString())); const QList outputLines = tarList.readAllStandardOutput().split('\n'); QList cleanOutputLines; foreach (const QByteArray &line, outputLines) { const QByteArray trimmedLine = line.trimmed(); if (!trimmedLine.isEmpty()) cleanOutputLines << trimmedLine; } QCOMPARE(cleanOutputLines.count(), 3); foreach (const QByteArray &line, cleanOutputLines) { QVERIFY2(line.contains("public_tool") || line.contains("mylib") || line.contains("lib.h"), line.constData()); } } void TestBlackbox::installable() { QDir::setCurrent(testDataDir + "/installable"); QCOMPARE(runQbs(), 0); QFile installList(relativeProductBuildDir("install-list") + "/installed-files.txt"); QVERIFY2(installList.open(QIODevice::ReadOnly), qPrintable(installList.errorString())); QCOMPARE(installList.readAll().count('\n'), 2); } void TestBlackbox::installTree() { QDir::setCurrent(testDataDir + "/install-tree"); QbsRunParameters params; params.command = "install"; QCOMPARE(runQbs(params), 0); const QString installRoot = relativeBuildDir() + "/install-root/"; QVERIFY(QFile::exists(installRoot + "content/foo.txt")); QVERIFY(QFile::exists(installRoot + "content/subdir1/bar.txt")); QVERIFY(QFile::exists(installRoot + "content/subdir2/baz.txt")); } static QProcessEnvironment processEnvironmentWithCurrentDirectoryInLibraryPath() { QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert(HostOsInfo::libraryPathEnvironmentVariable(), (QStringList() << env.value(HostOsInfo::libraryPathEnvironmentVariable()) << ".") .join(HostOsInfo::pathListSeparator())); return env; } void TestBlackbox::java() { Settings settings((QString())); Profile p(profileName(), &settings); QDir::setCurrent(testDataDir + "/java"); int status = runQbs(); if (p.value("java.jdkPath").toString().isEmpty() && status != 0 && m_qbsStderr.contains("jdkPath")) { QSKIP("java.jdkPath not set and automatic detection failed"); } QCOMPARE(status, 0); const QStringList classFiles = QStringList() << "Jet" << "Ship" << "Vehicles"; QStringList classFiles1 = QStringList(classFiles) << "io/qt/qbs/HelloWorld" << "NoPackage"; for (int i = 0; i < classFiles1.count(); ++i) { QString &classFile = classFiles1[i]; classFile = relativeProductBuildDir("class_collection") + "/classes/" + classFile + ".class"; QVERIFY2(regularFileExists(classFile), qPrintable(classFile)); } foreach (const QString &classFile, classFiles) { const QString filePath = relativeProductBuildDir("jar_file") + "/classes/" + classFile + ".class"; QVERIFY2(regularFileExists(filePath), qPrintable(filePath)); } const QString jarFilePath = relativeProductBuildDir("jar_file") + '/' + "jar_file.jar"; QVERIFY2(regularFileExists(jarFilePath), qPrintable(jarFilePath)); // Now check whether we correctly predicted the class file output paths. QCOMPARE(runQbs(QbsRunParameters("clean", QStringList() << "--all-artifacts")), 0); foreach (const QString &classFile, classFiles1) { QVERIFY2(!regularFileExists(classFile), qPrintable(classFile)); } // This tests various things: java.manifestClassPath, JNI, etc. QDir::setCurrent(relativeBuildDir() + "/install-root"); QProcess process; process.setProcessEnvironment(processEnvironmentWithCurrentDirectoryInLibraryPath()); process.start("java", QStringList() << "-jar" << "jar_file.jar"); if (process.waitForStarted()) { QVERIFY2(process.waitForFinished(), qPrintable(process.errorString())); QVERIFY2(process.exitCode() == 0, process.readAllStandardError().constData()); const QByteArray stdOut = process.readAllStandardOutput(); QVERIFY2(stdOut.contains("Driving!"), stdOut.constData()); QVERIFY2(stdOut.contains("Flying!"), stdOut.constData()); QVERIFY2(stdOut.contains("Flying (this is a space ship)!"), stdOut.constData()); QVERIFY2(stdOut.contains("Sailing!"), stdOut.constData()); QVERIFY2(stdOut.contains("Native code performing complex internal combustion process ("), stdOut.constData()); } process.start("unzip", QStringList() << "-p" << "jar_file.jar"); if (process.waitForStarted()) { QVERIFY2(process.waitForFinished(), qPrintable(process.errorString())); const QByteArray stdOut = process.readAllStandardOutput(); QVERIFY2(stdOut.contains("Class-Path: car_jar.jar random_stuff.jar"), stdOut.constData()); QVERIFY2(stdOut.contains("Main-Class: Vehicles"), stdOut.constData()); } } void TestBlackbox::jsExtensionsFile() { QDir::setCurrent(testDataDir + "/jsextensions-file"); QbsRunParameters params(QStringList() << "-f" << "file.qbs"); QCOMPARE(runQbs(params), 0); QVERIFY(!QFileInfo("original.txt").exists()); QFile copy("copy.txt"); QVERIFY(copy.exists()); QVERIFY(copy.open(QIODevice::ReadOnly)); const QList lines = copy.readAll().trimmed().split('\n'); QCOMPARE(lines.count(), 2); QCOMPARE(lines.at(0).trimmed().constData(), "false"); QCOMPARE(lines.at(1).trimmed().constData(), "true"); } void TestBlackbox::jsExtensionsFileInfo() { QDir::setCurrent(testDataDir + "/jsextensions-fileinfo"); QbsRunParameters params(QStringList() << "-f" << "fileinfo.qbs"); QCOMPARE(runQbs(params), 0); QFile output("output.txt"); QVERIFY(output.exists()); QVERIFY(output.open(QIODevice::ReadOnly)); const QList lines = output.readAll().trimmed().split('\n'); QCOMPARE(lines.count(), 19); QCOMPARE(lines.at(0).trimmed().constData(), "blubb"); QCOMPARE(lines.at(1).trimmed().constData(), "blubb.tar"); QCOMPARE(lines.at(2).trimmed().constData(), "blubb.tar.gz"); QCOMPARE(lines.at(3).trimmed().constData(), "/tmp/blubb.tar.gz"); QCOMPARE(lines.at(4).trimmed().constData(), "c:/tmp/blubb.tar.gz"); QCOMPARE(lines.at(5).trimmed().constData(), "true"); QCOMPARE(lines.at(6).trimmed().constData(), "true"); QCOMPARE(lines.at(7).trimmed().constData(), "false"); QCOMPARE(lines.at(8).trimmed().constData(), "false"); QCOMPARE(lines.at(9).trimmed().constData(), "/tmp/blubb.tar.gz"); QCOMPARE(lines.at(10).trimmed().constData(), "/tmp"); QCOMPARE(lines.at(11).trimmed().constData(), "/tmp"); QCOMPARE(lines.at(12).trimmed().constData(), "/"); QCOMPARE(lines.at(13).trimmed().constData(), "d:/"); QCOMPARE(lines.at(14).trimmed().constData(), "blubb.tar.gz"); QCOMPARE(lines.at(15).trimmed().constData(), "tmp/blubb.tar.gz"); QCOMPARE(lines.at(16).trimmed().constData(), "../blubb.tar.gz"); QCOMPARE(lines.at(17).trimmed().constData(), "\\tmp\\blubb.tar.gz"); QCOMPARE(lines.at(18).trimmed().constData(), "c:\\tmp\\blubb.tar.gz"); } void TestBlackbox::jsExtensionsProcess() { QDir::setCurrent(testDataDir + "/jsextensions-process"); QbsRunParameters params(QStringList() << "-f" << "process.qbs" << "project.qbsFilePath:" + qbsExecutableFilePath); QCOMPARE(runQbs(params), 0); QFile output("output.txt"); QVERIFY(output.exists()); QVERIFY(output.open(QIODevice::ReadOnly)); const QList lines = output.readAll().trimmed().split('\n'); QCOMPARE(lines.count(), 7); QCOMPARE(lines.at(0).trimmed().constData(), "0"); QVERIFY(lines.at(1).startsWith("qbs ")); QCOMPARE(lines.at(2).trimmed().constData(), "true"); QCOMPARE(lines.at(3).trimmed().constData(), "true"); QCOMPARE(lines.at(4).trimmed().constData(), "0"); QVERIFY(lines.at(5).startsWith("qbs ")); QCOMPARE(lines.at(6).trimmed().constData(), "false"); } void TestBlackbox::jsExtensionsPropertyList() { if (!HostOsInfo::isOsxHost()) QSKIP("temporarily only applies on OS X"); QDir::setCurrent(testDataDir + "/jsextensions-propertylist"); QbsRunParameters params(QStringList() << "-nf" << "propertylist.qbs"); QCOMPARE(runQbs(params), 0); QFile file1("test.json"); QVERIFY(file1.exists()); QVERIFY(file1.open(QIODevice::ReadOnly)); QFile file2("test.xml"); QVERIFY(file2.exists()); QVERIFY(file2.open(QIODevice::ReadOnly)); QFile file3("test2.json"); QVERIFY(file3.exists()); QVERIFY(file3.open(QIODevice::ReadOnly)); QByteArray file1Contents = file1.readAll(); QCOMPARE(file3.readAll(), file1Contents); //QCOMPARE(file1Contents, file2.readAll()); // keys don't have guaranteed order #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) QJsonParseError err1, err2; QCOMPARE(QJsonDocument::fromJson(file1Contents, &err1), QJsonDocument::fromJson(file2.readAll(), &err2)); QVERIFY(err1.error == QJsonParseError::NoError && err2.error == QJsonParseError::NoError); #endif QFile file4("test.openstep.plist"); QVERIFY(file4.exists()); QFile file5("test3.json"); QVERIFY(file5.exists()); QVERIFY(file5.open(QIODevice::ReadOnly)); QVERIFY(file1Contents != file5.readAll()); } void TestBlackbox::jsExtensionsTemporaryDir() { QDir::setCurrent(testDataDir + "/jsextensions-temporarydir"); QbsRunParameters params; QCOMPARE(runQbs(params), 0); } void TestBlackbox::jsExtensionsTextFile() { QDir::setCurrent(testDataDir + "/jsextensions-textfile"); QbsRunParameters params(QStringList() << "-f" << "textfile.qbs"); QCOMPARE(runQbs(params), 0); QFile file1("file1.txt"); QVERIFY(file1.exists()); QVERIFY(file1.open(QIODevice::ReadOnly)); QCOMPARE(file1.size(), qint64(0)); QFile file2("file2.txt"); QVERIFY(file2.exists()); QVERIFY(file2.open(QIODevice::ReadOnly)); const QList lines = file2.readAll().trimmed().split('\n'); QCOMPARE(lines.count(), 5); QCOMPARE(lines.at(0).trimmed().constData(), "false"); QCOMPARE(lines.at(1).trimmed().constData(), "First line."); QCOMPARE(lines.at(2).trimmed().constData(), "Second line."); QCOMPARE(lines.at(3).trimmed().constData(), "Third line."); QCOMPARE(lines.at(4).trimmed().constData(), "true"); } void TestBlackbox::listPropertiesWithOuter() { QDir::setCurrent(testDataDir + "/list-properties-with-outer"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStderr.contains("listProp: [\"product\",\"higher\",\"group\"]"), m_qbsStderr.constData()); } void TestBlackbox::listPropertyOrder() { QDir::setCurrent(testDataDir + "/list-property-order"); const QbsRunParameters params(QStringList() << "-qq"); QCOMPARE(runQbs(params), 0); const QByteArray firstOutput = m_qbsStderr; for (int i = 0; i < 25; ++i) { rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); if (m_qbsStderr != firstOutput) break; } QCOMPARE(m_qbsStderr.constData(), firstOutput.constData()); } void TestBlackbox::mixedBuildVariants() { QDir::setCurrent(testDataDir + "/mixed-build-variants"); Settings settings((QString())); Profile profile(profileName(), &settings); if (profile.value("qbs.toolchain").toStringList().contains("msvc")) { QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("not allowed"), m_qbsStderr.constData()); } else if (!profile.value("Qt.core.availableBuildVariants").toStringList().contains("release")) { QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY2(m_qbsStderr.contains("not supported"), m_qbsStderr.constData()); } else { QCOMPARE(runQbs(), 0); } } void TestBlackbox::multipleChanges() { QDir::setCurrent(testDataDir + "/multiple-changes"); QCOMPARE(runQbs(), 0); QFile newFile("test.blubb"); QVERIFY(newFile.open(QIODevice::WriteOnly)); newFile.close(); QCOMPARE(runQbs(QStringList() << "-qq" << "project.prop:true"), 0); QVERIFY(m_qbsStderr.contains("prop: true")); } void TestBlackbox::nestedProperties() { QDir::setCurrent(testDataDir + "/nested-properties"); QCOMPARE(runQbs(), 0); QVERIFY2(m_qbsStdout.contains("value in higherlevel"), m_qbsStdout.constData()); } void TestBlackbox::nonBrokenFilesInBrokenProduct() { QDir::setCurrent(testDataDir + "/non-broken-files-in-broken-product"); QbsRunParameters params(QStringList() << "-k"); params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStdout.contains("fine.cpp")); QVERIFY(runQbs(params) != 0); QVERIFY(!m_qbsStdout.contains("fine.cpp")); // The non-broken file must not be recompiled. } void TestBlackbox::nonDefaultProduct() { QDir::setCurrent(testDataDir + "/non-default-product"); const QString defaultAppExe = relativeExecutableFilePath("default app"); const QString nonDefaultAppExe = relativeExecutableFilePath("non-default app"); QCOMPARE(runQbs(), 0); QVERIFY2(QFile::exists(defaultAppExe), qPrintable(defaultAppExe)); QVERIFY2(!QFile::exists(nonDefaultAppExe), qPrintable(nonDefaultAppExe)); QCOMPARE(runQbs(QbsRunParameters(QStringList() << "--all-products")), 0); QVERIFY2(QFile::exists(nonDefaultAppExe), qPrintable(nonDefaultAppExe)); } static void switchProfileContents(qbs::Profile &p, Settings *s, bool on) { const QString scalarKey = "leaf.scalarProp"; const QString listKey = "leaf.listProp"; if (on) { p.setValue(scalarKey, "profile"); p.setValue(listKey, QStringList() << "profile"); } else { p.remove(scalarKey); p.remove(listKey); } s->sync(); } static void switchFileContents(QFile &f, bool on) { f.seek(0); QByteArray contents = f.readAll(); f.resize(0); if (on) contents.replace("// leaf.", "leaf."); else contents.replace("leaf.", "// leaf."); f.write(contents); f.flush(); } void TestBlackbox::propertyPrecedence() { QDir::setCurrent(testDataDir + "/property-precedence"); qbs::Settings s((QString())); qbs::Internal::TemporaryProfile profile("qbs_autotests_propPrecedence", &s); profile.p.setValue("qbs.architecture", "x86"); // Profiles must not be empty... s.sync(); const QStringList args = QStringList() << "-f" << "project.qbs" << ("profile:" + profile.p.name()); QbsRunParameters params(args); params.useProfile = false; // Case 1: [cmdline=0,prod=0,export=0,nonleaf=0,profile=0] QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: leaf\nlist prop: [\"leaf\"]\n", m_qbsStderr.constData()); // Case 2: [cmdline=0,prod=0,export=0,nonleaf=0,profile=1] switchProfileContents(profile.p, &s, true); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: profile\nlist prop: [\"profile\"]\n", m_qbsStderr.constData()); // Case 3: [cmdline=0,prod=0,export=0,nonleaf=1,profile=0] QFile nonleafFile("modules/nonleaf/nonleaf.qbs"); QVERIFY2(nonleafFile.open(QIODevice::ReadWrite), qPrintable(nonleafFile.errorString())); switchProfileContents(profile.p, &s, false); switchFileContents(nonleafFile, true); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: nonleaf\nlist prop: [\"nonleaf\",\"leaf\"]\n", m_qbsStderr.constData()); // Case 4: [cmdline=0,prod=0,export=0,nonleaf=1,profile=1] switchProfileContents(profile.p, &s, true); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: nonleaf\nlist prop: [\"nonleaf\",\"profile\"]\n", m_qbsStderr.constData()); // Case 5: [cmdline=0,prod=0,export=1,nonleaf=0,profile=0] QFile depFile("dep.qbs"); QVERIFY2(depFile.open(QIODevice::ReadWrite), qPrintable(depFile.errorString())); switchProfileContents(profile.p, &s, false); switchFileContents(nonleafFile, false); switchFileContents(depFile, true); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: export\nlist prop: [\"export\",\"leaf\"]\n", m_qbsStderr.constData()); // Case 6: [cmdline=0,prod=0,export=1,nonleaf=0,profile=1] switchProfileContents(profile.p, &s, true); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: export\nlist prop: [\"export\",\"profile\"]\n", m_qbsStderr.constData()); // Case 7: [cmdline=0,prod=0,export=1,nonleaf=1,profile=0] switchProfileContents(profile.p, &s, false); switchFileContents(nonleafFile, true); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: export\nlist prop: [\"export\",\"nonleaf\",\"leaf\"]\n", m_qbsStderr.constData()); // Case 8: [cmdline=0,prod=0,export=1,nonleaf=1,profile=1] switchProfileContents(profile.p, &s, true); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: export\nlist prop: [\"export\",\"nonleaf\",\"profile\"]\n", m_qbsStderr.constData()); // Case 9: [cmdline=0,prod=1,export=0,nonleaf=0,profile=0] QFile productFile("project.qbs"); QVERIFY2(productFile.open(QIODevice::ReadWrite), qPrintable(productFile.errorString())); switchProfileContents(profile.p, &s, false); switchFileContents(nonleafFile, false); switchFileContents(depFile, false); switchFileContents(productFile, true); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: product\nlist prop: [\"product\",\"leaf\"]\n", m_qbsStderr.constData()); // Case 10: [cmdline=0,prod=1,export=0,nonleaf=0,profile=1] switchProfileContents(profile.p, &s, true); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: product\nlist prop: [\"product\",\"profile\"]\n", m_qbsStderr.constData()); // Case 11: [cmdline=0,prod=1,export=0,nonleaf=1,profile=0] switchProfileContents(profile.p, &s, false); switchFileContents(nonleafFile, true); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: product\nlist prop: [\"product\",\"nonleaf\",\"leaf\"]\n", m_qbsStderr.constData()); // Case 12: [cmdline=0,prod=1,export=0,nonleaf=1,profile=1] switchProfileContents(profile.p, &s, true); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: product\nlist prop: [\"product\",\"nonleaf\",\"profile\"]\n", m_qbsStderr.constData()); // Case 13: [cmdline=0,prod=1,export=1,nonleaf=0,profile=0] switchProfileContents(profile.p, &s, false); switchFileContents(nonleafFile, false); switchFileContents(depFile, true); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: product\nlist prop: [\"product\",\"export\",\"leaf\"]\n", m_qbsStderr.constData()); // Case 14: [cmdline=0,prod=1,export=1,nonleaf=0,profile=1] switchProfileContents(profile.p, &s, true); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: product\nlist prop: [\"product\",\"export\",\"profile\"]\n", m_qbsStderr.constData()); // Case 15: [cmdline=0,prod=1,export=1,nonleaf=1,profile=0] switchProfileContents(profile.p, &s, false); switchFileContents(nonleafFile, true); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: product\nlist prop: [\"product\",\"export\",\"nonleaf\",\"leaf\"]\n", m_qbsStderr.constData()); // Case 16: [cmdline=0,prod=1,export=1,nonleaf=1,profile=1] switchProfileContents(profile.p, &s, true); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: product\nlist prop: [\"product\",\"export\",\"nonleaf\",\"profile\"]\n", m_qbsStderr.constData()); // Command line properties wipe everything, including lists. // Case 17: [cmdline=1,prod=0,export=0,nonleaf=0,profile=0] switchProfileContents(profile.p, &s, false); switchFileContents(nonleafFile, false); switchFileContents(depFile, false); switchFileContents(productFile, false); params.arguments << "leaf.scalarProp:cmdline" << "leaf.listProp:cmdline"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: cmdline\nlist prop: [\"cmdline\"]\n", m_qbsStderr.constData()); // Case 18: [cmdline=1,prod=0,export=0,nonleaf=0,profile=1] switchProfileContents(profile.p, &s, true); params.arguments << "leaf.scalarProp:cmdline" << "leaf.listProp:cmdline"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: cmdline\nlist prop: [\"cmdline\"]\n", m_qbsStderr.constData()); // Case 19: [cmdline=1,prod=0,export=0,nonleaf=1,profile=0] switchProfileContents(profile.p, &s, false); switchFileContents(nonleafFile, true); params.arguments << "leaf.scalarProp:cmdline" << "leaf.listProp:cmdline"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: cmdline\nlist prop: [\"cmdline\"]\n", m_qbsStderr.constData()); // Case 20: [cmdline=1,prod=0,export=0,nonleaf=1,profile=1] switchProfileContents(profile.p, &s, true); params.arguments << "leaf.scalarProp:cmdline" << "leaf.listProp:cmdline"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: cmdline\nlist prop: [\"cmdline\"]\n", m_qbsStderr.constData()); // Case 21: [cmdline=1,prod=0,export=1,nonleaf=0,profile=0] switchProfileContents(profile.p, &s, false); switchFileContents(nonleafFile, false); switchFileContents(depFile, true); params.arguments << "leaf.scalarProp:cmdline" << "leaf.listProp:cmdline"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: cmdline\nlist prop: [\"cmdline\"]\n", m_qbsStderr.constData()); // Case 22: [cmdline=1,prod=0,export=1,nonleaf=0,profile=1] switchProfileContents(profile.p, &s, true); params.arguments << "leaf.scalarProp:cmdline" << "leaf.listProp:cmdline"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: cmdline\nlist prop: [\"cmdline\"]\n", m_qbsStderr.constData()); // Case 23: [cmdline=1,prod=0,export=1,nonleaf=1,profile=0] switchProfileContents(profile.p, &s, false); switchFileContents(nonleafFile, true); params.arguments << "leaf.scalarProp:cmdline" << "leaf.listProp:cmdline"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: cmdline\nlist prop: [\"cmdline\"]\n", m_qbsStderr.constData()); // Case 24: [cmdline=1,prod=0,export=1,nonleaf=1,profile=1] switchProfileContents(profile.p, &s, true); params.arguments << "leaf.scalarProp:cmdline" << "leaf.listProp:cmdline"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: cmdline\nlist prop: [\"cmdline\"]\n", m_qbsStderr.constData()); // Case 25: [cmdline=1,prod=1,export=0,nonleaf=0,profile=0] switchProfileContents(profile.p, &s, false); switchFileContents(nonleafFile, false); switchFileContents(depFile, false); switchFileContents(productFile, true); params.arguments << "leaf.scalarProp:cmdline" << "leaf.listProp:cmdline"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: cmdline\nlist prop: [\"cmdline\"]\n", m_qbsStderr.constData()); // Case 26: [cmdline=1,prod=1,export=0,nonleaf=0,profile=1] switchProfileContents(profile.p, &s, true); params.arguments << "leaf.scalarProp:cmdline" << "leaf.listProp:cmdline"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: cmdline\nlist prop: [\"cmdline\"]\n", m_qbsStderr.constData()); // Case 27: [cmdline=1,prod=1,export=0,nonleaf=1,profile=0] switchProfileContents(profile.p, &s, false); switchFileContents(nonleafFile, true); params.arguments << "leaf.scalarProp:cmdline" << "leaf.listProp:cmdline"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: cmdline\nlist prop: [\"cmdline\"]\n", m_qbsStderr.constData()); // Case 28: [cmdline=1,prod=1,export=0,nonleaf=1,profile=1] switchProfileContents(profile.p, &s, true); params.arguments << "leaf.scalarProp:cmdline" << "leaf.listProp:cmdline"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: cmdline\nlist prop: [\"cmdline\"]\n", m_qbsStderr.constData()); // Case 29: [cmdline=1,prod=1,export=1,nonleaf=0,profile=0] switchProfileContents(profile.p, &s, false); switchFileContents(nonleafFile, false); switchFileContents(depFile, true); params.arguments << "leaf.scalarProp:cmdline" << "leaf.listProp:cmdline"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: cmdline\nlist prop: [\"cmdline\"]\n", m_qbsStderr.constData()); // Case 30: [cmdline=1,prod=1,export=1,nonleaf=0,profile=1] switchProfileContents(profile.p, &s, true); params.arguments << "leaf.scalarProp:cmdline" << "leaf.listProp:cmdline"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: cmdline\nlist prop: [\"cmdline\"]\n", m_qbsStderr.constData()); // Case 31: [cmdline=1,prod=1,export=1,nonleaf=1,profile=0] switchProfileContents(profile.p, &s, false); switchFileContents(nonleafFile, true); params.arguments << "leaf.scalarProp:cmdline" << "leaf.listProp:cmdline"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: cmdline\nlist prop: [\"cmdline\"]\n", m_qbsStderr.constData()); // Case 32: [cmdline=1,prod=1,export=1,nonleaf=1,profile=1] switchProfileContents(profile.p, &s, true); params.arguments << "leaf.scalarProp:cmdline" << "leaf.listProp:cmdline"; QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStderr == "scalar prop: cmdline\nlist prop: [\"cmdline\"]\n", m_qbsStderr.constData()); } void TestBlackbox::qmlDebugging() { QDir::setCurrent(testDataDir + "/qml-debugging"); QCOMPARE(runQbs(), 0); Settings settings((QString())); Profile profile(profileName(), &settings); if (!profile.value("qbs.toolchain").toStringList().contains("gcc")) return; QProcess nm; nm.start("nm", QStringList(relativeExecutableFilePath("debuggable-app"))); if (nm.waitForStarted()) { // Let's ignore hosts without nm. QVERIFY2(nm.waitForFinished(), qPrintable(nm.errorString())); QVERIFY2(nm.exitCode() == 0, nm.readAllStandardError().constData()); const QByteArray output = nm.readAllStandardOutput(); QVERIFY2(output.toLower().contains("debugginghelper"), output.constData()); } } void TestBlackbox::productDependenciesByType() { QDir::setCurrent(testDataDir + "/product-dependencies-by-type"); QCOMPARE(runQbs(), 0); QFile appListFile(relativeProductBuildDir("app list") + "/app-list.txt"); QVERIFY2(appListFile.open(QIODevice::ReadOnly), qPrintable(appListFile.fileName())); const QList appList = appListFile.readAll().trimmed().split('\n'); QCOMPARE(appList.count(), 3); QStringList apps = QStringList() << QDir::currentPath() + '/' + relativeExecutableFilePath("app1") << QDir::currentPath() + '/' + relativeExecutableFilePath("app2") << QDir::currentPath() + '/' + relativeExecutableFilePath("app3"); foreach (const QByteArray &line, appList) { const QString cleanLine = QString::fromLocal8Bit(line.trimmed()); QVERIFY2(apps.removeOne(cleanLine), qPrintable(cleanLine)); } QVERIFY(apps.isEmpty()); } void TestBlackbox::properQuoting() { QDir::setCurrent(testDataDir + "/proper quoting"); QCOMPARE(runQbs(), 0); QbsRunParameters params(QLatin1String("run"), QStringList() << "-q" << "-p" << "Hello World"); params.expectFailure = true; // Because the exit code is non-zero. QCOMPARE(runQbs(params), 156); const char * const expectedOutput = "whitespaceless\ncontains space\ncontains\ttab\n" "backslash\\\nHello World! The magic number is 156."; QCOMPARE(unifiedLineEndings(m_qbsStdout).constData(), expectedOutput); } void TestBlackbox::radAfterIncompleteBuild_data() { QTest::addColumn("projectFileName"); QTest::newRow("Project with Rule") << "project_with_rule.qbs"; QTest::newRow("Project with Transformer") << "project_with_transformer.qbs"; } void TestBlackbox::radAfterIncompleteBuild() { QDir::setCurrent(testDataDir + "/rad-after-incomplete-build"); rmDirR(relativeBuildDir()); QFETCH(QString, projectFileName); // Step 1: Have a directory where a file used to be. QbsRunParameters params(QStringList() << "-f" << projectFileName); QCOMPARE(runQbs(params), 0); WAIT_FOR_NEW_TIMESTAMP(); QFile projectFile(projectFileName); QVERIFY(projectFile.open(QIODevice::ReadWrite)); QByteArray content = projectFile.readAll(); content.replace("oldfile", "oldfile/newfile"); projectFile.resize(0); projectFile.write(content); projectFile.flush(); params.expectFailure = true; QVERIFY(runQbs(params) != 0); WAIT_FOR_NEW_TIMESTAMP(); content.replace("oldfile/newfile", "newfile"); projectFile.resize(0); projectFile.write(content); projectFile.flush(); params.expectFailure = false; QCOMPARE(runQbs(params), 0); WAIT_FOR_NEW_TIMESTAMP(); content.replace("newfile", "oldfile/newfile"); projectFile.resize(0); projectFile.write(content); projectFile.flush(); QCOMPARE(runQbs(params), 0); // Step 2: Have a file where a directory used to be. WAIT_FOR_NEW_TIMESTAMP(); content.replace("oldfile/newfile", "oldfile"); projectFile.resize(0); projectFile.write(content); projectFile.flush(); params.expectFailure = true; QVERIFY(runQbs(params) != 0); WAIT_FOR_NEW_TIMESTAMP(); content.replace("oldfile", "newfile"); projectFile.resize(0); projectFile.write(content); projectFile.flush(); params.expectFailure = false; QCOMPARE(runQbs(params), 0); WAIT_FOR_NEW_TIMESTAMP(); content.replace("newfile", "oldfile"); projectFile.resize(0); projectFile.write(content); projectFile.flush(); QCOMPARE(runQbs(params), 0); } void TestBlackbox::subProfileChangeTracking() { QDir::setCurrent(testDataDir + "/subprofile-change-tracking"); qbs::Settings settings((QString())); qbs::Internal::TemporaryProfile subProfile("qbs-autotests-subprofile", &settings); subProfile.p.setValue("baseProfile", profileName()); subProfile.p.setValue("cpp.includePaths", QStringList("/tmp/include1")); settings.sync(); QCOMPARE(runQbs(), 0); subProfile.p.setValue("cpp.includePaths", QStringList("/tmp/include2")); settings.sync(); QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("main1.cpp")); QVERIFY(m_qbsStdout.contains("main2.cpp")); } void TestBlackbox::installedApp() { QDir::setCurrent(testDataDir + "/installed_artifact"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(defaultInstallRoot + HostOsInfo::appendExecutableSuffix(QLatin1String("/usr/bin/installedApp")))); QCOMPARE(runQbs(QbsRunParameters(QStringList("qbs.installRoot:" + testDataDir + "/installed-app"))), 0); QVERIFY(regularFileExists(testDataDir + HostOsInfo::appendExecutableSuffix("/installed-app/usr/bin/installedApp"))); QFile addedFile(defaultInstallRoot + QLatin1String("/blubb.txt")); QVERIFY(addedFile.open(QIODevice::WriteOnly)); addedFile.close(); QVERIFY(addedFile.exists()); QCOMPARE(runQbs(QbsRunParameters(QStringList("--clean-install-root"))), 0); QVERIFY(regularFileExists(defaultInstallRoot + HostOsInfo::appendExecutableSuffix(QLatin1String("/usr/bin/installedApp")))); QVERIFY(regularFileExists(defaultInstallRoot + QLatin1String("/usr/src/main.cpp"))); QVERIFY(!addedFile.exists()); // Check whether changing install parameters on the product causes re-installation. QFile projectFile("installed_artifact.qbs"); QVERIFY(projectFile.open(QIODevice::ReadWrite)); QByteArray content = projectFile.readAll(); content.replace("qbs.installPrefix: \"/usr\"", "qbs.installPrefix: '/usr/local'"); WAIT_FOR_NEW_TIMESTAMP(); projectFile.resize(0); projectFile.write(content); QVERIFY(projectFile.flush()); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(defaultInstallRoot + HostOsInfo::appendExecutableSuffix(QLatin1String("/usr/local/bin/installedApp")))); QVERIFY(regularFileExists(defaultInstallRoot + QLatin1String("/usr/local/src/main.cpp"))); // Check whether changing install parameters on the artifact causes re-installation. content.replace("qbs.installDir: \"bin\"", "qbs.installDir: 'custom'"); WAIT_FOR_NEW_TIMESTAMP(); projectFile.resize(0); projectFile.write(content); QVERIFY(projectFile.flush()); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(defaultInstallRoot + HostOsInfo::appendExecutableSuffix(QLatin1String("/usr/local/custom/installedApp")))); // Check whether changing install parameters on a source file causes re-installation. content.replace("qbs.installDir: \"src\"", "qbs.installDir: 'source'"); WAIT_FOR_NEW_TIMESTAMP(); projectFile.resize(0); projectFile.write(content); projectFile.close(); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(defaultInstallRoot + QLatin1String("/usr/local/source/main.cpp"))); // Check whether changing install parameters on the command line causes re-installation. QbsRunParameters(QStringList("qbs.installRoot:" + relativeBuildDir() + "/blubb")); QCOMPARE(runQbs(QbsRunParameters(QStringList("qbs.installRoot:" + relativeBuildDir() + "/blubb"))), 0); QVERIFY(regularFileExists(relativeBuildDir() + "/blubb/usr/local/source/main.cpp")); // Check --no-install rmDirR(relativeBuildDir()); QCOMPARE(runQbs(QbsRunParameters(QStringList("--no-install"))), 0); QCOMPARE(QDir(defaultInstallRoot).entryList(QDir::NoDotAndDotDot).count(), 0); // Check --no-build rmDirR(relativeBuildDir()); QbsRunParameters params("install", QStringList("--no-build")); params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStderr.contains("No build graph")); } void TestBlackbox::installedSourceFiles() { QDir::setCurrent(testDataDir + "/installed-source-files"); QCOMPARE(runQbs(), 0); QVERIFY(regularFileExists(defaultInstallRoot + QLatin1String("/readme.txt"))); QVERIFY(regularFileExists(defaultInstallRoot + QLatin1String("/main.cpp"))); } void TestBlackbox::toolLookup() { QbsRunParameters params(QLatin1String("setup-toolchains"), QStringList("--help")); params.useProfile = false; QCOMPARE(runQbs(params), 0); } void TestBlackbox::checkProjectFilePath() { QDir::setCurrent(testDataDir + "/project_filepath_check"); QbsRunParameters params(QStringList("-f") << "project1.qbs"); QCOMPARE(runQbs(params), 0); QCOMPARE(runQbs(params), 0); params.arguments = QStringList("-f") << "project2.qbs"; params.expectFailure = true; QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStderr.contains("project file")); params.arguments = QStringList("-f") << "project2.qbs" << "--force"; params.expectFailure = false; QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStderr.contains("project file")); } class TemporaryDefaultProfileRemover { public: TemporaryDefaultProfileRemover(Settings *settings) : m_settings(settings), m_defaultProfile(settings->defaultProfile()) { m_settings->remove(QLatin1String("defaultProfile")); } ~TemporaryDefaultProfileRemover() { if (!m_defaultProfile.isEmpty()) m_settings->setValue(QLatin1String("defaultProfile"), m_defaultProfile); } private: Settings *m_settings; const QString m_defaultProfile; }; void TestBlackbox::missingProfile() { Settings settings((QString())); TemporaryDefaultProfileRemover dpr(&settings); settings.sync(); QVERIFY(settings.defaultProfile().isEmpty()); QDir::setCurrent(testDataDir + "/project_filepath_check"); QbsRunParameters params; params.arguments = QStringList("-f") << "project1.qbs"; params.expectFailure = true; params.useProfile = false; QVERIFY(runQbs(params) != 0); QVERIFY(m_qbsStderr.contains("No profile")); } void TestBlackbox::testAssembly() { Settings settings((QString())); Profile profile(profileName(), &settings); bool haveGcc = profile.value("qbs.toolchain").toStringList().contains("gcc"); bool haveMSVC = profile.value("qbs.toolchain").toStringList().contains("msvc"); QDir::setCurrent(testDataDir + "/assembly"); QVERIFY(runQbs() == 0); QCOMPARE((bool)m_qbsStdout.contains("compiling testa.s"), haveGcc); QCOMPARE((bool)m_qbsStdout.contains("compiling testb.S"), haveGcc); QCOMPARE((bool)m_qbsStdout.contains("compiling testc.sx"), haveGcc); QCOMPARE((bool)m_qbsStdout.contains("creating libtesta.a"), haveGcc); QCOMPARE((bool)m_qbsStdout.contains("creating libtestb.a"), haveGcc); QCOMPARE((bool)m_qbsStdout.contains("creating libtestc.a"), haveGcc); QCOMPARE(m_qbsStdout.contains("creating testd.lib"), haveMSVC); } void TestBlackbox::testNsis() { QStringList regKeys; regKeys << QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS") << QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS"); QStringList paths = QProcessEnvironment::systemEnvironment().value("PATH") .split(HostOsInfo::pathListSeparator(), QString::SkipEmptyParts); foreach (const QString &key, regKeys) { QSettings settings(key, QSettings::NativeFormat); QString str = settings.value(QLatin1String(".")).toString(); if (!str.isEmpty()) paths.prepend(str); } bool haveMakeNsis = false; foreach (const QString &path, paths) { if (regularFileExists(QDir::fromNativeSeparators(path) + HostOsInfo::appendExecutableSuffix(QLatin1String("/makensis")))) { haveMakeNsis = true; break; } } if (!haveMakeNsis) { QSKIP("makensis is not installed"); return; } Settings settings((QString())); Profile profile(profileName(), &settings); bool targetIsWindows = profile.value("qbs.targetOS").toStringList().contains("windows"); QDir::setCurrent(testDataDir + "/nsis"); QVERIFY(runQbs() == 0); QCOMPARE((bool)m_qbsStdout.contains("compiling hello.nsi"), targetIsWindows); QCOMPARE((bool)m_qbsStdout.contains("SetCompressor ignored due to previous call with the /FINAL switch"), targetIsWindows); QVERIFY(!QFile::exists(defaultInstallRoot + "/you-should-not-see-a-file-with-this-name.exe")); } void TestBlackbox::testEmbedInfoPlist() { if (!HostOsInfo::isOsxHost()) QSKIP("only applies on OS X"); QDir::setCurrent(testDataDir + QLatin1String("/embedInfoPlist")); QbsRunParameters params; params.command = QLatin1String("run"); QCOMPARE(runQbs(params), 0); params.arguments = QStringList(QLatin1String("bundle.embedInfoPlist:false")); params.expectFailure = true; QVERIFY(runQbs(params) != 0); } void TestBlackbox::testFrameworkStructure() { if (!HostOsInfo::isOsxHost()) QSKIP("only applies on OS X"); QDir::setCurrent(testDataDir + QLatin1String("/frameworkStructure")); QbsRunParameters params; QCOMPARE(runQbs(params), 0); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/Widget")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/Headers/Widget.h")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/PrivateHeaders/WidgetPrivate.h")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/Resources/BaseResource")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/A/Resources/en.lproj/EnglishResource")); QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/Versions/Current")); QVERIFY(regularFileExists(relativeProductBuildDir("Widget") + "/Widget.framework/Widget")); QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/Headers")); QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/PrivateHeaders")); QVERIFY(directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/Resources")); params.arguments = QStringList() << "project.includeHeaders:false"; QCOMPARE(runQbs(params), 0); QVERIFY(!directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/Headers")); QVERIFY(!directoryExists(relativeProductBuildDir("Widget") + "/Widget.framework/PrivateHeaders")); } static bool haveWiX(const Profile &profile) { if (profile.value("wix.toolchainInstallPath").isValid() && profile.value("wix.toolchainInstallRoot").isValid()) { return true; } QStringList regKeys; regKeys << QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows Installer XML\\") << QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Installer XML\\"); const QStringList versions = QStringList() << "4.0" << "3.10" << "3.9" << "3.8" << "3.7" << "3.6" << "3.5" << "3.0" << "2.0"; QStringList paths = QProcessEnvironment::systemEnvironment().value("PATH") .split(HostOsInfo::pathListSeparator(), QString::SkipEmptyParts); foreach (const QString &version, versions) { foreach (const QString &key, regKeys) { QSettings settings(key + version, QSettings::NativeFormat); QString str = settings.value(QLatin1String("InstallRoot")).toString(); if (!str.isEmpty()) paths.prepend(str); } } foreach (const QString &path, paths) { if (regularFileExists(QDir::fromNativeSeparators(path) + HostOsInfo::appendExecutableSuffix(QLatin1String("/candle"))) && regularFileExists(QDir::fromNativeSeparators(path) + HostOsInfo::appendExecutableSuffix(QLatin1String("/light")))) { return true; } } return false; } void TestBlackbox::testWiX() { Settings settings((QString())); Profile profile(profileName(), &settings); if (!haveWiX(profile)) { QSKIP("WiX is not installed"); return; } const QByteArray arch = profile.value("qbs.architecture").toString().toLatin1(); QDir::setCurrent(testDataDir + "/wix"); QbsRunParameters params; if (!HostOsInfo::isWindowsHost()) params.arguments << "qbs.targetOS:windows"; QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling QbsSetup.wxs")); QVERIFY(m_qbsStdout.contains("linking qbs-" + arch + ".msi")); QVERIFY(regularFileExists(relativeProductBuildDir("QbsSetup") + "/qbs-" + arch + ".msi")); if (HostOsInfo::isWindowsHost()) { QVERIFY(m_qbsStdout.contains("compiling QbsBootstrapper.wxs")); QVERIFY(m_qbsStdout.contains("linking qbs-setup-" + arch + ".exe")); QVERIFY(regularFileExists(relativeProductBuildDir("QbsBootstrapper") + "/qbs-setup-" + arch + ".exe")); } } static bool haveNodeJs() { // The Node.js binary is called nodejs on Debian/Ubuntu-family operating systems due to a // conflict with another package containing a binary named node return !findExecutable(QStringList() << QLatin1String("nodejs") << QLatin1String("node")).isEmpty(); } void TestBlackbox::testNodeJs() { if (!haveNodeJs()) { QSKIP("Node.js is not installed"); return; } QDir::setCurrent(testDataDir + QLatin1String("/nodejs")); QbsRunParameters params; params.command = QLatin1String("run"); QCOMPARE(runQbs(params), 0); QVERIFY((bool)m_qbsStdout.contains("hello world")); QVERIFY(regularFileExists(relativeProductBuildDir("hello") + "/hello.js")); } void TestBlackbox::testTypeScript() { if (!haveNodeJs()) { QSKIP("node.js is not installed"); return; } QDir::setCurrent(testDataDir + QLatin1String("/typescript")); QbsRunParameters params; params.command = QLatin1String("run"); params.arguments = QStringList() << "-p" << "animals"; QCOMPARE(runQbs(params), 0); QVERIFY(regularFileExists(relativeProductBuildDir("animals") + "/animals.js")); QVERIFY(regularFileExists(relativeProductBuildDir("animals") + "/extra.js")); QVERIFY(regularFileExists(relativeProductBuildDir("animals") + "/main.js")); } void TestBlackbox::testIconset() { if (!HostOsInfo::isOsxHost()) QSKIP("only applies on OS X"); QDir::setCurrent(testDataDir + QLatin1String("/ib/iconset")); QbsRunParameters params; params.arguments = QStringList() << "-f" << "iconset.qbs"; QCOMPARE(runQbs(params), 0); QVERIFY(regularFileExists(relativeProductBuildDir("iconset") + "/white.icns")); } void TestBlackbox::testIconsetApp() { if (!HostOsInfo::isOsxHost()) QSKIP("only applies on OS X"); QDir::setCurrent(testDataDir + QLatin1String("/ib/iconsetapp")); QbsRunParameters params; params.arguments = QStringList() << "-f" << "iconsetapp.qbs"; QCOMPARE(runQbs(params), 0); QVERIFY(regularFileExists(relativeProductBuildDir("iconsetapp") + "/iconsetapp.app/Contents/Resources/white.icns")); } void TestBlackbox::testAssetCatalog() { if (!HostOsInfo::isOsxHost()) QSKIP("only applies on OS X"); if (HostOsInfo::hostOsVersion() < qbs::Internal::Version(10, 9)) QSKIP("This test needs at least OS X 10.9."); QDir::setCurrent(testDataDir + QLatin1String("/ib/assetcatalog")); QbsRunParameters params; // Make sure a dry run does not write anything params.arguments = QStringList() << "-f" << "assetcatalogempty.qbs" << "--dry-run"; QCOMPARE(runQbs(params), 0); QVERIFY(!directoryExists(relativeBuildDir())); params.arguments = QStringList() << "-f" << "assetcatalogempty.qbs"; QCOMPARE(runQbs(params), 0); // empty asset catalogs must still produce output QVERIFY((bool)m_qbsStdout.contains("actool")); // should not produce a CAR since minimumOsxVersion will be < 10.9 QVERIFY(!regularFileExists(relativeProductBuildDir("assetcatalogempty") + "/assetcatalogempty.app/Contents/Resources/Assets.car")); rmDirR(relativeBuildDir()); params.arguments.append("cpp.minimumOsxVersion:10.9"); // force CAR generation QCOMPARE(runQbs(params), 0); // empty asset catalogs must still produce output QVERIFY((bool)m_qbsStdout.contains("actool")); QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") + "/assetcatalogempty.app/Contents/Resources/Assets.car")); // this asset catalog happens to have an embedded icon set, // but this should NOT be built since it is not in the files list QVERIFY(!(bool)m_qbsStdout.contains("iconutil")); // now we'll add the iconset rmDirR(relativeBuildDir()); params.arguments.append("project.includeIconset:true"); QCOMPARE(runQbs(params), 0); QVERIFY(!(bool)m_qbsStdout.contains("actool")); QVERIFY((bool)m_qbsStdout.contains("iconutil")); // make sure the nibs/storyboards are in there QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") + "/assetcatalogempty.app/Contents/Resources/MainMenu.nib")); if (HostOsInfo::hostOsVersion() >= qbs::Internal::Version(10, 10)) QVERIFY(directoryExists(relativeProductBuildDir("assetcatalogempty") + "/assetcatalogempty.app/Contents/Resources/Storyboard.storyboardc")); QDir::setCurrent(testDataDir + QLatin1String("/ib/multiple-asset-catalogs")); params.arguments = QStringList(); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("compiling assetcatalog1.xcassets"), m_qbsStdout); QVERIFY2(m_qbsStdout.contains("compiling assetcatalog2.xcassets"), m_qbsStdout); QDir::setCurrent(testDataDir + QLatin1String("/ib/empty-asset-catalogs")); params.arguments = QStringList(); QCOMPARE(runQbs(params), 0); QVERIFY2(!m_qbsStdout.contains("compiling assetcatalog1.xcassets"), m_qbsStdout); QVERIFY2(!m_qbsStdout.contains("compiling assetcatalog2.xcassets"), m_qbsStdout); } void TestBlackbox::testObjcArc() { if (!HostOsInfo::isOsxHost()) QSKIP("only applies on platforms supporting Objective-C"); QDir::setCurrent(testDataDir + QLatin1String("/objc-arc")); QCOMPARE(runQbs(), 0); } void TestBlackbox::wildCardsAndRules() { QDir::setCurrent(testDataDir + "/wildcards-and-rules"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("Creating output artifact")); QFile output(relativeProductBuildDir("wildcards-and-rules") + "/test.mytype"); QVERIFY2(output.open(QIODevice::ReadOnly), qPrintable(output.errorString())); QCOMPARE(output.readAll().count('\n'), 1); output.close(); // Add input. touch("input2.inp"); QbsRunParameters params; params.expectFailure = true; QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("Creating output artifact")); QVERIFY2(output.open(QIODevice::ReadOnly), qPrintable(output.errorString())); QCOMPARE(output.readAll().count('\n'), 2); output.close(); // Add "explicitlyDependsOn". touch("dep.dep"); QCOMPARE(runQbs(), 0); QVERIFY(m_qbsStdout.contains("Creating output artifact")); // Add nothing. QCOMPARE(runQbs(), 0); QVERIFY(!m_qbsStdout.contains("Creating output artifact")); } void TestBlackbox::testLoadableModule() { QDir::setCurrent(testDataDir + QLatin1String("/loadablemodule")); QCOMPARE(runQbs(), 0); } void TestBlackbox::testBadInterpreter() { if (!HostOsInfo::isAnyUnixHost()) QSKIP("only applies on Unix"); QDir::setCurrent(testDataDir + QLatin1String("/badInterpreter")); QCOMPARE(runQbs(), 0); QbsRunParameters params("run"); params.expectFailure = true; params.arguments = QStringList() << "-p" << "script-interp-missing"; QCOMPARE(runQbs(params), 1); QVERIFY(m_qbsStderr.contains("bad interpreter: No such file or directory")); params.arguments = QStringList() << "-p" << "script-interp-noexec"; QCOMPARE(runQbs(params), 1); QVERIFY(m_qbsStderr.contains("bad interpreter: Permission denied") || m_qbsStderr.contains("bad interpreter: No such file or directory")); params.arguments = QStringList() << "-p" << "script-noexec"; QCOMPARE(runQbs(params), 1); QCOMPARE(runQbs(QbsRunParameters("run", QStringList() << "-p" << "script-ok")), 0); } void TestBlackbox::qbsVersion() { const qbs::Internal::Version v = qbs::Internal::Version::qbsVersion(); QDir::setCurrent(testDataDir + QLatin1String("/qbsVersion")); QbsRunParameters params; params.arguments = QStringList() << "project.qbsVersion:" + v.toString() << "project.qbsVersionMajor:" + QString::number(v.majorVersion()) << "project.qbsVersionMinor:" + QString::number(v.minorVersion()) << "project.qbsVersionPatch:" + QString::number(v.patchLevel()); QCOMPARE(runQbs(params), 0); params.arguments.append("project.qbsVersionPatch:" + QString::number(v.patchLevel() + 1)); params.expectFailure = true; QVERIFY(runQbs(params) != 0); } void TestBlackbox::transitiveOptionalDependencies() { QDir::setCurrent(testDataDir + "/transitive-optional-dependencies"); QbsRunParameters params; QCOMPARE(runQbs(params), 0); } void TestBlackbox::groupsInModules() { QDir::setCurrent(testDataDir + "/groups-in-modules"); QbsRunParameters params; QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compile rock.coal => rock.diamond")); QVERIFY(m_qbsStdout.contains("compile chunk.coal => chunk.diamond")); QVERIFY(m_qbsStdout.contains("compiling helper2.c")); QVERIFY(!m_qbsStdout.contains("compiling helper3.c")); QVERIFY(m_qbsStdout.contains("compiling helper4.c")); QVERIFY(m_qbsStdout.contains("compiling helper5.c")); QVERIFY(!m_qbsStdout.contains("compiling helper6.c")); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compile rock.coal => rock.diamond")); QVERIFY(!m_qbsStdout.contains("compile chunk.coal => chunk.diamond")); WAIT_FOR_NEW_TIMESTAMP(); touch("modules/helper/diamondc.c"); QCOMPARE(runQbs(params), 0); QVERIFY(m_qbsStdout.contains("compiling diamondc.c")); QVERIFY(m_qbsStdout.contains("compile rock.coal => rock.diamond")); QVERIFY(m_qbsStdout.contains("compile chunk.coal => chunk.diamond")); QVERIFY(regularFileExists(relativeProductBuildDir("groups-in-modules") + "/rock.diamond")); QFile output(relativeProductBuildDir("groups-in-modules") + "/rock.diamond"); QVERIFY(output.open(QIODevice::ReadOnly)); QCOMPARE(output.readAll().trimmed(), QByteArray("diamond")); } void TestBlackbox::probesInNestedModules() { QDir::setCurrent(testDataDir + "/probes-in-nested-modules"); QbsRunParameters params; QCOMPARE(runQbs(params), 0); QEXPECT_FAIL(0, "ignore for now", Continue); QCOMPARE(m_qbsStderr.count("running probe a"), 1); QCOMPARE(m_qbsStderr.count("running probe b"), 1); QCOMPARE(m_qbsStderr.count("running probe c"), 1); QCOMPARE(m_qbsStderr.count("running second probe a"), 1); QVERIFY(m_qbsStderr.contains("product a, outer.somethingElse = goodbye")); QVERIFY(m_qbsStderr.contains("product b, inner.something = hahaha")); QVERIFY(m_qbsStderr.contains("product c, inner.something = hello")); QVERIFY(m_qbsStderr.contains("product a, inner.something = hahaha")); QEXPECT_FAIL(0, "QBS-833", Continue); QVERIFY(m_qbsStderr.contains("product a, outer.something = hello")); } QTEST_MAIN(TestBlackbox) qbs-src-1.4.5/tests/auto/blackbox/tst_blackbox.h000066400000000000000000000131651266132464200216360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef TST_BLACKBOX_H #define TST_BLACKBOX_H #include #include #include #include #include #include class QbsRunParameters { public: QbsRunParameters() { init(); } QbsRunParameters(const QString &cmd, const QStringList &args = QStringList()) : command(cmd), arguments(args) { init(); } QbsRunParameters(const QStringList &args) : arguments(args) { init(); } void init() { expectFailure = false; useProfile = true; environment = QProcessEnvironment::systemEnvironment(); } QString command; QStringList arguments; QProcessEnvironment environment; bool expectFailure; bool useProfile; }; class TestBlackbox : public QObject { Q_OBJECT const QString testDataDir; const QString testSourceDir; const QString qbsExecutableFilePath; const QString defaultInstallRoot; public: TestBlackbox(); protected: int runQbs(const QbsRunParameters ¶ms = QbsRunParameters()); void rmDirR(const QString &dir); static QByteArray unifiedLineEndings(const QByteArray &ba); static void sanitizeOutput(QByteArray *ba); public slots: void initTestCase(); private slots: void android(); void android_data(); void buildDirectories(); void changedFiles_data(); void changedFiles(); void changeInDisabledProduct(); void checkProjectFilePath(); void clean(); void concurrentExecutor(); void dependenciesProperty(); void dynamicMultiplexRule(); void dynamicRuleOutputs(); void erroneousFiles_data(); void erroneousFiles(); void exportRule(); void fileDependencies(); void groupsInModules(); void inputsFromDependencies(); void installable(); void installedApp(); void installedSourceFiles(); void installedTransformerOutput(); void installPackage(); void installTree(); void java(); void jsExtensionsFile(); void jsExtensionsFileInfo(); void jsExtensionsProcess(); void jsExtensionsPropertyList(); void jsExtensionsTemporaryDir(); void jsExtensionsTextFile(); void listPropertiesWithOuter(); void listPropertyOrder(); void missingProfile(); void mixedBuildVariants(); void multipleChanges(); void nestedProperties(); void nonBrokenFilesInBrokenProduct(); void nonDefaultProduct(); void overrideProjectProperties(); void probesInNestedModules(); void productDependenciesByType(); void productProperties(); void propertyChanges(); void propertyPrecedence(); void properQuoting(); void qbsVersion(); void qmlDebugging(); void qobjectInObjectiveCpp(); void radAfterIncompleteBuild_data(); void radAfterIncompleteBuild(); void recursiveRenaming(); void recursiveWildcards(); void ruleConditions(); void ruleCycle(); void subProfileChangeTracking(); void symlinkRemoval(); void renameDependency(); void separateDebugInfo(); void sevenZip(); void tar(); void testAssembly(); void testAssetCatalog(); void testBadInterpreter(); void testEmbedInfoPlist(); void testFrameworkStructure(); void testIconset(); void testIconsetApp(); void testLoadableModule(); void testNodeJs(); void testNsis(); void testObjcArc(); void testTypeScript(); void testWiX(); void toolLookup(); void track_qobject_change(); void track_qrc(); void trackAddFile(); void trackAddFileTag(); void trackAddMocInclude(); void trackAddProduct(); void trackExternalProductChanges(); void trackGroupConditionChange(); void trackRemoveFile(); void trackRemoveFileTag(); void trackRemoveProduct(); void transitiveOptionalDependencies(); void usingsAsSoleInputsNonMultiplexed(); void wildCardsAndRules(); void wildcardRenaming(); void zip(); void zip_data(); void zipInvalid(); private: QString findArchiver(const QString &fileName, int *status = nullptr); private: QByteArray m_qbsStderr; QByteArray m_qbsStdout; }; #endif // TST_BLACKBOX_H qbs-src-1.4.5/tests/auto/buildgraph/000077500000000000000000000000001266132464200173345ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/buildgraph/buildgraph.pro000066400000000000000000000002011266132464200221700ustar00rootroot00000000000000TARGET = tst_buildgraph SOURCES = tst_buildgraph.cpp include(../auto.pri) include(../../../src/app/shared/logging/logging.pri) qbs-src-1.4.5/tests/auto/buildgraph/buildgraph.qbs000066400000000000000000000001271266132464200221640ustar00rootroot00000000000000import qbs QbsAutotest { testName: "buildgraph" files: "tst_buildgraph.cpp" } qbs-src-1.4.5/tests/auto/buildgraph/tst_buildgraph.cpp000066400000000000000000000034761266132464200230650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #include #include #include int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); qbs::Internal::TestBuildGraph tbg(ConsoleLogger::instance().logSink()); return QTest::qExec(&tbg, argc, argv); } qbs-src-1.4.5/tests/auto/cmdlineparser/000077500000000000000000000000001266132464200200435ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/cmdlineparser/cmdlineparser.pro000066400000000000000000000003301266132464200234110ustar00rootroot00000000000000TARGET = tst_cmdlineparser SOURCES = tst_cmdlineparser.cpp ../../../src/app/qbs/qbstool.cpp include(../auto.pri) include(../../../src/app/qbs/parser/parser.pri) include(../../../src/app/shared/logging/logging.pri) qbs-src-1.4.5/tests/auto/cmdlineparser/cmdlineparser.qbs000066400000000000000000000014461266132464200234070ustar00rootroot00000000000000import qbs import QbsFunctions QbsAutotest { testName: "cmdlineparser" files: ["tst_cmdlineparser.cpp", "../../../src/app/qbs/qbstool.cpp"] cpp.defines: base.concat([ 'SRCDIR="' + path + '"', "QBS_VERSION=\"" + QbsFunctions.qbsVersion() + "\"" ]) // TODO: Make parser a static library? Group { name: "parser" prefix: "../../../src/app/qbs/parser/" files: [ "command.cpp", "command.h", "commandlineoption.cpp", "commandlineoption.h", "commandlineoptionpool.cpp", "commandlineoptionpool.h", "commandlineparser.cpp", "commandlineparser.h", "commandpool.cpp", "commandpool.h", "commandtype.h", ] } } qbs-src-1.4.5/tests/auto/cmdlineparser/data/000077500000000000000000000000001266132464200207545ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/cmdlineparser/data/dirwithmultipleprojects/000077500000000000000000000000001266132464200257545ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/cmdlineparser/data/dirwithmultipleprojects/project.qbs000066400000000000000000000000001266132464200301170ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/cmdlineparser/data/dirwithmultipleprojects/project2.qbs000066400000000000000000000000001266132464200302010ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/cmdlineparser/data/dirwithnoprojects/000077500000000000000000000000001266132464200245355ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/cmdlineparser/data/dirwithnoprojects/.gitignore000066400000000000000000000000161266132464200265220ustar00rootroot00000000000000* !.gitignore qbs-src-1.4.5/tests/auto/cmdlineparser/data/dirwithoneproject/000077500000000000000000000000001266132464200245175ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/cmdlineparser/data/dirwithoneproject/project.qbs000066400000000000000000000000001266132464200266620ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/cmdlineparser/tst_cmdlineparser.cpp000066400000000000000000000224321266132464200242740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #include #include #include #include #include #include #include #include using namespace qbs; class TestCmdLineParser : public QObject { Q_OBJECT public: TestCmdLineParser() { ConsoleLogger::instance().logSink()->setEnabled(false); } private slots: void testValidCommandLine() { QTemporaryFile projectFile; QVERIFY(projectFile.open()); const QStringList fileArgs = QStringList() << "-f" << projectFile.fileName(); QStringList args; args.append("-vvk"); args.append("-v"); args << "--products" << "blubb"; args << "--changed-files" << "foo,bar" << fileArgs; args << "--force"; args << "--check-timestamps"; CommandLineParser parser; QVERIFY(parser.parseCommandLine(args)); QCOMPARE(ConsoleLogger::instance().logSink()->logLevel(), LoggerTrace); QCOMPARE(parser.command(), BuildCommandType); QCOMPARE(parser.products(), QStringList() << "blubb"); QCOMPARE(parser.buildOptions(QString()).changedFiles().count(), 2); QVERIFY(parser.buildOptions(QString()).keepGoing()); QVERIFY(parser.force()); QVERIFY(parser.forceTimestampCheck()); QVERIFY(!parser.logTime()); QCOMPARE(parser.buildConfigurations().count(), 1); QVERIFY(parser.parseCommandLine(QStringList() << "-vvvqqq" << fileArgs)); QCOMPARE(ConsoleLogger::instance().logSink()->logLevel(), defaultLogLevel()); QVERIFY(!parser.force()); QVERIFY(parser.parseCommandLine(QStringList() << "-t" << fileArgs)); QVERIFY(parser.logTime()); if (!Internal::HostOsInfo::isWindowsHost()) { // Windows has no progress bar atm. // Note: We cannot just check for !parser.logTime() here, because if the test is not // run in a terminal, "--show-progress" is ignored, in which case "--log-time" // takes effect. QVERIFY(parser.parseCommandLine(QStringList() << "-t" << "--show-progress" << fileArgs)); QVERIFY(parser.showProgress() != parser.logTime()); } QVERIFY(parser.parseCommandLine(QStringList() << "-vvqqq" << fileArgs)); QCOMPARE(ConsoleLogger::instance().logSink()->logLevel(), LoggerWarning); QVERIFY(parser.parseCommandLine(QStringList() << "-vvvqq" << fileArgs)); QCOMPARE(ConsoleLogger::instance().logSink()->logLevel(), LoggerDebug); QVERIFY(parser.parseCommandLine(QStringList() << "--log-level" << "trace" << fileArgs)); QCOMPARE(ConsoleLogger::instance().logSink()->logLevel(), LoggerTrace); // Second "global" profile overwrites first. QVERIFY(parser.parseCommandLine(QStringList(fileArgs) << "profile:a" << "profile:b")); QCOMPARE(parser.buildConfigurations().count(), 1); QCOMPARE(parser.buildConfigurations().first().value("qbs.profile").toString(), QLatin1String("b")); // Second build variant-specific profile overwrites first. QVERIFY(parser.parseCommandLine(QStringList(fileArgs) << "debug" << "profile:a" << "profile:b")); QCOMPARE(parser.buildConfigurations().count(), 1); QCOMPARE(parser.buildConfigurations().first().value("qbs.profile").toString(), QLatin1String("b")); QVERIFY(parser.parseCommandLine(QStringList(fileArgs) << "debug" << "profile:a" << "debug" << "profile:b")); QCOMPARE(parser.buildConfigurations().count(), 2); QCOMPARE(parser.buildConfigurations().first().value("qbs.buildVariant").toString(), QLatin1String("debug")); QCOMPARE(parser.buildConfigurations().first().value("qbs.profile").toString(), QLatin1String("a")); QCOMPARE(parser.buildConfigurations().at(1).value("qbs.buildVariant").toString(), QLatin1String("debug")); QCOMPARE(parser.buildConfigurations().at(1).value("qbs.profile").toString(), QLatin1String("b")); // Redundant build request QVERIFY(parser.parseCommandLine(QStringList(fileArgs) << "debug" << "profile:a" << "debug" << "profile:a")); QCOMPARE(parser.buildConfigurations().count(), 1); QVERIFY(parser.parseCommandLine(QStringList(fileArgs) << "debug" << "profile:a" << "release" << "profile:b")); QCOMPARE(parser.buildConfigurations().count(), 2); QCOMPARE(parser.buildConfigurations().first().value("qbs.buildVariant").toString(), QLatin1String("debug")); QCOMPARE(parser.buildConfigurations().first().value("qbs.profile").toString(), QLatin1String("a")); QCOMPARE(parser.buildConfigurations().at(1).value("qbs.buildVariant").toString(), QLatin1String("release")); QCOMPARE(parser.buildConfigurations().at(1).value("qbs.profile").toString(), QLatin1String("b")); // Non-global property takes precedence. QVERIFY(parser.parseCommandLine(QStringList(fileArgs) << "profile:a" << "debug" << "profile:b")); QCOMPARE(parser.buildConfigurations().count(), 1); QCOMPARE(parser.buildConfigurations().first().value("qbs.buildVariant").toString(), QLatin1String("debug")); QCOMPARE(parser.buildConfigurations().first().value("qbs.profile").toString(), QLatin1String("b")); } void testInvalidCommandLine() { QTemporaryFile projectFile; QVERIFY(projectFile.open()); const QStringList fileArgs = QStringList() << "-f" << projectFile.fileName(); CommandLineParser parser; QVERIFY(!parser.parseCommandLine(QStringList() << fileArgs << "-x")); // Unknown short option. QVERIFY(!parser.parseCommandLine(QStringList() << fileArgs << "--xyz")); // Unknown long option. QVERIFY(!parser.parseCommandLine(QStringList() << fileArgs << "-vjv")); // Invalid position. QVERIFY(!parser.parseCommandLine(QStringList() << fileArgs << "-j")); // Missing argument. QVERIFY(!parser.parseCommandLine(QStringList() << "-j" << "0" << fileArgs)); // Wrong argument. QVERIFY(!parser.parseCommandLine(QStringList() << fileArgs << "--products")); // Missing argument. QVERIFY(!parser.parseCommandLine(QStringList() << "--changed-files" << "," << fileArgs)); // Wrong argument. QVERIFY(!parser.parseCommandLine(QStringList() << "--log-level" << "blubb" << fileArgs)); // Wrong argument. } void testProjectFileLookup() { const QString srcDir = QLatin1String(SRCDIR); const QString noProjectsDir = srcDir + QLatin1String("/data/dirwithnoprojects"); const QString oneProjectDir = srcDir + QLatin1String("/data/dirwithoneproject"); const QString multiProjectsDir = srcDir + QLatin1String("/data/dirwithmultipleprojects"); QVERIFY(QDir(noProjectsDir).exists() && QDir(oneProjectDir).exists() && QDir(multiProjectsDir).exists()); CommandLineParser parser; const QStringList args(QLatin1String("-f")); QString projectFilePath = multiProjectsDir + QLatin1String("/project.qbs"); QVERIFY(parser.parseCommandLine(args + QStringList(projectFilePath))); QCOMPARE(projectFilePath, parser.projectFilePath()); projectFilePath = oneProjectDir + QLatin1String("/project.qbs"); QVERIFY(parser.parseCommandLine(args + QStringList(oneProjectDir))); QCOMPARE(projectFilePath, parser.projectFilePath()); QVERIFY(!parser.parseCommandLine(args + QStringList(noProjectsDir))); QVERIFY(!parser.parseCommandLine(args + QStringList(multiProjectsDir))); } }; QTEST_MAIN(TestCmdLineParser) #include "tst_cmdlineparser.moc" qbs-src-1.4.5/tests/auto/language/000077500000000000000000000000001266132464200167765ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/language/language.pro000066400000000000000000000001751266132464200213060ustar00rootroot00000000000000TARGET = tst_language SOURCES = tst_language.cpp include(../auto.pri) include(../../../src/app/shared/logging/logging.pri) qbs-src-1.4.5/tests/auto/language/language.qbs000066400000000000000000000001231266132464200212640ustar00rootroot00000000000000import qbs QbsAutotest { testName: "language" files: "tst_language.cpp" } qbs-src-1.4.5/tests/auto/language/tst_language.cpp000066400000000000000000000034701266132464200221630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #include #include #include int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); qbs::Internal::TestLanguage tl(ConsoleLogger::instance().logSink()); return QTest::qExec(&tl, argc, argv); } qbs-src-1.4.5/tests/auto/shared.h000066400000000000000000000131611266132464200166340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_TEST_SHARED_H #define QBS_TEST_SHARED_H #include #include #include #include #include #include #include #include #include #include inline QString profileName() { return QLatin1String("qbs_autotests"); } inline QString relativeBuildDir(const QString &pName = QString()) { const QString actualProfileName = pName.isEmpty() ? profileName() : pName; return actualProfileName + QLatin1String("-debug"); } inline QString relativeBuildGraphFilePath() { return relativeBuildDir() + QLatin1Char('/') + relativeBuildDir() + QLatin1String(".bg"); } inline bool regularFileExists(const QString &filePath) { const QFileInfo fi(filePath); return fi.exists() && fi.isFile(); } inline bool directoryExists(const QString &dirPath) { const QFileInfo fi(dirPath); return fi.exists() && fi.isDir(); } inline QString uniqueProductName(const QString &productName, const QString &_profileName) { const QString p = _profileName.isEmpty() ? profileName() : _profileName; return productName + '.' + p; } inline QString relativeProductBuildDir(const QString &productName, const QString &productProfileName = QString(), const QString &topLevelProfileName = QString()) { const QString fullName = uniqueProductName(productName, productProfileName); QString dirName = qbs::Internal::HostOsInfo::rfc1034Identifier(fullName); const QByteArray hash = QCryptographicHash::hash(fullName.toUtf8(), QCryptographicHash::Sha1); dirName.append('.').append(hash.toHex().left(8)); return relativeBuildDir(topLevelProfileName) + '/' + dirName; } inline QString relativeExecutableFilePath(const QString &productName) { return relativeProductBuildDir(productName) + '/' + qbs::Internal::HostOsInfo::appendExecutableSuffix(productName); } inline void waitForNewTimestamp(const QString &testDir) { // Waits for the time that corresponds to the host file system's time stamp granularity. if (qbs::Internal::HostOsInfo::isWindowsHost()) { QTest::qWait(1); // NTFS has 100 ns precision. Let's ignore exFAT. } else { const QString nameTemplate = testDir + "/XXXXXX"; QTemporaryFile f1(nameTemplate); if (!f1.open()) qFatal("Failed to open temp file"); const QDateTime initialTime = QFileInfo(f1).lastModified(); while (true) { QTest::qWait(50); QTemporaryFile f2(nameTemplate); if (!f2.open()) qFatal("Failed to open temp file"); if (QFileInfo(f2).lastModified() > initialTime) break; } } } inline void touch(const QString &fn) { QFile f(fn); int s = f.size(); if (!f.open(QFile::ReadWrite)) qFatal("cannot open file %s", qPrintable(fn)); f.resize(s+1); f.resize(s); } inline void copyFileAndUpdateTimestamp(const QString &source, const QString &target) { QFile::remove(target); if (!QFile::copy(source, target)) qFatal("Failed to copy '%s' to '%s'", qPrintable(source), qPrintable(target)); touch(target); } inline QString objectFileName(const QString &baseName, const QString &profileName) { qbs::Settings settings((QString())); qbs::Profile profile(profileName, &settings); const QString suffix = profile.value("qbs.toolchain").toStringList().contains("msvc") ? "obj" : "o"; return baseName + '.' + suffix; } inline QString inputDirHash(const QString &dir) { return QCryptographicHash::hash(dir.toLatin1(), QCryptographicHash::Sha1).toHex().left(16); } inline QString testWorkDir(const QString &testName) { QString dir = QDir::fromNativeSeparators(QString::fromLocal8Bit(qgetenv("QBS_TEST_WORK_ROOT"))); if (dir.isEmpty()) { dir = QCoreApplication::applicationDirPath() + QStringLiteral("/../tests/auto/"); } else { if (!dir.endsWith(QLatin1Char('/'))) dir += QLatin1Char('/'); } return dir + testName + "/testWorkDir"; } #endif // Include guard. qbs-src-1.4.5/tests/auto/tools/000077500000000000000000000000001266132464200163535ustar00rootroot00000000000000qbs-src-1.4.5/tests/auto/tools/tools.pro000066400000000000000000000001431266132464200202330ustar00rootroot00000000000000TARGET = tst_tools SOURCES = tst_tools.cpp ../../../src/app/qbs/qbstool.cpp include(../auto.pri) qbs-src-1.4.5/tests/auto/tools/tools.qbs000066400000000000000000000001171266132464200202210ustar00rootroot00000000000000import qbs QbsAutotest { testName: "tools" files: ["tst_tools.cpp"] } qbs-src-1.4.5/tests/auto/tools/tst_tools.cpp000066400000000000000000000034521266132464200211150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #include #include #include int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); qbs::Settings settings((QString())); qbs::Internal::TestTools tt(&settings); return QTest::qExec(&tt, argc, argv); } qbs-src-1.4.5/tests/benchmarker/000077500000000000000000000000001266132464200165245ustar00rootroot00000000000000qbs-src-1.4.5/tests/benchmarker/activities.h000066400000000000000000000035221266132464200210430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_BENCHMARKER_ACTIVITY_H #define QBS_BENCHMARKER_ACTIVITY_H #include namespace qbsBenchmarker { enum Activity { ActivityResolving = 1, ActivityRuleExecution = 2, ActivityNullBuild = 4 }; Q_DECLARE_FLAGS(Activities, Activity) Q_DECLARE_OPERATORS_FOR_FLAGS(Activities) } // namespace qbsBenchmarker #endif // Include guard. qbs-src-1.4.5/tests/benchmarker/benchmarker-main.cpp000066400000000000000000000103361266132464200224360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "benchmarker.h" #include "commandlineparser.h" #include "exception.h" #include #include #include using namespace qbsBenchmarker; static QByteArray relativeChange(qint64 oldVal, qint64 newVal) { QByteArray change = newVal == 0 ? "0" : QByteArray::number(std::abs(newVal * 100 / oldVal - 100)); change += " %"; if (oldVal > newVal) change.prepend('-'); else if (oldVal < newVal) change.prepend('+'); return change; } static void printResults(Activity activity, const BenchmarkResults &results) { std::cout << "========== Performance data for "; switch (activity) { case ActivityResolving: std::cout << "Resolving"; break; case ActivityRuleExecution: std::cout << "Rule Execution"; break; case ActivityNullBuild: std::cout << "Null Build"; break; } std::cout << " ==========" << std::endl; const BenchmarkResult result = results.value(activity); const char * const indent = " "; std::cout << indent << "Old instruction count: " << result.oldInstructionCount << std::endl; std::cout << indent << "New instruction count: " << result.newInstructionCount << std::endl; std::cout << indent << "Relative change: " << relativeChange(result.oldInstructionCount, result.newInstructionCount).constData() << std::endl; std::cout << indent << "Old peak memory usage: " << result.oldPeakMemoryUsage << " Bytes" << std::endl; std::cout << indent << "New peak memory usage: " << result.newPeakMemoryUsage << " Bytes" << std::endl; std::cout << indent << "Relative change: " << relativeChange(result.oldPeakMemoryUsage, result.newPeakMemoryUsage).constData() << std::endl; } static void printResults(Activities activities, const BenchmarkResults &results) { if (activities & ActivityResolving) printResults(ActivityResolving, results); if (activities & ActivityRuleExecution) printResults(ActivityRuleExecution, results); if (activities & ActivityNullBuild) printResults(ActivityNullBuild, results); } int main(int argc, char *argv[]) { try { QCoreApplication app(argc, argv); CommandLineParser clParser; clParser.parse(); Benchmarker benchmarker(clParser.activies(), clParser.oldCommit(), clParser.newCommit(), clParser.testProjectFilePath(), clParser.qbsRepoDirPath()); benchmarker.benchmark(); printResults(clParser.activies(), benchmarker.results()); } catch (const Exception &e) { std::cerr << qPrintable(e.description()) << std::endl; return EXIT_FAILURE; } } qbs-src-1.4.5/tests/benchmarker/benchmarker.cpp000066400000000000000000000114221266132464200215110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "benchmarker.h" #include "exception.h" #include "runsupport.h" #include "valgrindrunner.h" #include #include namespace qbsBenchmarker { Benchmarker::Benchmarker(Activities activities, const QString &oldCommit, const QString &newCommit, const QString &testProject, const QString &qbsRepo) : m_activities(activities) , m_oldCommit(oldCommit) , m_newCommit(newCommit) , m_testProject(testProject) , m_qbsRepo(qbsRepo) { } Benchmarker::~Benchmarker() { if (!m_commitToRestore.isEmpty()) { try { runProcess(QStringList() << "git" << "checkout" << m_commitToRestore, m_qbsRepo); } catch (const Exception &e) { qDebug("Failed to restore original commit %s: %s", qPrintable(m_commitToRestore), qPrintable(e.description())); } } } void Benchmarker::benchmark() { rememberCurrentRepoState(); runProcess(QStringList() << "git" << "checkout" << m_oldCommit, m_qbsRepo); const QString oldQbsBuildDir = m_baseOutputDir.path() + "/old-qbs-build"; std::cout << "Building from old repo state..." << std::endl; buildQbs(oldQbsBuildDir); runProcess(QStringList() << "git" << "checkout" << m_newCommit, m_qbsRepo); const QString newQbsBuildDir = m_baseOutputDir.path() + "/new-qbs-build"; std::cout << "Building from new repo state..." << std::endl; buildQbs(newQbsBuildDir); std::cout << "Now running valgrind. This can take a while." << std::endl; ValgrindRunner oldDataRetriever(m_activities, m_testProject, oldQbsBuildDir, m_baseOutputDir.path() + "/old-stuff"); ValgrindRunner newDataRetriever(m_activities, m_testProject, newQbsBuildDir, m_baseOutputDir.path() + "/new-stuff"); QFuture oldFuture = QtConcurrent::run(&oldDataRetriever, &ValgrindRunner::run); QFuture newFuture = QtConcurrent::run(&newDataRetriever, &ValgrindRunner::run); oldFuture.waitForFinished(); foreach (const ValgrindResult &valgrindResult, oldDataRetriever.results()) { BenchmarkResult &benchmarkResult = m_results[valgrindResult.activity]; benchmarkResult.oldInstructionCount = valgrindResult.instructionCount; benchmarkResult.oldPeakMemoryUsage = valgrindResult.peakMemoryUsage; } newFuture.waitForFinished(); foreach (const ValgrindResult &valgrindResult, newDataRetriever.results()) { BenchmarkResult &benchmarkResult = m_results[valgrindResult.activity]; benchmarkResult.newInstructionCount = valgrindResult.instructionCount; benchmarkResult.newPeakMemoryUsage = valgrindResult.peakMemoryUsage; } std::cout << "Done!" << std::endl; } void Benchmarker::rememberCurrentRepoState() { QByteArray commit; runProcess(QStringList() << "git" << "describe" << "HEAD", m_qbsRepo, &commit); m_commitToRestore = QString::fromLatin1(commit); } void Benchmarker::buildQbs(const QString &buildDir) const { if (!QDir::root().mkpath(buildDir)) throw Exception(QString::fromLatin1("Failed to create directory '%1'.").arg(buildDir)); runProcess(QStringList() << "qmake" << m_qbsRepo + "/qbs.pro", buildDir); runProcess(QStringList() << "make" << "-s", buildDir); } } // namespace qbsBenchmarker qbs-src-1.4.5/tests/benchmarker/benchmarker.h000066400000000000000000000052161266132464200211620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_BENCHMARKER_BENCHMARKER_H #define QBS_BENCHMARKER_BENCHMARKER_H #include "activities.h" #include #include #include QT_BEGIN_NAMESPACE class QStringList; QT_END_NAMESPACE namespace qbsBenchmarker { class BenchmarkResult { public: qint64 oldInstructionCount; qint64 newInstructionCount; qint64 oldPeakMemoryUsage; qint64 newPeakMemoryUsage; }; typedef QHash BenchmarkResults; class Benchmarker { public: Benchmarker(Activities activities, const QString &oldCommit, const QString &newCommit, const QString &testProject, const QString &qbsRepo); ~Benchmarker(); void benchmark(); BenchmarkResults results() const { return m_results; } private: void rememberCurrentRepoState(); void buildQbs(const QString &buildDir) const; const Activities m_activities; const QString m_oldCommit; const QString m_newCommit; const QString m_testProject; const QString m_qbsRepo; QString m_commitToRestore; QTemporaryDir m_baseOutputDir; BenchmarkResults m_results; }; } // namespace qbsBenchmarker #endif // Include guard. qbs-src-1.4.5/tests/benchmarker/benchmarker.pro000066400000000000000000000006021266132464200215250ustar00rootroot00000000000000TARGET = qbs_benchmarker DESTDIR = ../../bin CONFIG += console CONFIG -= app_bundle CONFIG += c++11 QT += concurrent SOURCES = \ benchmarker-main.cpp \ benchmarker.cpp \ commandlineparser.cpp \ runsupport.cpp \ valgrindrunner.cpp HEADERS = \ activities.h \ benchmarker.h \ commandlineparser.h \ exception.h \ runsupport.h \ valgrindrunner.h qbs-src-1.4.5/tests/benchmarker/benchmarker.qbs000066400000000000000000000010331266132464200215110ustar00rootroot00000000000000import qbs QtApplication { name: "qbs_benchmarker" destinationDirectory: "bin" type: "application" consoleApplication: true cpp.cxxLanguageVersion: "c++11" Depends { name: "Qt.concurrent" } files: [ "activities.h", "benchmarker-main.cpp", "benchmarker.cpp", "benchmarker.h", "commandlineparser.cpp", "commandlineparser.h", "exception.h", "runsupport.cpp", "runsupport.h", "valgrindrunner.cpp", "valgrindrunner.h", ] } qbs-src-1.4.5/tests/benchmarker/commandlineparser.cpp000066400000000000000000000123521266132464200227360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "commandlineparser.h" #include "exception.h" #include #include #include #include namespace qbsBenchmarker { static QString resolveActivity() { return "resolving"; } static QString ruleExecutionActivity() { return "rule-execution"; } static QString nullBuildActivity() { return "null-build"; } static QString allActivities() { return "all"; } CommandLineParser::CommandLineParser() { } void CommandLineParser::parse() { QCommandLineParser parser; parser.setApplicationDescription("This tool aims to detect qbs performance regressions " "using valgrind."); parser.addHelpOption(); QCommandLineOption oldCommitOption("old-commit", "The old qbs commit.", "old commit"); parser.addOption(oldCommitOption); QCommandLineOption newCommitOption("new-commit", "The new qbs commit.", "new commit"); parser.addOption(newCommitOption); QCommandLineOption testProjectOption("test-project", "The example project to use for the benchmark.", "project file path"); parser.addOption(testProjectOption); QCommandLineOption qbsRepoOption("qbs-repo", "The qbs repository.", "repo path"); parser.addOption(qbsRepoOption); QCommandLineOption activitiesOption("activities", QString::fromLatin1("The activities to benchmark. Possible values (CSV): %1,%2,%3,%4") .arg(resolveActivity(), ruleExecutionActivity(), nullBuildActivity(), allActivities()), "activities", allActivities()); parser.addOption(activitiesOption); parser.process(*QCoreApplication::instance()); QList mandatoryOptions = QList() << oldCommitOption << newCommitOption << testProjectOption << qbsRepoOption; foreach (const QCommandLineOption &o, mandatoryOptions) { if (!parser.isSet(o)) throwException(o.names().first(), parser.helpText()); if (parser.value(o).isEmpty()) throwException(o.names().first(), QString(), parser.helpText()); } m_oldCommit = parser.value(oldCommitOption); m_newCommit = parser.value(newCommitOption); m_testProjectFilePath = parser.value(testProjectOption); m_qbsRepoDirPath = parser.value(qbsRepoOption); const QStringList activitiesList = parser.value(activitiesOption).split(','); m_activities = 0; foreach (const QString &activityString, activitiesList) { if (activityString == allActivities()) { m_activities = ActivityResolving | ActivityRuleExecution | ActivityNullBuild; break; } else if (activityString == resolveActivity()) { m_activities = ActivityResolving; } else if (activityString == ruleExecutionActivity()) { m_activities |= ActivityRuleExecution; } else if (activityString == nullBuildActivity()) { m_activities |= ActivityNullBuild; } else { throwException(activitiesOption.names().first(), activityString, parser.helpText()); } } } void CommandLineParser::throwException(const QString &optionName, const QString &illegalValue, const QString &helpText) { const QString errorText(QString::fromLatin1("Error parsing command line: Illegal value '%1' " "for option '--%2'.\n%3").arg(illegalValue, optionName, helpText)); throw Exception(errorText); } void CommandLineParser::throwException(const QString &missingOption, const QString &helpText) { const QString errorText(QString::fromLatin1("Error parsing command line: Missing mandatory " "option '--%1'.\n%3").arg(missingOption, helpText)); throw Exception(errorText); } } // namespace qbsBenchmarker qbs-src-1.4.5/tests/benchmarker/commandlineparser.h000066400000000000000000000047451266132464200224120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_BENCHMARKER_COMMANDLINEPARSER_H #define QBS_BENCHMARKER_COMMANDLINEPARSER_H #include "activities.h" #include namespace qbsBenchmarker { class CommandLineParser { public: CommandLineParser(); void parse(); Activities activies() const { return m_activities; } QString oldCommit() const { return m_oldCommit; } QString newCommit() const { return m_newCommit; } QString testProjectFilePath() const { return m_testProjectFilePath; } QString qbsRepoDirPath() const { return m_qbsRepoDirPath; } private: Q_NORETURN void throwException(const QString &optionName, const QString &illegalValue, const QString &helpText); Q_NORETURN void throwException(const QString &missingOption, const QString &helpText); Activities m_activities; QString m_oldCommit; QString m_newCommit; QString m_testProjectFilePath; QString m_qbsRepoDirPath; }; } // namespace qbsBenchmarker #endif // Include guard. qbs-src-1.4.5/tests/benchmarker/exception.h000066400000000000000000000040501266132464200206720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_BENCHMARKER_EXCEPTION_H #define QBS_BENCHMARKER_EXCEPTION_H #include #include namespace qbsBenchmarker { class Exception : public QException { public: explicit Exception(const QString &description) : m_description(description) {} ~Exception() throw() { } QString description() const { return m_description; } private: void raise() const { throw *this; } Exception *clone() const { return new Exception(*this); } QString m_description; }; } // namespace qbsBenchmarker #endif // Include guard. qbs-src-1.4.5/tests/benchmarker/runsupport.cpp000066400000000000000000000055021266132464200214730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "runsupport.h" #include "exception.h" #include #include #include #include namespace qbsBenchmarker { void runProcess(const QStringList &commandLine, const QString &workingDir, QByteArray *output) { QStringList args = commandLine; const QString command = args.takeFirst(); QProcess p; if (!workingDir.isEmpty()) p.setWorkingDirectory(workingDir); p.start(command, args); if (!p.waitForStarted()) throw Exception(QString::fromLatin1("Process '%1' failed to start.").arg(command)); p.waitForFinished(-1); if (p.exitStatus() != QProcess::NormalExit) { throw Exception(QString::fromLatin1("Error running '%1': %2") .arg(command, p.errorString())); } if (p.exitCode() != 0) { QString errorString = QString::fromLatin1("Command '%1' finished with exit code %2.") .arg(command).arg(p.exitCode()); const QByteArray stdErr = p.readAllStandardError(); if (!stdErr.isEmpty()) { errorString += QString::fromLatin1("\nStandard error output was: '%1'") .arg(QString::fromLocal8Bit(stdErr)); } throw Exception(errorString); } if (output) *output = p.readAllStandardOutput().trimmed(); } } // namespace qbsBenchmarker qbs-src-1.4.5/tests/benchmarker/runsupport.h000066400000000000000000000036121266132464200211400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_BENCHMARKER_RUNSUPPORT_H #define QBS_BENCHMARKER_RUNSUPPORT_H #include #include QT_BEGIN_NAMESPACE class QByteArray; class QStringList; QT_END_NAMESPACE namespace qbsBenchmarker { void runProcess(const QStringList &commandLine, const QString& workingDir = QString(), QByteArray *output = 0); } // namespace qbsBenchmarker #endif // Include guard. qbs-src-1.4.5/tests/benchmarker/valgrindrunner.cpp000066400000000000000000000243341266132464200222760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "valgrindrunner.h" #include "exception.h" #include "runsupport.h" #include #include #include #include #include #include namespace qbsBenchmarker { ValgrindRunner::ValgrindRunner(Activities activities, const QString &testProject, const QString &qbsBuildDir, const QString &baseOutputDir) : m_activities(activities) , m_testProject(testProject) , m_qbsBinary(qbsBuildDir + "/bin/qbs") , m_baseOutputDir(baseOutputDir) { if (!QDir::root().mkpath(m_baseOutputDir)) throw Exception(QString::fromLatin1("Failed to create directory '%1'.").arg(baseOutputDir)); } void ValgrindRunner::run() { QList> futures; if (m_activities & ActivityResolving) futures << QtConcurrent::run(this, &ValgrindRunner::traceResolving); if (m_activities & ActivityRuleExecution) futures << QtConcurrent::run(this, &ValgrindRunner::traceRuleExecution); if (m_activities & ActivityNullBuild) futures << QtConcurrent::run(this, &ValgrindRunner::traceNullBuild); while (!futures.isEmpty()) futures.takeFirst().waitForFinished(); } void ValgrindRunner::traceResolving() { const QString buildDirCallgrind = m_baseOutputDir + "/build-dir.resolving.callgrind"; const QString buildDirMassif = m_baseOutputDir + "/build-dir.resolving.massif"; traceActivity(ActivityResolving, buildDirCallgrind, buildDirMassif); } void ValgrindRunner::traceRuleExecution() { const QString buildDirCallgrind = m_baseOutputDir + "/build-dir.rule-execution.callgrind"; const QString buildDirMassif = m_baseOutputDir + "/build-dir.rule-execution.massif"; runProcess(qbsCommandLine("resolve", buildDirCallgrind, false)); runProcess(qbsCommandLine("resolve", buildDirMassif, false)); traceActivity(ActivityRuleExecution, buildDirCallgrind, buildDirMassif); } void ValgrindRunner::traceNullBuild() { const QString buildDirCallgrind = m_baseOutputDir + "/build-dir.null-build.callgrind"; const QString buildDirMassif = m_baseOutputDir + "/build-dir.null-build.massif"; runProcess(qbsCommandLine("build", buildDirCallgrind, false)); runProcess(qbsCommandLine("build", buildDirMassif, false)); traceActivity(ActivityNullBuild, buildDirCallgrind, buildDirMassif); } void ValgrindRunner::traceActivity(Activity activity, const QString &buildDirCallgrind, const QString &buildDirMassif) { QString activityString; QString qbsCommand; bool dryRun; switch (activity) { case ActivityResolving: activityString = "resolving"; qbsCommand = "resolve"; dryRun = false; break; case ActivityRuleExecution: activityString = "rule-execution"; qbsCommand = "build"; dryRun = true; break; case ActivityNullBuild: activityString = "null-build"; qbsCommand = "build"; dryRun = false; break; } const QString outFileCallgrind = m_baseOutputDir + "/outfile." + activityString + ".callgrind"; const QString outFileMassif = m_baseOutputDir + "/outfile." + activityString + ".massif"; QFuture callGrindFuture = QtConcurrent::run(this, &ValgrindRunner::runCallgrind, qbsCommand, buildDirCallgrind, dryRun, outFileCallgrind); QFuture massifFuture = QtConcurrent::run(this, &ValgrindRunner::runMassif, qbsCommand, buildDirMassif, dryRun, outFileMassif); callGrindFuture.waitForFinished(); massifFuture.waitForFinished(); addToResults(ValgrindResult(activity, callGrindFuture.result(), massifFuture.result())); } QStringList ValgrindRunner::qbsCommandLine(const QString &command, const QString &buildDir, bool dryRun) const { QStringList commandLine = QStringList() << m_qbsBinary << command << "-qq" << "-d" << buildDir << "-f" << m_testProject; if (dryRun) commandLine << "--dry-run"; return commandLine; } QStringList ValgrindRunner::wrapForValgrind(const QStringList &commandLine, const QString &tool, const QString &outFile) const { return QStringList() << "valgrind" << "--smc-check=all" << ("--tool=" + tool) << ("--" + tool + "-out-file=" + outFile) << commandLine; } QStringList ValgrindRunner::valgrindCommandLine(const QString &qbsCommand, const QString &buildDir, bool dryRun, const QString &tool, const QString &outFile) const { return wrapForValgrind(qbsCommandLine(qbsCommand, buildDir, dryRun), tool, outFile); } void ValgrindRunner::addToResults(const ValgrindResult &result) { QMutexLocker locker(&m_resultsMutex); m_results << result; } qint64 ValgrindRunner::runCallgrind(const QString &qbsCommand, const QString &buildDir, bool dryRun, const QString &outFile) { runProcess(valgrindCommandLine(qbsCommand, buildDir, dryRun, "callgrind", outFile)); QFile f(outFile); if (!f.open(QIODevice::ReadOnly)) { throw Exception(QString::fromLatin1("Failed to open file '%1': %2") .arg(outFile, f.errorString())); } while (!f.atEnd()) { const QByteArray line = f.readLine().trimmed(); static const QByteArray magicString = "summary: "; if (!line.startsWith(magicString)) continue; const QByteArray icString = line.mid(magicString.count()); bool ok; const qint64 iCount = icString.toLongLong(&ok); if (!ok) { throw Exception(QString::fromLatin1("Unexpected line in callgrind output file " "'%1': '%2'.") .arg(outFile, QString::fromLocal8Bit(line))); } return iCount; } throw Exception(QString::fromLatin1("Failed to find summary line in callgrind " "output file '%1'.").arg(outFile)); } qint64 ValgrindRunner::runMassif(const QString &qbsCommand, const QString &buildDir, bool dryRun, const QString &outFile) { runProcess(valgrindCommandLine(qbsCommand, buildDir, dryRun, "massif", outFile)); QByteArray ms_printOutput; runProcess(QStringList() << "ms_print" << outFile, QString(), &ms_printOutput); QBuffer buffer(&ms_printOutput); buffer.open(QIODevice::ReadOnly); QByteArray peakSnapshot; const QString exceptionStringPattern = QString::fromLatin1("Failed to extract peak memory " "usage from file '%1': %2").arg(outFile); while (!buffer.atEnd()) { const QByteArray line = buffer.readLine(); static const QByteArray magicString = " (peak)"; const int magicStringOffset = line.indexOf(magicString); if (magicStringOffset == -1) continue; int delimiterOffset = line.lastIndexOf(',', magicStringOffset); if (delimiterOffset == -1) delimiterOffset = line.lastIndexOf('[', magicStringOffset); if (delimiterOffset == -1) { const QString details = QString::fromLatin1("Failed to extract peak snapshot from " "line '%1'.").arg(QString::fromLocal8Bit(line)); throw Exception(exceptionStringPattern.arg(details)); } peakSnapshot = line.mid(delimiterOffset + 1, magicStringOffset - delimiterOffset).trimmed(); break; } if (peakSnapshot.isEmpty()) throw Exception(exceptionStringPattern.arg("No peak marker found")); while (!buffer.atEnd()) { const QByteArray line = buffer.readLine().simplified(); if (!line.startsWith(peakSnapshot + ' ')) continue; const QList entries = line.split(' '); if (entries.count() != 6) { const QString details = QString::fromLatin1("Expected 6 entries in line '%1', but " "there are %2.").arg(QString::fromLocal8Bit(line)).arg(entries.count()); throw Exception(exceptionStringPattern.arg(details)); } QByteArray peakMemoryString = entries.at(4); peakMemoryString.replace(',', QByteArray()); bool ok; qint64 peakMemoryUsage = peakMemoryString.toLongLong(&ok); if (!ok) { const QString details = QString::fromLatin1("Failed to parse peak memory value '%1' " "as a number.").arg(QString::fromLocal8Bit(peakMemoryString)); throw Exception(exceptionStringPattern.arg(details)); } return peakMemoryUsage; } const QString details = QString::fromLatin1("Failed to find snapshot '%1'.") .arg(QString::fromLocal8Bit(peakSnapshot)); throw Exception(exceptionStringPattern.arg(details)); } } // namespace qbsBenchmarker qbs-src-1.4.5/tests/benchmarker/valgrindrunner.h000066400000000000000000000066541266132464200217500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_BENCHMARKER_BENCHMARKRUNNER_H #define QBS_BENCHMARKER_BENCHMARKRUNNER_H #include "activities.h" #include #include #include QT_BEGIN_NAMESPACE class QStringList; QT_END_NAMESPACE namespace qbsBenchmarker { class ValgrindResult { public: ValgrindResult(Activity a, qint64 ic, qint64 mem) : activity(a), instructionCount(ic), peakMemoryUsage(mem) {} Activity activity; qint64 instructionCount; qint64 peakMemoryUsage; }; class ValgrindRunner { public: ValgrindRunner(Activities activities, const QString &testProject, const QString &qbsBuildDir, const QString &baseOutputDir); void run(); QList results() const { return m_results; } private: void traceResolving(); void traceRuleExecution(); void traceNullBuild(); void traceActivity(Activity activity, const QString &buildDirCallgrind, const QString &buildDirMassif); QStringList qbsCommandLine(const QString &command, const QString &buildDir, bool dryRun) const; QStringList wrapForValgrind(const QStringList &commandLine, const QString &tool, const QString &outFile) const; QStringList valgrindCommandLine(const QString &qbsCommand, const QString &buildDir, bool dryRun, const QString &tool, const QString &outFile) const; void addToResults(const ValgrindResult &results); qint64 runCallgrind(const QString &qbsCommand, const QString &buildDir, bool dryRun, const QString &outFile); qint64 runMassif(const QString &qbsCommand, const QString &buildDir, bool dryRun, const QString &outFile); const Activities m_activities; const QString m_testProject; const QString m_qbsBinary; const QString m_baseOutputDir; QList m_results; QMutex m_resultsMutex; }; } // namespace qbsBenchmarker #endif // Include guard. qbs-src-1.4.5/tests/fuzzy-test/000077500000000000000000000000001266132464200164075ustar00rootroot00000000000000qbs-src-1.4.5/tests/fuzzy-test/commandlineparser.cpp000066400000000000000000000121411266132464200226150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "commandlineparser.h" #include #include static QString profileOption() { return "--profile"; } static QString startCommitOption() { return "--start-commit"; } static QString maxDurationoption() { return "--max-duration"; } static QString jobCountOption() { return "--jobs"; } static QString logOption() { return "--log"; } CommandLineParser::CommandLineParser() { } void CommandLineParser::parse(const QStringList &commandLine) { m_profile.clear(); m_startCommit.clear(); m_maxDuration = 0; m_jobCount = 0; m_log = false; m_commandLine = commandLine; Q_ASSERT(!m_commandLine.isEmpty()); m_command = m_commandLine.takeFirst(); while (!m_commandLine.isEmpty()) { const QString arg = m_commandLine.takeFirst(); if (arg == profileOption()) assignOptionArgument(arg, m_profile); else if (arg == startCommitOption()) assignOptionArgument(arg, m_startCommit); else if (arg == jobCountOption()) assignOptionArgument(arg, m_jobCount); else if (arg == maxDurationoption()) parseDuration(); else if (arg == logOption()) m_log = true; else throw ParseException(QString::fromLocal8Bit("Unknown parameter '%1'").arg(arg)); } if (m_profile.isEmpty()) throw ParseException("No profile given."); if (m_startCommit.isEmpty()) throw ParseException("No start commit given."); } QString CommandLineParser::usageString() const { return QString::fromLocal8Bit("%1 %2 %3 [%4 ] " "[%5 ] [%6]") .arg(QFileInfo(m_command).fileName(), profileOption(), startCommitOption(), maxDurationoption(), jobCountOption(), logOption()); } void CommandLineParser::assignOptionArgument(const QString &option, QString &argument) { if (m_commandLine.isEmpty()) throw ParseException(QString::fromLocal8Bit("Option '%1' needs an argument.").arg(option)); argument = m_commandLine.takeFirst(); if (argument.isEmpty()) { throw ParseException(QString::fromLocal8Bit("Argument for option '%1' must not be empty.") .arg(option)); } } void CommandLineParser::assignOptionArgument(const QString &option, int &argument) { QString numberString; assignOptionArgument(option, numberString); bool ok; argument = numberString.toInt(&ok); if (!ok || argument <= 0) { throw ParseException(QString::fromLocal8Bit("Invalid argument '%1' for option '%2'.") .arg(numberString, option)); } } void CommandLineParser::parseDuration() { QString durationString; QString choppedDurationString; assignOptionArgument(maxDurationoption(), durationString); choppedDurationString = durationString; const char suffix = durationString.at(durationString.count() - 1).toLatin1(); const bool hasSuffix = !std::isdigit(suffix); if (hasSuffix) choppedDurationString.chop(1); bool ok; m_maxDuration = choppedDurationString.toInt(&ok); if (!ok || m_maxDuration <= 0) { throw ParseException(QString::fromLocal8Bit("Invalid duration argument '%1'.") .arg(durationString)); } if (hasSuffix) { switch (suffix) { case 'm': break; case 'd': m_maxDuration *= 24; // Fall-through. case 'h': m_maxDuration *= 60; break; default: throw ParseException(QString::fromLocal8Bit("Invalid duration suffix '%1'.") .arg(suffix)); } } } qbs-src-1.4.5/tests/fuzzy-test/commandlineparser.h000066400000000000000000000052141266132464200222650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_FUZZYTEST_COMMANDLINEPARSER_H #define QBS_FUZZYTEST_COMMANDLINEPARSER_H #include #include class ParseException : public std::exception { public: ParseException(const QString &error) : errorMessage(error) { } ~ParseException() throw() {} QString errorMessage; private: const char *what() const throw() { return qPrintable(errorMessage); } }; class CommandLineParser { public: CommandLineParser(); void parse(const QStringList &commandLine); QString profile() const { return m_profile; } QString startCommit() const { return m_startCommit; } int maxDurationInMinutes() const { return m_maxDuration; } int jobCount() const { return m_jobCount; } bool log() const { return m_log; } QString usageString() const; private: void assignOptionArgument(const QString &option, QString &argument); void assignOptionArgument(const QString &option, int &argument); void parseDuration(); QStringList m_commandLine; QString m_command; QString m_profile; QString m_startCommit; int m_maxDuration; int m_jobCount; bool m_log; }; #endif // Include guard. qbs-src-1.4.5/tests/fuzzy-test/fuzzy-test.pro000066400000000000000000000003221266132464200212720ustar00rootroot00000000000000TARGET = qbs_fuzzy-test DESTDIR = ../../bin CONFIG += console CONFIG -= app_bundle SOURCES = main.cpp \ commandlineparser.cpp \ fuzzytester.cpp HEADERS += \ commandlineparser.h \ fuzzytester.h qbs-src-1.4.5/tests/fuzzy-test/fuzzy-test.qbs000066400000000000000000000004511266132464200212620ustar00rootroot00000000000000import qbs QtApplication { name: "qbs_fuzzy-test" destinationDirectory: "bin" type: "application" consoleApplication: true files: [ "commandlineparser.cpp", "commandlineparser.h", "fuzzytester.cpp", "fuzzytester.h", "main.cpp", ] } qbs-src-1.4.5/tests/fuzzy-test/fuzzytester.cpp000066400000000000000000000277401266132464200215430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "fuzzytester.h" #include #include #include #include #include #include #include #include static QString resolveIncrementalActivity() { return "resolve-incremental"; } static QString buildIncrementalActivity() { return "build-incremental"; } static QString buildFromScratchActivity() { return "build-from-scratch"; } FuzzyTester::FuzzyTester() { loadSettings(); } FuzzyTester::~FuzzyTester() { storeSettings(); } void FuzzyTester::runTest(const QString &profile, const QString &startCommit, int maxDurationInMinutes, int jobCount, bool log) { m_profile = profile; m_jobCount = jobCount; m_log = log; runGit(QStringList() << "rev-parse" << "HEAD", &m_headCommit); qDebug("HEAD is %s", qPrintable(m_headCommit)); qDebug("Trying to find a buildable commit to start with..."); const QString workingStartCommit = findWorkingStartCommit(startCommit); qDebug("Found buildable start commit %s.", qPrintable(workingStartCommit)); QStringList allCommits = findAllCommits(workingStartCommit); qDebug("The test set comprises all %d commits between the start commit and HEAD.", allCommits.count()); // Shuffle the initial sequence. Otherwise all invocations of the tool with the same start // commit would try the same sequence of commits. std::srand(std::time(0)); std::random_shuffle(allCommits.begin(), allCommits.end()); quint64 run = 0; QStringList buildSequence(workingStartCommit); QElapsedTimer timer; const qint64 maxDurationInMillis = maxDurationInMinutes * 60 * 1000; if (maxDurationInMillis != 0) timer.start(); bool timerHasExpired = false; while (std::next_permutation(allCommits.begin(), allCommits.end()) && !timerHasExpired) { qDebug("Testing permutation %llu...", ++run); foreach (const QString ¤tCommit, allCommits) { if (timer.isValid() && timer.hasExpired(maxDurationInMillis)) { timerHasExpired = true; break; } m_currentCommit = currentCommit; buildSequence << currentCommit; checkoutCommit(currentCommit); qDebug("Testing incremental build #%d (%s)", buildSequence.count() - 1, qPrintable(currentCommit)); // Doing "resolve" and "build" separately introduces additional possibilities // for errors, as information from change tracking has to be serialized correctly. QString qbsError; m_currentActivity = resolveIncrementalActivity(); bool success = runQbs(defaultBuildDir(), QLatin1String("resolve"), &qbsError); if (success) { m_currentActivity = buildIncrementalActivity(); success = runQbs(defaultBuildDir(), QLatin1String("build"), &qbsError); } m_currentActivity = buildFromScratchActivity(); if (success) { if (!doCleanBuild(&qbsError)) { QString message = "An incremental build succeeded " "with a commit for which a clean build failed."; if (!m_log) { message += QString::fromLocal8Bit("\nThe qbs error message " "for the clean build was: '%1'").arg(qbsError); } throwIncrementalBuildError(message, buildSequence); } } else { qDebug("Incremental build failed. Checking whether clean build works..."); if (doCleanBuild()) { QString message = "An incremental build failed " "with a commit for which a clean build succeeded."; if (!m_log) { message += QString::fromLocal8Bit("\nThe qbs error message for " "the incremental build was: '%1'").arg(qbsError); } throwIncrementalBuildError(message, buildSequence); } else { qDebug("Clean build also fails. Continuing."); } } } } if (timerHasExpired) qDebug("Maximum duration reached."); else qDebug("All possible permutations were tried."); } void FuzzyTester::checkoutCommit(const QString &commit) { runGit(QStringList() << "checkout" << commit); runGit(QStringList() << "submodule" << "update" << "--init"); } QStringList FuzzyTester::findAllCommits(const QString &startCommit) { QString allCommitsString; runGit(QStringList() << "log" << (startCommit + "~1.." + m_headCommit) << "--format=format:%h", &allCommitsString); return allCommitsString.simplified().split(QLatin1Char(' '), QString::SkipEmptyParts); } QString FuzzyTester::findWorkingStartCommit(const QString &startCommit) { const QStringList allCommits = findAllCommits(startCommit); QString qbsError; m_currentActivity = buildFromScratchActivity(); for (int i = allCommits.count() - 1; i >= 0; --i) { m_currentCommit = allCommits.at(i); if (m_unbuildableCommits.contains(m_currentCommit)) { qDebug("Skipping known bad commit %s.", qPrintable(m_currentCommit)); continue; } checkoutCommit(m_currentCommit); removeDir(defaultBuildDir()); if (runQbs(defaultBuildDir(), QLatin1String("build"), &qbsError)) { m_buildableCommits << m_currentCommit; return m_currentCommit; } qDebug("Commit %s is not buildable.", qPrintable(m_currentCommit)); m_unbuildableCommits << m_currentCommit; } throw TestError(QString::fromLocal8Bit("Cannot run test: Failed to find a single commit that " "builds successfully with qbs. The last qbs error was: '%1'").arg(qbsError)); } void FuzzyTester::runGit(const QStringList &arguments, QString *output) { QProcess git; git.start("git", arguments); if (!git.waitForStarted()) throw TestError("Failed to start git. It is expected to be in the PATH."); if (!git.waitForFinished(300000) || git.exitStatus() != QProcess::NormalExit) // 5 minutes ought to be enough for everyone throw TestError(QString::fromLocal8Bit("git failed: %1").arg(git.errorString())); if (git.exitCode() != 0) { throw TestError(QString::fromLocal8Bit("git failed: %1") .arg(QString::fromLocal8Bit(git.readAllStandardError()))); } if (output) *output = QString::fromLocal8Bit(git.readAllStandardOutput()).trimmed(); } bool FuzzyTester::runQbs(const QString &buildDir, const QString &command, QString *errorOutput) { if (errorOutput) errorOutput->clear(); QProcess qbs; QStringList commandLine = QStringList(command) << "-d" << buildDir; if (m_log) { commandLine << "-vv"; const int maxLoggedCommits = 2; Q_ASSERT(m_commitsWithLogFiles.count() <= maxLoggedCommits + 1); if (m_commitsWithLogFiles.count() == maxLoggedCommits + 1) { static const QStringList allActivities = QStringList() << resolveIncrementalActivity() << buildIncrementalActivity() << buildFromScratchActivity(); const QString oldCommit = m_commitsWithLogFiles.dequeue(); foreach (const QString &a, allActivities) QFile::remove(logFilePath(oldCommit, a)); } qbs.setStandardErrorFile(logFilePath(m_currentCommit, m_currentActivity)); if (m_commitsWithLogFiles.isEmpty() || m_commitsWithLogFiles.last() != m_currentCommit) m_commitsWithLogFiles.enqueue(m_currentCommit); } else { commandLine << "-qq"; } if (m_jobCount != 0) commandLine << "--jobs" << QString::number(m_jobCount); commandLine << ("profile:" + m_profile); qbs.start("qbs", commandLine); if (!qbs.waitForStarted()) { throw TestError(QString::fromLocal8Bit("Failed to start qbs. It is expected to be " "in the PATH. QProcess error string: '%1'").arg(qbs.errorString())); } if (!qbs.waitForFinished(-1) || qbs.exitCode() != 0) { if (errorOutput) *errorOutput = QString::fromLocal8Bit(qbs.readAllStandardError()); return false; } return true; } void FuzzyTester::removeDir(const QString &dirPath) { QDir dir(dirPath); if (!dir.removeRecursively()) { throw TestError(QString::fromLocal8Bit("Failed to remove temporary dir '%1'.") .arg(dir.absolutePath())); } } bool FuzzyTester::doCleanBuild(QString *errorMessage) { if (m_unbuildableCommits.contains(m_currentCommit)) { qDebug("Commit is known not to be buildable, not running qbs."); return false; } if (m_buildableCommits.contains(m_currentCommit)) { qDebug("Commit is known to be buildable, not running qbs."); return true; } const QString cleanBuildDir = "fuzzytest-verification-build"; removeDir(cleanBuildDir); if (runQbs(cleanBuildDir, QLatin1String("build"), errorMessage)) { m_buildableCommits << m_currentCommit; return true; } m_unbuildableCommits << m_currentCommit; return false; } void FuzzyTester::throwIncrementalBuildError(const QString &message, const QStringList &commitSequence) { const QString commitSequenceString = commitSequence.join(QLatin1Char(',')); throw TestError(QString::fromLocal8Bit("Found qbs bug with incremental build!\n" "%1\n" "The sequence of commits was: %2.").arg(message, commitSequenceString)); } QString FuzzyTester::logFilePath(const QString &commit, const QString &activity) { return "log." + commit + '.' + activity; } QString FuzzyTester::defaultBuildDir() { return "fuzzytest-build"; } static QString organization() { return "QtProject"; } static QString app() { return "qbs-fuzzy-tester"; } static QString unbuildableCommitsKey() { return "unbuildable-commits"; } static QString buildableCommitsKey() { return "buildable-commits"; } void FuzzyTester::loadSettings() { QSettings s(organization(), app()); m_unbuildableCommits = s.value(unbuildableCommitsKey()).toStringList(); m_buildableCommits = s.value(buildableCommitsKey()).toStringList(); } void FuzzyTester::storeSettings() const { QSettings s(organization(), app()); s.setValue(unbuildableCommitsKey(), m_unbuildableCommits); s.setValue(buildableCommitsKey(), m_buildableCommits); } qbs-src-1.4.5/tests/fuzzy-test/fuzzytester.h000066400000000000000000000060231266132464200211770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #ifndef QBS_FUZZYTESTER_H #define QBS_FUZZYTESTER_H #include #include #include class TestError { public: TestError(const QString &errorMessage) : errorMessage(errorMessage) {} ~TestError() throw() {} QString errorMessage; private: const char *what() const throw() { return qPrintable(errorMessage); } }; class FuzzyTester { public: FuzzyTester(); ~FuzzyTester(); void runTest(const QString &profile, const QString &startCommit, int maxDurationInMinutes, int jobCount, bool log); private: void checkoutCommit(const QString &commit); QStringList findAllCommits(const QString &startCommit); QString findWorkingStartCommit(const QString &startCommit); void runGit(const QStringList &arguments, QString *output = 0); bool runQbs(const QString &buildDir, const QString &command, QString *errorOutput = 0); void removeDir(const QString &dir); bool doCleanBuild(QString *errorMessage = 0); void throwIncrementalBuildError(const QString &message, const QStringList &commitSequence); void loadSettings(); void storeSettings() const; static QString logFilePath(const QString &commit, const QString &activity); static QString defaultBuildDir(); QString m_profile; int m_jobCount; bool m_log; QString m_headCommit; QString m_currentCommit; QString m_currentActivity; QQueue m_commitsWithLogFiles; QStringList m_unbuildableCommits; QStringList m_buildableCommits; }; #endif // Include guard. qbs-src-1.4.5/tests/fuzzy-test/main.cpp000066400000000000000000000066701266132464200200500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include "commandlineparser.h" #include "fuzzytester.h" #include #include #include static bool parseCommandLine(const QStringList &commandLine, QString &profile, QString &startCommi, int &maxDuration, int &jobCount, bool &log); static bool runTest(const QString &profile, const QString &startCommit, int maxDuration, int jobCount, bool log); int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QString profile; QString startCommit; int maxDuration; int jobCount; bool log; if (!parseCommandLine(app.arguments(), profile, startCommit, maxDuration, jobCount, log)) return EXIT_FAILURE; if (!runTest(profile, startCommit, maxDuration, jobCount, log)) return EXIT_FAILURE; std::cout << "Test finished successfully." << std::endl; return EXIT_SUCCESS; } bool parseCommandLine(const QStringList &commandLine, QString &profile, QString &startCommit, int &maxDuration, int &jobCount, bool &log) { CommandLineParser cmdParser; try { cmdParser.parse(commandLine); } catch (const ParseException &e) { std::cerr << "Invalid command line: " << qPrintable(e.errorMessage) << std::endl; std::cerr << "Usage:" << std::endl << qPrintable(cmdParser.usageString()) << std::endl; return false; } profile = cmdParser.profile(); startCommit = cmdParser.startCommit(); maxDuration = cmdParser.maxDurationInMinutes(); jobCount = cmdParser.jobCount(); log = cmdParser.log(); return true; } bool runTest(const QString &profile, const QString &startCommit, int maxDuration, int jobCount, bool log) { try { FuzzyTester().runTest(profile, startCommit, maxDuration, jobCount, log); } catch (const TestError &e) { std::cerr << qPrintable(e.errorMessage) << std::endl; return false; } return true; } qbs-src-1.4.5/tests/manual/000077500000000000000000000000001266132464200155205ustar00rootroot00000000000000qbs-src-1.4.5/tests/manual/configure/000077500000000000000000000000001266132464200175015ustar00rootroot00000000000000qbs-src-1.4.5/tests/manual/configure/configure.qbs000066400000000000000000000004731266132464200221750ustar00rootroot00000000000000import qbs 1.0 import qbs.FileInfo Project { property string name: 'configure' qbsSearchPaths: '.' Product { type: 'application' consoleApplication: true name: project.name files: 'main.cpp' Depends { name: 'cpp' } Depends { name: 'definition' } } } qbs-src-1.4.5/tests/manual/configure/main.cpp000066400000000000000000000031051266132464200211300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include int main() { printf("%s..\n", TEXT); return 0; } qbs-src-1.4.5/tests/manual/configure/modules/000077500000000000000000000000001266132464200211515ustar00rootroot00000000000000qbs-src-1.4.5/tests/manual/configure/modules/definition/000077500000000000000000000000001266132464200233015ustar00rootroot00000000000000qbs-src-1.4.5/tests/manual/configure/modules/definition/module.qbs000066400000000000000000000014541266132464200253010ustar00rootroot00000000000000import qbs 1.0 import qbs.Process Module { name: 'definition' Depends { name: 'cpp' } Probe { id: node property string result configure: { var cmd; var args; if (qbs.targetOS.contains("windows")) { cmd = "cmd"; args = ["/c", "date", "/t"]; } else { cmd = 'date'; args = []; } var p = new Process(); if (0 === p.exec(cmd, args)) { found = true; result = p.readLine(); } else { found = false; result = undefined; } p.close(); } } cpp.defines: node.found ? 'TEXT="Configured at ' + node.result + '"' : undefined } qbs-src-1.4.5/tests/manual/includeLookup/000077500000000000000000000000001266132464200203355ustar00rootroot00000000000000qbs-src-1.4.5/tests/manual/includeLookup/includeLookup.qbs000066400000000000000000000004771266132464200236710ustar00rootroot00000000000000import qbs 1.0 import qbs.FileInfo Project { property string name: 'includeLookup' qbsSearchPaths: '.' Product { type: 'application' consoleApplication: true name: project.name files: 'main.cpp' Depends { name: 'cpp' } Depends { name: 'definition' } } } qbs-src-1.4.5/tests/manual/includeLookup/main.cpp000066400000000000000000000031051266132464200217640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include int main() { printf("%s..\n", TEXT); return 0; } qbs-src-1.4.5/tests/manual/includeLookup/modules/000077500000000000000000000000001266132464200220055ustar00rootroot00000000000000qbs-src-1.4.5/tests/manual/includeLookup/modules/definition/000077500000000000000000000000001266132464200241355ustar00rootroot00000000000000qbs-src-1.4.5/tests/manual/includeLookup/modules/definition/module.qbs000066400000000000000000000004121266132464200261260ustar00rootroot00000000000000import qbs 1.0 import qbs.Probes Module { name: 'definition' Depends { name: 'cpp' } Probes.IncludeProbe { id: includeNode names: "openssl/sha.h" } cpp.defines: includeNode.found ? 'TEXT="' + includeNode.path + '"' : undefined } qbs-src-1.4.5/tests/manual/localDeployment/000077500000000000000000000000001266132464200206535ustar00rootroot00000000000000qbs-src-1.4.5/tests/manual/localDeployment/localDeployment.qbs000066400000000000000000000005201266132464200245120ustar00rootroot00000000000000import qbs 1.0 Project { Product { type: ["application"] consoleApplication: true name: "HelloWorld" destinationDirectory: "bin" Depends { name: "Qt.core"} Group { qbs.install: true qbs.installDir: "share" files: ['main.cpp'] } } } qbs-src-1.4.5/tests/manual/localDeployment/main.cpp000066400000000000000000000033731266132464200223110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing ** ** This file is part of the Qt Build Suite. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms and ** conditions see http://www.qt.io/terms-conditions. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, The Qt Company gives you certain additional ** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #include #include int main(int argc, char **argv) { QCoreApplication app(argc, argv); QFile f(app.applicationDirPath() + "/../share/main.cpp"); f.open(QFile::ReadOnly); qDebug() << f.readAll(); } qbs-src-1.4.5/tests/manual/minimumSystemVersion/000077500000000000000000000000001266132464200217465ustar00rootroot00000000000000qbs-src-1.4.5/tests/manual/minimumSystemVersion/main.cpp000066400000000000000000000036271266132464200234060ustar00rootroot00000000000000#include #include #include #include int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QTextStream out(stdout); #ifdef Q_OS_WIN32 out.setIntegerBase(16); out.setNumberFlags(QTextStream::ShowBase); #ifdef WINVER out << "WINVER = " << WINVER; #else out << "WINVER is not defined"; #endif endl(out); QProcess dumpbin; dumpbin.start("dumpbin", QStringList() << "/HEADERS" << a.applicationFilePath()); dumpbin.waitForStarted(); out << "dumpbin says..."; endl(out); while (dumpbin.waitForReadyRead()) { while (dumpbin.canReadLine()) { QString line = dumpbin.readLine(); if (line.contains("version")) out << line.trimmed() << "\n"; } } dumpbin.waitForFinished(); #endif #ifdef Q_OS_MACX out.setIntegerBase(10); // This gets set by -mmacosx-version-min. If left undefined, defaults to the current OS version. out << "__MAC_OS_X_VERSION_MIN_REQUIRED = " << __MAC_OS_X_VERSION_MIN_REQUIRED; endl(out); // This gets determined by the SDK version you're compiling with out << "__MAC_OS_X_VERSION_MAX_ALLOWED = " << __MAC_OS_X_VERSION_MAX_ALLOWED; endl(out); bool print = false; QProcess otool; otool.start("otool", QStringList() << "-l" << a.applicationFilePath()); otool.waitForStarted(); out << "otool says..."; endl(out); while (otool.waitForReadyRead()) { while (otool.canReadLine()) { QString line = otool.readLine(); if (line.contains("LC_VERSION_MIN_MACOSX")) print = true; if (print && (line.contains("version") || line.contains("sdk"))) { out << line.trimmed(); endl(out); if (line.contains("sdk")) print = false; } } } #endif return 0; } qbs-src-1.4.5/tests/manual/minimumSystemVersion/minimumSystemVersion.qbs000066400000000000000000000044751266132464200267150ustar00rootroot00000000000000import qbs 1.0 Project { // no minimum versions are specified so the profile defaults will be used QtApplication { name: "unspecified" files: "main.cpp" consoleApplication: true Properties { condition: qbs.targetOS.contains("darwin") cpp.frameworks: "Foundation" } } // no minimum versions are specified, and explicitly set to undefined in // case the profile has set it QtApplication { name: "unspecified-forced" files: "main.cpp" consoleApplication: true cpp.minimumWindowsVersion: undefined cpp.minimumOsxVersion: undefined cpp.minimumIosVersion: undefined cpp.minimumAndroidVersion: undefined Properties { condition: qbs.targetOS.contains("darwin") cpp.frameworks: "Foundation" } } // a specific version of the operating systems is specified // when the application is run its output should confirm // that the given values took effect QtApplication { condition: qbs.targetOS.contains("windows") || qbs.targetOS.contains("osx") name: "specific" files: "main.cpp" consoleApplication: true Properties { condition: qbs.targetOS.contains("windows") cpp.minimumWindowsVersion: "6.0" } Properties { condition: qbs.targetOS.contains("osx") cpp.frameworks: "Foundation" cpp.minimumOsxVersion: "10.6" } } // non-existent versions of Windows should print a QBS warning // (but will still compile and link since we avoid passing a // bad value to the linker) QtApplication { condition: qbs.targetOS.contains("windows") name: "fakewindows" files: "main.cpp" consoleApplication: true cpp.minimumWindowsVersion: "5.3" } // just to make sure three-digit minimum versions work on OS X // this only affects the value of __MAC_OS_X_VERSION_MIN_REQUIRED, // not the actual LC_VERSION_MIN_MACOSX command which is limited to two QtApplication { condition: qbs.targetOS.contains("osx") name: "macappstore" files: "main.cpp" consoleApplication: true cpp.frameworks: "Foundation" cpp.minimumOsxVersion: "10.6.8" } } qbs-src-1.4.5/tests/manual/pkgconfig/000077500000000000000000000000001266132464200174675ustar00rootroot00000000000000qbs-src-1.4.5/tests/manual/pkgconfig/main.cpp000066400000000000000000000002311266132464200211130ustar00rootroot00000000000000#include #include int main(int argc, char **argv) { QCoreApplication app(argc, argv); qDebug() << "Hello world!"; } qbs-src-1.4.5/tests/manual/pkgconfig/pkgconfig.qbs000066400000000000000000000006241266132464200221470ustar00rootroot00000000000000import qbs 1.0 import qbs.Probes Project { property string name: 'pkgconfig' CppApplication { name: project.name Probes.PkgConfigProbe { id: pkgConfig name: "QtCore" minVersion: '4.0.0' maxVersion: '5.99.99' } files: 'main.cpp' cpp.cxxFlags: pkgConfig.cflags cpp.linkerFlags: pkgConfig.libs } } qbs-src-1.4.5/tests/manual/run-qbs-tests.bat000066400000000000000000000002261266132464200207370ustar00rootroot00000000000000@echo off :: Usage :: run-qbs-tests.bat qbs debug release profile:x64 platform:clang for /D %%i in (%CD%\*) do ( cmd /C "cd %%i && cmd /C %*" ) qbs-src-1.4.5/tests/manual/run-qbs-tests.sh000077500000000000000000000002471266132464200206110ustar00rootroot00000000000000#!/bin/bash # Usage # ./run-qbs-tests.sh qbs debug release profile:x64 platform:clang for i in *; do [ -d "$i" ] || continue cd "$i" "$@" cd .. done qbs-src-1.4.5/tests/tests.pro000066400000000000000000000000711266132464200161250ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS = auto fuzzy-test benchmarker