From e4c0de9cff31aadb0b87a6ee16d8e27420fe0536 Mon Sep 17 00:00:00 2001 From: Brian Shirai Date: Mon, 9 Feb 2026 20:44:37 -0800 Subject: [PATCH 1/9] Squashed 'certifiable-build/' content from commit 748fa1d git-subtree-dir: certifiable-build git-subtree-split: 748fa1db86129d7f6126d07393849f6a3ee68ef5 --- .gitignore | 0 LICENSE | 678 +++++++++++++++++++++++++++++++++++++ Makefile.template | 63 ++++ README.md | 51 +++ etc/lima/tt-metal-dev.yaml | 21 ++ github/workflows/ci.yml | 24 ++ scripts/build.sh | 10 + scripts/clean.sh | 69 ++++ scripts/config.sh | 62 ++++ scripts/install.sh | 23 ++ scripts/package.sh | 26 ++ scripts/release.sh | 18 + scripts/setup.sh | 47 +++ scripts/start-tt.sh | 136 ++++++++ scripts/test.sh | 10 + 15 files changed, 1238 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 Makefile.template create mode 100644 README.md create mode 100644 etc/lima/tt-metal-dev.yaml create mode 100644 github/workflows/ci.yml create mode 100755 scripts/build.sh create mode 100755 scripts/clean.sh create mode 100755 scripts/config.sh create mode 100755 scripts/install.sh create mode 100755 scripts/package.sh create mode 100755 scripts/release.sh create mode 100755 scripts/setup.sh create mode 100755 scripts/start-tt.sh create mode 100755 scripts/test.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..cebc493 --- /dev/null +++ b/LICENSE @@ -0,0 +1,678 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state 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 program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. + +--- + +For commercial licensing inquiries, contact: william@fstopify.com diff --git a/Makefile.template b/Makefile.template new file mode 100644 index 0000000..3093b98 --- /dev/null +++ b/Makefile.template @@ -0,0 +1,63 @@ +EXES := +DIST := + +# Versioning +VERSION ?= $(shell (git describe --tags 2>/dev/null || echo "develop") | sed 's/^v//') +REVISION ?= $(shell git rev-parse --short HEAD) + +export VERSION +export REVISION + +# Build configuration (overrideable) +# build2 requires out-of-source builds. Default to parent directory with compiler suffix. +SRCDIR := $(notdir $(CURDIR)) +SCRIPTS_DIR ?= ./certifiable-build/scripts +BUILD_DIR ?= ../build2/$(SRCDIR)-default +BUILD_TYPE ?= release +PREFIX ?= /usr/local + +# Export for scripts +export BUILD_DIR +export BUILD_TYPE +export PREFIX + +.PHONY: all help setup start-tt config build test install package release clean + +all: config build test + +##@ Dependencies +setup: ## Setup project + $(SCRIPTS_DIR)/setup.sh + +##@ Development +config: ## Configure the build + $(SCRIPTS_DIR)/config.sh + +build: ## Build the project + $(SCRIPTS_DIR)/build.sh + +start-tt: ## Start the Tenstorrent container + $(SCRIPTS_DIR)/start-tt.sh + +##@ Testing +test: ## Run tests + $(SCRIPTS_DIR)/test.sh + +##@ Project Management +install: build ## Install the project + $(SCRIPTS_DIR)/install.sh + +package: ## Build release artifacts + $(SCRIPTS_DIR)/package.sh + +release: ## Publish release artifacts + $(SCRIPTS_DIR)/release.sh + +##@ Maintenance +clean: ## Remove all build artifacts + $(SCRIPTS_DIR)/clean.sh + +##@ Documentation +help: ## Display this help + @awk 'BEGIN {FS = ":.*##"; printf "Makefile Usage:\n make \033[36m\033[0m\n"} /^[.a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + diff --git a/README.md b/README.md new file mode 100644 index 0000000..357e748 --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +# Certifiable Build + +This repository contains the build infrastructure that supports the [build2](https://www.build2.org) tools for developers and CI systems like GitHub Actions for projects in this organization. + +The repository is included via `git subtree` in the individual component repositories. + +## Building Components + +All components are built using the same four step process: + +1. `make setup` installs the compilers and build2 tools; +1. `make config` configures the source code for building; +1. `make build` builds the source code into artifacts; +1. `make test` runs the tests for the component. + +If you wish, you can skip the `make setup` step and install the required C/C++ compilers and build2 tools yourself. + +## License + +**Dual Licensed:** + +* **Open Source:** GNU General Public License v3.0 (GPLv3) +* **Commercial:** Available for proprietary use in safety-critical systems + +For commercial licensing and compliance documentation packages, contact below. + +## Patent Protection + +This implementation is built on the **Murray Deterministic Computing Platform (MDCP)**, +protected by UK Patent **GB2521625.0**. + +For commercial licensing inquiries: william@fstopify.com + +## About + +Built by **SpeyTech** in the Scottish Highlands. + +30 years of UNIX infrastructure experience applied to deterministic computing for safety-critical systems. + +Patent: UK GB2521625.0 - Murray Deterministic Computing Platform (MDCP) + +**Contact:** +William Murray +william@fstopify.com +[speytech.com](https://speytech.com) + +--- + +*Building deterministic AI systems for when lives depend on the answer.* + +Copyright © 2026 The Murray Family Innovation Trust. All rights reserved. diff --git a/etc/lima/tt-metal-dev.yaml b/etc/lima/tt-metal-dev.yaml new file mode 100644 index 0000000..7f6b48e --- /dev/null +++ b/etc/lima/tt-metal-dev.yaml @@ -0,0 +1,21 @@ +# certifiable-build/etc/lima/tt-metal-dev.yaml +vmType: "qemu" +arch: "x86_64" +plain: true +base: + - template://_images/ubuntu +images: + - location: "ghcr.io/tenstorrent/tt-metal/tt-metalium/ubuntu-22.04-dev-amd64:d6958801d86fe1e20a07f2be7795fac0b2c9b211" + arch: x86_64 + +cpus: 8 +memory: "16GiB" +disk: "80GiB" + +mounts: + - location: "~" + writable: true + +containerd: + system: false + user: false diff --git a/github/workflows/ci.yml b/github/workflows/ci.yml new file mode 100644 index 0000000..a688531 --- /dev/null +++ b/github/workflows/ci.yml @@ -0,0 +1,24 @@ +name: CI + +on: + push: + pull_request: + +permissions: + contents: read + +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + uses: vivarium-ai/certifiable-github/.github/workflows/ci.yml@master + with: + build-target: certifiable-inference + + tt-build: + uses: vivarium-ai/certifiable-github/.github/workflows/tt-ci.yml@master + with: + build-target: certifiable-inference + tt_dev_image: ghcr.io/tenstorrent/tt-metal/tt-metalium/ubuntu-22.04-dev-amd64:d6958801d86fe1e20a07f2be7795fac0b2c9b211 diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 0000000..98aac7d --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,10 @@ +#!/bin/sh +set -eu + +SCRIPT_DIR=$(CDPATH='' cd -- "$(dirname "$0")" && pwd) +REPO_ROOT=$(CDPATH='' cd -- "$SCRIPT_DIR/../.." && pwd) +cd "$REPO_ROOT" + +BDEP=${BDEP:-bdep} + +"$BDEP" update -a @clang @gcc diff --git a/scripts/clean.sh b/scripts/clean.sh new file mode 100755 index 0000000..0d7ee7b --- /dev/null +++ b/scripts/clean.sh @@ -0,0 +1,69 @@ +#!/bin/sh +set -eu + +usage() { + code=${1:-1} + cat </dev/null 2>&1 || true +"$BDEP" deinit --force -a @clang >/dev/null 2>&1 || true +"$BDEP" config remove @gcc >/dev/null 2>&1 || true +"$BDEP" config remove @clang >/dev/null 2>&1 || true + +"$BDEP" --no-default-options init --wipe -C "$clang_dir" @clang cc \ + "config.c=$CC_CLANG" "config.cxx=$CXX_CLANG" \ + "config.config.mode=$BUILD_TYPE" \ + "config.install.root=$PREFIX" + +"$BDEP" --no-default-options init --wipe -C "$gcc_dir" @gcc cc \ + "config.c=$CC_GCC" "config.cxx=$CXX_GCC" \ + "config.config.mode=$BUILD_TYPE" diff --git a/scripts/install.sh b/scripts/install.sh new file mode 100755 index 0000000..94a68e7 --- /dev/null +++ b/scripts/install.sh @@ -0,0 +1,23 @@ +#!/bin/sh +set -eu + +usage() { + cat <-gcc) + PREFIX: Install prefix (env: PREFIX, default: /usr/local) +EOF + exit 1 +} + +cd "$(dirname "$0")/../.." || exit 1 +SRCDIR="$(basename "$(pwd)")" +BUILD_DIR="${1:-${BUILD_DIR:-../$SRCDIR-gcc}}" +PREFIX="${2:-${PREFIX:-/usr/local}}" +B="${B:-b}" + +[ -d "$BUILD_DIR" ] || { echo "Build directory not found. Run build first."; exit 1; } + +echo "Installing to $PREFIX..." +"$B" install: "$BUILD_DIR" \ + "config.install.root=$PREFIX" diff --git a/scripts/package.sh b/scripts/package.sh new file mode 100755 index 0000000..58dda3b --- /dev/null +++ b/scripts/package.sh @@ -0,0 +1,26 @@ +#!/bin/sh +set -eu + +usage() { + cat <-gcc) + VERSION: Package version (env: VERSION, required) + REVISION: Package revision (env: REVISION, required) +EOF + exit 1 +} + +cd "$(dirname "$0")/../.." || exit 1 +SRCDIR="$(basename "$(pwd)")" +BUILD_DIR="${1:-${BUILD_DIR:-../$SRCDIR-gcc}}" +VERSION="${2:-${VERSION:-}}" +REVISION="${3:-${REVISION:-}}" + +[ -z "$VERSION" ] && usage +[ -z "$REVISION" ] && usage +[ -d "$BUILD_DIR" ] || { echo "Build directory not found. Run build first."; exit 1; } + +echo "Creating package $VERSION-$REVISION..." +# Add packaging logic here +echo "Package created." diff --git a/scripts/release.sh b/scripts/release.sh new file mode 100755 index 0000000..7b8c8a0 --- /dev/null +++ b/scripts/release.sh @@ -0,0 +1,18 @@ +#!/bin/sh +set -eu + +usage() { + cat </dev/null 2>&1; then + echo "Homebrew already installed." +else + NONINTERACTIVE=1 /bin/bash -c \ + "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + + case "$OS" in + Linux) + test -d ~/.linuxbrew && eval "$(~/.linuxbrew/bin/brew shellenv)" + test -d /home/linuxbrew/.linuxbrew && eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" + echo "eval \"\$($(brew --prefix)/bin/brew shellenv)\"" >> ~/.bashrc + ;; + Darwin) + if [ -x /opt/homebrew/bin/brew ]; then + eval "$(/opt/homebrew/bin/brew shellenv)" + return 0 + elif [ -x /usr/local/bin/brew ]; then + eval "$(/usr/local/bin/brew shellenv)" + return 0 + fi + ;; + *) + echo "Unsupported OS: $OS" + exit 1 + ;; + esac +fi + +echo "Homebrew version:" +brew --version + +brew update +brew install --overwrite --force gcc llvm build2 +brew link --overwrite --force gcc llvm build2 + +gcc --version +g++ --version +clang --version +clang++ --version +bdep --version + +echo "System dependencies installed successfully." diff --git a/scripts/start-tt.sh b/scripts/start-tt.sh new file mode 100755 index 0000000..c52f3f6 --- /dev/null +++ b/scripts/start-tt.sh @@ -0,0 +1,136 @@ +#!/bin/sh +set -eu + +# Optional env: +# TT_RUNTIME=lima|podman|docker (force runtime selection) +# TT_LIMA_INSTANCE=tt-metal-dev (override Lima instance name) +# TT_LIMA_CONFIG=path/to/yaml (override Lima config file) +# TT_IMAGE=ghcr.io/...:tag (override container image) + +echo "Starting TT environment…" + +# Resolve repo root (prefer git, fall back to current directory) +if command -v git >/dev/null 2>&1 && git rev-parse --show-toplevel >/dev/null 2>&1; then + REPO_ROOT="$(git rev-parse --show-toplevel)" +else + REPO_ROOT="$(pwd)" +fi + +# Normalize REPO_ROOT (best-effort) +# shellcheck disable=SC2164 +cd "$REPO_ROOT" +REPO_ROOT="$(pwd)" + +IMAGE_DEFAULT="ghcr.io/tenstorrent/tt-metal/tt-metalium/ubuntu-22.04-dev-amd64:d6958801d86fe1e20a07f2be7795fac0b2c9b211" +TT_IMAGE="${TT_IMAGE:-$IMAGE_DEFAULT}" + +OS="$(uname -s)" + +TT_LIMA_INSTANCE="${TT_LIMA_INSTANCE:-tt-metal-dev}" +TT_LIMA_CONFIG="${TT_LIMA_CONFIG:-certifiable-build/etc/lima/tt-metal-dev.yaml}" + +# Choose runtime +choose_runtime() { + # If user forced it, obey. + if [ "${TT_RUNTIME:-}" != "" ]; then + echo "$TT_RUNTIME" + return + fi + + case "$OS" in + Darwin) + # Default to Lima on macOS. + echo "lima" + ;; + Linux) + if command -v podman >/dev/null 2>&1; then + echo "podman" + elif command -v docker >/dev/null 2>&1; then + echo "docker" + else + echo "none" + fi + ;; + *) + echo "none" + ;; + esac +} + +RUNTIME="$(choose_runtime)" + +run_container() { + runtime="$1" + + if ! command -v "$runtime" >/dev/null 2>&1; then + echo "Error: requested runtime '$runtime' not found in PATH." + exit 1 + fi + + # Pick a sensible interactive shell inside the container. + # Most of these images have bash; fall back to sh if not. + SHELL_CMD='if command -v bash >/dev/null 2>&1; then exec bash -l; else exec sh -l; fi' + + echo "Using $runtime to run container:" + echo " Image: $TT_IMAGE" + echo " Repo: $REPO_ROOT" + + # --userns=keep-id helps on podman (Linux); harmless or ignored elsewhere. + # We do NOT set --user because macOS Docker Desktop file permissions are quirky; + # on Linux you can add it later if you care. + exec "$runtime" run --rm -it \ + -v "$REPO_ROOT:$REPO_ROOT" \ + -w "$REPO_ROOT" \ + --userns=keep-id \ + "$TT_IMAGE" \ + sh -lc "$SHELL_CMD" +} + +run_lima() { + if ! command -v limactl >/dev/null 2>&1; then + echo "Error: limactl not found. Install Lima (e.g., brew install lima)." + exit 1 + fi + + if [ ! -f "$TT_LIMA_CONFIG" ]; then + echo "Error: Lima config not found at: $TT_LIMA_CONFIG" + echo "Set TT_LIMA_CONFIG to the correct path." + exit 1 + fi + + # Create/start instance if needed. + if limactl list -q | grep -Fx "$TT_LIMA_INSTANCE" >/dev/null 2>&1; then + : # instance exists + else + echo "Creating Lima instance '$TT_LIMA_INSTANCE' from $TT_LIMA_CONFIG…" + limactl create --name="$TT_LIMA_INSTANCE" "$TT_LIMA_CONFIG" + fi + + echo "Starting Lima instance '$TT_LIMA_INSTANCE'…" + limactl start "$TT_LIMA_INSTANCE" >/dev/null + + # Drop into an interactive shell, cd to repo root. + # Note: With your current Lima YAML (containerd disabled), this lands you in the VM. + # If you truly want "container inside Lima", enable containerd or run a container runtime in the VM. + echo "Entering Lima shell (VM) at repo root: $REPO_ROOT" + exec limactl shell "$TT_LIMA_INSTANCE" -- sh -lc "cd '$REPO_ROOT' && if command -v bash >/dev/null 2>&1; then exec bash -l; else exec sh -l; fi" +} + +case "$RUNTIME" in + docker|podman) + run_container "$RUNTIME" + ;; + lima) + # If user set TT_RUNTIME=docker/podman, they get a container on macOS too. + run_lima + ;; + none) + echo "Unsupported or missing runtime on OS '$OS'." + echo "On Linux install podman or docker. On macOS install lima (or set TT_RUNTIME=docker/podman if you insist)." + exit 1 + ;; + *) + echo "Error: unknown TT_RUNTIME='$RUNTIME' (expected lima|docker|podman)." + exit 1 + ;; +esac diff --git a/scripts/test.sh b/scripts/test.sh new file mode 100755 index 0000000..ee46bf5 --- /dev/null +++ b/scripts/test.sh @@ -0,0 +1,10 @@ +#!/bin/sh +set -eu + +SCRIPT_DIR=$(CDPATH='' cd -- "$(dirname "$0")" && pwd) +REPO_ROOT=$(CDPATH='' cd -- "$SCRIPT_DIR/../.." && pwd) +cd "$REPO_ROOT" + +BDEP=${BDEP:-bdep} + +"$BDEP" test -a @clang @gcc From 74bdfd944285b1632bb6b4d1f1a1931bb1b4f9b1 Mon Sep 17 00:00:00 2001 From: Brian Shirai Date: Mon, 9 Feb 2026 20:45:05 -0800 Subject: [PATCH 2/9] Add Makefile. --- Makefile | 131 ++++++++++++++++++++++++++----------------------------- 1 file changed, 63 insertions(+), 68 deletions(-) diff --git a/Makefile b/Makefile index 9d1afe9..3093b98 100644 --- a/Makefile +++ b/Makefile @@ -1,68 +1,63 @@ -# certifiable-deploy Makefile -# Copyright (c) 2026 The Murray Family Innovation Trust. All rights reserved. - -CC = gcc -CFLAGS = -std=c99 -Wall -Wextra -Wpedantic -Werror -Wshadow -Wconversion -CFLAGS += -Wstrict-prototypes -fno-common -O2 -g -CFLAGS += -I./include - -# Source files -AUDIT_SRC = src/audit/sha256.c src/audit/domain_hash.c -ATTEST_SRC = src/attest/merkle.c -TARGET_SRC = src/target/target.c -VERIFY_SRC = src/verify/verify.c - -ALL_SRC = $(AUDIT_SRC) $(ATTEST_SRC) $(TARGET_SRC) $(VERIFY_SRC) - -# Test executables -TEST_AUDIT = tests/unit/test_audit -TEST_ATTEST = tests/unit/test_attest -TEST_TARGET = tests/unit/test_target -TEST_VERIFY = tests/unit/test_verify - -.PHONY: all clean test test-audit test-attest test-target test-verify - -all: $(TEST_AUDIT) $(TEST_ATTEST) $(TEST_TARGET) $(TEST_VERIFY) - -# Test executables -$(TEST_AUDIT): tests/unit/test_audit.c $(AUDIT_SRC) - $(CC) $(CFLAGS) -o $@ $^ - -$(TEST_ATTEST): tests/unit/test_attest.c $(AUDIT_SRC) $(ATTEST_SRC) - $(CC) $(CFLAGS) -o $@ $^ - -$(TEST_TARGET): tests/unit/test_target.c $(TARGET_SRC) - $(CC) $(CFLAGS) -o $@ $^ - -$(TEST_VERIFY): tests/unit/test_verify.c $(ALL_SRC) - $(CC) $(CFLAGS) -o $@ $^ - -# Test targets -test-audit: $(TEST_AUDIT) - ./$(TEST_AUDIT) - -test-attest: $(TEST_ATTEST) - ./$(TEST_ATTEST) - -test-target: $(TEST_TARGET) - ./$(TEST_TARGET) - -test-verify: $(TEST_VERIFY) - ./$(TEST_VERIFY) - -test: all - @echo "" - @echo "========================================" - @echo " certifiable-deploy test suite" - @echo "========================================" - @./$(TEST_AUDIT) - @./$(TEST_ATTEST) - @./$(TEST_TARGET) - @./$(TEST_VERIFY) - @echo "========================================" - @echo " All tests passed!" - @echo "========================================" - -clean: - rm -f $(TEST_AUDIT) $(TEST_ATTEST) $(TEST_TARGET) $(TEST_VERIFY) - rm -f *.o src/*/*.o tests/unit/*.o +EXES := +DIST := + +# Versioning +VERSION ?= $(shell (git describe --tags 2>/dev/null || echo "develop") | sed 's/^v//') +REVISION ?= $(shell git rev-parse --short HEAD) + +export VERSION +export REVISION + +# Build configuration (overrideable) +# build2 requires out-of-source builds. Default to parent directory with compiler suffix. +SRCDIR := $(notdir $(CURDIR)) +SCRIPTS_DIR ?= ./certifiable-build/scripts +BUILD_DIR ?= ../build2/$(SRCDIR)-default +BUILD_TYPE ?= release +PREFIX ?= /usr/local + +# Export for scripts +export BUILD_DIR +export BUILD_TYPE +export PREFIX + +.PHONY: all help setup start-tt config build test install package release clean + +all: config build test + +##@ Dependencies +setup: ## Setup project + $(SCRIPTS_DIR)/setup.sh + +##@ Development +config: ## Configure the build + $(SCRIPTS_DIR)/config.sh + +build: ## Build the project + $(SCRIPTS_DIR)/build.sh + +start-tt: ## Start the Tenstorrent container + $(SCRIPTS_DIR)/start-tt.sh + +##@ Testing +test: ## Run tests + $(SCRIPTS_DIR)/test.sh + +##@ Project Management +install: build ## Install the project + $(SCRIPTS_DIR)/install.sh + +package: ## Build release artifacts + $(SCRIPTS_DIR)/package.sh + +release: ## Publish release artifacts + $(SCRIPTS_DIR)/release.sh + +##@ Maintenance +clean: ## Remove all build artifacts + $(SCRIPTS_DIR)/clean.sh + +##@ Documentation +help: ## Display this help + @awk 'BEGIN {FS = ":.*##"; printf "Makefile Usage:\n make \033[36m\033[0m\n"} /^[.a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + From 944a76505781ed418784a55170badc021a796eb7 Mon Sep 17 00:00:00 2001 From: Brian Shirai Date: Mon, 9 Feb 2026 20:45:20 -0800 Subject: [PATCH 3/9] Add GitHub Actions workflows. --- .github/workflows/ci.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..a688531 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,24 @@ +name: CI + +on: + push: + pull_request: + +permissions: + contents: read + +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + uses: vivarium-ai/certifiable-github/.github/workflows/ci.yml@master + with: + build-target: certifiable-inference + + tt-build: + uses: vivarium-ai/certifiable-github/.github/workflows/tt-ci.yml@master + with: + build-target: certifiable-inference + tt_dev_image: ghcr.io/tenstorrent/tt-metal/tt-metalium/ubuntu-22.04-dev-amd64:d6958801d86fe1e20a07f2be7795fac0b2c9b211 From 1771b751e08d87299b849330a64ed2fcdce13be8 Mon Sep 17 00:00:00 2001 From: Brian Shirai Date: Mon, 9 Feb 2026 20:54:12 -0800 Subject: [PATCH 4/9] Add build2 files. --- .gitattributes | 19 +++++++++++++++++++ .gitignore | 41 +++++++++++++++++++++++++++++++++++++++++ buildfile | 13 +++++++++++++ include/buildfile | 22 ++++++++++++++++++++++ manifest | 13 +++++++++++++ repositories.manifest | 11 +++++++++++ src/buildfile | 9 +++++++++ tests/.gitignore | 8 ++++++++ tests/buildfile | 3 +++ tests/unit/buildfile | 19 +++++++++++++++++++ 10 files changed, 158 insertions(+) create mode 100644 .gitattributes create mode 100644 buildfile create mode 100644 include/buildfile create mode 100644 manifest create mode 100644 repositories.manifest create mode 100644 src/buildfile create mode 100644 tests/.gitignore create mode 100644 tests/buildfile create mode 100644 tests/unit/buildfile diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1631641 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,19 @@ +# This is a good default: files that are auto-detected by git to be text are +# converted to the platform-native line ending (LF on Unix, CRLF on Windows) +# in the working tree and to LF in the repository. +# +* text=auto + +# Use `eol=crlf` for files that should have the CRLF line ending both in the +# working tree (even on Unix) and in the repository. +# +#*.bat text eol=crlf + +# Use `eol=lf` for files that should have the LF line ending both in the +# working tree (even on Windows) and in the repository. +# +#*.sh text eol=lf + +# Use `binary` to make sure certain files are never auto-detected as text. +# +#*.png binary diff --git a/.gitignore b/.gitignore index 3821c60..7b5ec46 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,44 @@ +.bdep/ + +# Local default options files. +# +.build2/local/ + +# Compiler/linker output. +# +*.d +*.t +*.i +*.i.* +*.ii +*.ii.* +*.o +*.obj +*.gcm +*.pcm +*.ifc +*.so +*.dylib +*.dll +*.a +*.lib +*.exp +*.pdb +*.ilk +*.exe +*.exe.dlls/ +*.exe.manifest +*.pc + +# Build2 symlinks exes from build dir to src dir for convenient +tests/unit/test_attest +tests/unit/test_audit +tests/unit/test_target +tests/unit/test_verify +tests/unit/test_bundle +tests/unit/test_loader +tests/unit/test_manifest + # Build build/ *.o diff --git a/buildfile b/buildfile new file mode 100644 index 0000000..3c047cf --- /dev/null +++ b/buildfile @@ -0,0 +1,13 @@ +./: {*/ -build/ -certifiable-build/ -include/ -.github/ -docs/} \ + doc{README.md} \ + legal{LICENSE} \ + manifest + +./: src/ tests/ + +import src = src/ +import tests = tests/ + +# Don't install tests. +# +tests/: install = false diff --git a/include/buildfile b/include/buildfile new file mode 100644 index 0000000..8bd231d --- /dev/null +++ b/include/buildfile @@ -0,0 +1,22 @@ +intf_libs = # Interface dependencies. + +lib{certifiable-training}: h{**} $intf_libs + +# Export options. +# +out_pfx = [dir_path] $out_root/include/ +src_pfx = [dir_path] $src_root/include/ + +lib{certifiable-training}: +{ + c.export.poptions = "-I$out_pfx" "-I$src_pfx" + c.export.libs = $intf_libs +} + +# Install recreating subdirectories. +# +h{*}: +{ + install = include/ + install.subdirs = true +} diff --git a/manifest b/manifest new file mode 100644 index 0000000..f0eb05a --- /dev/null +++ b/manifest @@ -0,0 +1,13 @@ +: 1 +name: certifiable-deploy +version: 0.1.0-a.0.z +type: lib,binless +language: c +summary: Certifiable inference engine with deterministic behavior +license: other: proprietary +description-file: README.md +url: https://github.com/SpeyTech/certifiable-deploy +package-url: https://github.com/SpeyTech/certifiable-deploy +package-email: packaging@build2.org ; Mailing list. +depends: * build2 >= 0.16.0 +depends: * bpkg >= 0.16.0 diff --git a/repositories.manifest b/repositories.manifest new file mode 100644 index 0000000..b8ad813 --- /dev/null +++ b/repositories.manifest @@ -0,0 +1,11 @@ +: 1 +summary: certifiable-deploy project repository + +#: +#role: prerequisite +#location: https://pkg.cppget.org/1/stable +#trust: ... + +#: +#role: prerequisite +#location: https://git.build2.org/hello/libhello.git diff --git a/src/buildfile b/src/buildfile new file mode 100644 index 0000000..348cb21 --- /dev/null +++ b/src/buildfile @@ -0,0 +1,9 @@ +liba{certifiable_deploy}: \ + c{**/**.c} \ + h{../include/**.h} +{ + export = true + install = true +} + +./: liba{certifiable_deploy} diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..662178d --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1,8 @@ +# Test executables. +# +driver + +# Testscript output directories (can be symlinks). +# +test +test-* diff --git a/tests/buildfile b/tests/buildfile new file mode 100644 index 0000000..56a2778 --- /dev/null +++ b/tests/buildfile @@ -0,0 +1,3 @@ +import unit = unit/ + +./: unit/ diff --git a/tests/unit/buildfile b/tests/unit/buildfile new file mode 100644 index 0000000..b90535c --- /dev/null +++ b/tests/unit/buildfile @@ -0,0 +1,19 @@ +tests = exe{test_attest test_audit test_bundle test_loader test_manifest test_target test_verify} + + +exe{test_attest}: c{test_attest} ../../src/liba{certifiable_deploy} +exe{test_audit}: c{test_audit} ../../src/liba{certifiable_deploy} +exe{test_bundle}: c{test_bundle} ../../src/liba{certifiable_deploy} +exe{test_loader}: c{test_loader} ../../src/liba{certifiable_deploy} +exe{test_manifest}: c{test_manifest} ../../src/liba{certifiable_deploy} +exe{test_target}: c{test_target} ../../src/liba{certifiable_deploy} +exe{test_verify}: c{test_verify} ../../src/liba{certifiable_deploy} + +$tests: +{ + c.coptions += -UNDEBUG + c.libs += -lm + test = true +} + +./: $tests From 772a2125f0d652a26c127b5012357aa0c0bff7da Mon Sep 17 00:00:00 2001 From: Brian Shirai Date: Mon, 9 Feb 2026 20:58:09 -0800 Subject: [PATCH 5/9] Remove test executables. --- tests/unit/test_attest | Bin 72808 -> 0 bytes tests/unit/test_audit | Bin 46680 -> 0 bytes tests/unit/test_target | Bin 50384 -> 0 bytes tests/unit/test_verify | Bin 103272 -> 0 bytes 4 files changed, 0 insertions(+), 0 deletions(-) delete mode 100755 tests/unit/test_attest delete mode 100755 tests/unit/test_audit delete mode 100755 tests/unit/test_target delete mode 100755 tests/unit/test_verify diff --git a/tests/unit/test_attest b/tests/unit/test_attest deleted file mode 100755 index 5016f92a2a6798344b39111e9563196a893527f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72808 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 Bm)!sW diff --git a/tests/unit/test_audit b/tests/unit/test_audit deleted file mode 100755 index aa020ec5cace98c213cab672cfb591874fba08d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46680 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℧;;fQoh4Gc=I~&t?p6lb>S1OU`;$Dh~7%#=W z8>zDZ>=~oM^@s~GdBnBOtrZ*V+`HZS%4=Yi`z5!C$xH6HsOBwqtEg#ppQ7?9_i4#+ z+P$8ly54i6hfCPuk%xvyT?pBuuHA01NnnKRB?6kKfI#3tMGB}$c6R}Bn+t)w&Gn)i zL4Hx#hIqc@zR^S7!*)R3ewQ}K*zbD5ji!7-@S-cd1cO1~O6G7Sa`rLyxSw^S>yQH) z`ivTpScvXA>hjhwYw2*$QT?}p7h~jIir7P983o8H1O|pSiyLIRu52AfkD> z6KH{Z+=v#18>>b!SR&@EbKl^04BuwlfRxNqYoxhZH@I)(m^LEmzs-FYCvS>2>n>>d z83gGhv!Z$Jv1QZIVAEG2jH~uLMfce6Jn97TsPjibu(6}1)@bhigyZafk7Qc2I*q2el)Dd_;SV%CBjkiSlcX-KO9-KQvMC zp?O@Ck2*hdQU(3W$U5v=0KS`0u)ffE&GE7>GWvce&rrZ9V~N@`#*9*Q$kN|xdJQZk zTcCN1<4y-J-{*KuWL|Tebdat3ZnEsS`8g$@n}}|}_zd`3fL5cma~N!wMm^!(gCZX8eBOD+8JNmYsNov0=de0nD5sw{YN`ml)yn zoBA{J(P-j({WhdCv$Na|L2|y@_dA$J`yg40E-?3eAp_yvtr9M z8v6XH4>NDKD5jBxNbKo-xHmJ^egg&z829u%*pr#+2mS^tHtz5KW_M<)AL<+ILgVwU zw|8S^CKjMsMqF+*b-lkUGu3bBiS5VkIp%HiGE@C#+h8r4aZlps zNz7C~zBX8I_tQ|{*H&JWo$Px zgugfj=OE}Be$0~`bB3fvU+vldZ_eMDsmlO$4SZbE)vuryqfE!y;_zS8X=sHV1)MGF zt3ADRm7=jO>`08Aw2%wS7ukzbq97P;`KqyQO#M9(RXY;&4v0hSZ!#|6bj1}(7oLS) z4Z1JFX62eePeHpBFBT+q`%1qo@?j@QzoaXHt>Bk4tRnIB5zv#tuW(f55P&?UFzC2Uqt=x;3fF)7XQYuB?cp`#`5S#NyM>6@3vl zD|Za^zE&xcxgPWm4lLD|*AZ6D+|t@mc2+eWr}77QB}@5pCiw(ZKFpGTF)lAtu6)39?EUm0wQc@Wx3su+F1xo5y zGWxTrl|lT?$gJV*bKnJARRtb6*Osh;DWTd`th^S_5CdiP%a^Z$h^>UDp7`69c2?_A zqIxbE2uzuiH+^ydf3h(UV1fJvGxDYvOacs^DhDR}WvxGd4hu{zoH;SCFfen) zBB3doK8XTTM2{8e2^?Olz_Jql{8&7@wb-*qi5D;QoH0NT;N`0q zi-8A3ycP}db_3j!x;m-cvYzojg-fq9q9p@}o@zu2tLkr2K@9{-SC&wO@TY*U4n_g6 zth!ap@z5P=wyFv$M2c62yas=Bw~qeItGy6FU2U+kgal-+rZU8`_{*y-WV7&xR9RLi zxDwwq7Qj@^J3>})ne6?`$^fEDLR1U`A))dlMY;gM?J8MbQ3_kCL!<^2dfSwRMqpX= zW|{tka~A&AQ~grNmsBmq5SGP?s&WDlRZEuC23M#O{jFD(M>tiM$Y|L}xw@2IWmtf< zRZB(LnwkD@WqLpwrzl(#iKDB$K2)i^1edjf*D4^>4<8pkN`9=ASE&zm_Cs9m2d?j-9H`H*H%LV)-6aiH`eXgSRmxA4fWsw& zO5c=plBc`RSoym_BNYnYI&aJKcNf&zkJ$FV6P0#(pOjPScDpe0>aswk55&kHkQFLb z_9_@vR_U%7d3C*`(mQ-gQlv_+qCSp{-F|i5t5Uk}vmdekKZ#0`SMA4gCAUluTY(jH zWw+#F&md!$SN9((tyGLMjn)5ZjQrTCf>EXP`$+o{tN&e8;%9|?3=yBYe@mWDrAU7f zrAS%fgi%4a)Nb}n><*9w`htFO>p6=%;#7bV>*Bz1a#|Rt; zjXye+-Krlv1e#s{t^j9ayJm`XkVvd=C9hJtZ?wy+`^2!6Uu;Q=jFM9+ZM0yQSNAji zS%P2LsbG|xDtCi0(Ukw{`n_1nt9erK$I8<-GNgaFVvwnl9~eU?UOH4dP|6ExEBW(%BI}Epz?7U~ zyzVUWuRSa{zKEGWV&$nE!@>oh+a=^_p9eYy;6r^;g+ujAGEengWUXT?P0Tochyjn) VPfwlOlOMU4i?dr}1Y(Np{{YMO_V@q* diff --git a/tests/unit/test_verify b/tests/unit/test_verify deleted file mode 100755 index 733cbb0f3a105fd53210fd6669bdb93a1ade0508..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 103272 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 O499gd8kVmtTKo-JR#RvI From 645d2a3ff13c0e20bef2f575e928ed37c4c9e18a Mon Sep 17 00:00:00 2001 From: Brian Shirai Date: Tue, 10 Feb 2026 11:23:28 -0800 Subject: [PATCH 6/9] Fix improper gitignore. --- .gitignore | 1 - build/.gitignore | 4 ++++ build/bootstrap.build | 7 +++++++ build/export.build | 6 ++++++ build/root.build | 11 +++++++++++ 5 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 build/.gitignore create mode 100644 build/bootstrap.build create mode 100644 build/export.build create mode 100644 build/root.build diff --git a/.gitignore b/.gitignore index 7b5ec46..dfdbf1c 100644 --- a/.gitignore +++ b/.gitignore @@ -40,7 +40,6 @@ tests/unit/test_loader tests/unit/test_manifest # Build -build/ *.o *.a *.so diff --git a/build/.gitignore b/build/.gitignore new file mode 100644 index 0000000..974e01d --- /dev/null +++ b/build/.gitignore @@ -0,0 +1,4 @@ +/config.build +/root/ +/bootstrap/ +build/ diff --git a/build/bootstrap.build b/build/bootstrap.build new file mode 100644 index 0000000..df32c5f --- /dev/null +++ b/build/bootstrap.build @@ -0,0 +1,7 @@ +project = certifiable-deploy + +using version +using config +using test +using install +using dist diff --git a/build/export.build b/build/export.build new file mode 100644 index 0000000..3a2824c --- /dev/null +++ b/build/export.build @@ -0,0 +1,6 @@ +$out_root/ +{ + include include/ +} + +export $out_root/include/$import.target diff --git a/build/root.build b/build/root.build new file mode 100644 index 0000000..5f0fb4a --- /dev/null +++ b/build/root.build @@ -0,0 +1,11 @@ +using c +using test + +c.std = c99 +c.warnings = all +c.coptions += -Werror -pedantic -Wno-unused-parameter + +if ($c.id == 'gcc') + c.coptions += -fanalyzer + +c.poptions =+ "-I$src_root/include" From 6c7b708409457433807e4a42550bcb4496912d22 Mon Sep 17 00:00:00 2001 From: Brian Shirai Date: Tue, 24 Feb 2026 11:13:47 -0800 Subject: [PATCH 7/9] Fix for early return in test assertions. --- tests/unit/test_bundle.c | 60 +++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/tests/unit/test_bundle.c b/tests/unit/test_bundle.c index 25002d6..8d20c5b 100644 --- a/tests/unit/test_bundle.c +++ b/tests/unit/test_bundle.c @@ -20,6 +20,20 @@ static int tests_run = 0; static int tests_passed = 0; +static void fclosep(FILE **f) { + if (*f) { fclose(*f); } +} + +static void freep(void *p) { + free(*(void **)p); +} + +#if defined(__GNUC__) || defined(__clang__) +#define CLEANUP(func) __attribute__((cleanup(func))) +#else +#define CLEANUP(func) +#endif + #define TEST(name) static int name(void) #define RUN_TEST(name) do { \ tests_run++; \ @@ -203,32 +217,30 @@ TEST(test_le_null_safety) TEST(test_builder_init) { cd_builder_ctx_t ctx; - FILE *fp = tmpfile(); + CLEANUP(fclosep) FILE *fp = tmpfile(); ASSERT(fp != NULL); ASSERT_EQ(cd_builder_init(&ctx, fp), CD_BUNDLE_OK); ASSERT_EQ(ctx.state, CD_BUILD_STATE_WRITING); ASSERT_EQ(ctx.toc_count, 0); ASSERT_EQ(ctx.header.magic, CD_CBF_MAGIC_HEADER); ASSERT_EQ(ctx.header.version, CD_CBF_VERSION); - fclose(fp); return 1; } TEST(test_builder_null_args) { cd_builder_ctx_t ctx; - FILE *fp = tmpfile(); + CLEANUP(fclosep) FILE *fp = tmpfile(); ASSERT(fp != NULL); ASSERT_EQ(cd_builder_init(NULL, fp), CD_BUNDLE_ERR_NULL); ASSERT_EQ(cd_builder_init(&ctx, NULL), CD_BUNDLE_ERR_NULL); - fclose(fp); return 1; } TEST(test_builder_add_sorted) { cd_builder_ctx_t ctx; - FILE *fp = tmpfile(); + CLEANUP(fclosep) FILE *fp = tmpfile(); cd_hash_t h = {{0}}; uint8_t data[] = "test"; ASSERT(fp != NULL); @@ -237,14 +249,13 @@ TEST(test_builder_add_sorted) ASSERT_EQ(cd_builder_add_file(&ctx, "b.bin", data, sizeof(data), &h), CD_BUNDLE_OK); ASSERT_EQ(cd_builder_add_file(&ctx, "c.bin", data, sizeof(data), &h), CD_BUNDLE_OK); ASSERT_EQ(ctx.toc_count, 3); - fclose(fp); return 1; } TEST(test_builder_reject_unsorted) { cd_builder_ctx_t ctx; - FILE *fp = tmpfile(); + CLEANUP(fclosep) FILE *fp = tmpfile(); cd_hash_t h = {{0}}; uint8_t data[] = "test"; ASSERT(fp != NULL); @@ -252,14 +263,13 @@ TEST(test_builder_reject_unsorted) ASSERT_EQ(cd_builder_add_file(&ctx, "b.bin", data, sizeof(data), &h), CD_BUNDLE_OK); ASSERT_EQ(cd_builder_add_file(&ctx, "a.bin", data, sizeof(data), &h), CD_BUNDLE_ERR_NOT_SORTED); ASSERT_EQ(ctx.faults.domain, 1); - fclose(fp); return 1; } TEST(test_builder_reject_duplicate) { cd_builder_ctx_t ctx; - FILE *fp = tmpfile(); + CLEANUP(fclosep) FILE *fp = tmpfile(); cd_hash_t h = {{0}}; uint8_t data[] = "test"; ASSERT(fp != NULL); @@ -267,14 +277,13 @@ TEST(test_builder_reject_duplicate) ASSERT_EQ(cd_builder_add_file(&ctx, "a.bin", data, sizeof(data), &h), CD_BUNDLE_OK); ASSERT_EQ(cd_builder_add_file(&ctx, "a.bin", data, sizeof(data), &h), CD_BUNDLE_ERR_DUPLICATE); ASSERT_EQ(ctx.faults.domain, 1); - fclose(fp); return 1; } TEST(test_builder_empty_file) { cd_builder_ctx_t ctx; - FILE *fp = tmpfile(); + CLEANUP(fclosep) FILE *fp = tmpfile(); cd_hash_t h = {{0}}; cd_hash_t root = {{0xAA}}; ASSERT(fp != NULL); @@ -284,27 +293,25 @@ TEST(test_builder_empty_file) ASSERT_EQ(ctx.toc_count, 1); ASSERT_EQ(ctx.toc[0].size, 0); ASSERT_EQ(cd_builder_finalize(&ctx, &root, false, NULL), CD_BUNDLE_OK); - fclose(fp); return 1; } TEST(test_builder_add_null_data_nonzero_len) { cd_builder_ctx_t ctx; - FILE *fp = tmpfile(); + CLEANUP(fclosep) FILE *fp = tmpfile(); cd_hash_t h = {{0}}; ASSERT(fp != NULL); ASSERT_EQ(cd_builder_init(&ctx, fp), CD_BUNDLE_OK); /* NULL data with non-zero length is an error */ ASSERT_EQ(cd_builder_add_file(&ctx, "test.bin", NULL, 100, &h), CD_BUNDLE_ERR_NULL); - fclose(fp); return 1; } TEST(test_builder_finalize_with_signature) { cd_builder_ctx_t ctx; - FILE *fp = tmpfile(); + CLEANUP(fclosep) FILE *fp = tmpfile(); cd_hash_t h = {{0x11}}; cd_hash_t root = {{0xAA, 0xBB, 0xCC, 0xDD}}; uint8_t signature[64]; @@ -317,27 +324,25 @@ TEST(test_builder_finalize_with_signature) ASSERT_EQ(cd_builder_add_file(&ctx, "test.bin", data, sizeof(data), &h), CD_BUNDLE_OK); ASSERT_EQ(cd_builder_finalize(&ctx, &root, true, signature), CD_BUNDLE_OK); ASSERT_EQ(ctx.state, CD_BUILD_STATE_FINALIZED); - fclose(fp); return 1; } TEST(test_builder_finalize_signature_null_error) { cd_builder_ctx_t ctx; - FILE *fp = tmpfile(); + CLEANUP(fclosep) FILE *fp = tmpfile(); cd_hash_t root = {{0xAA}}; ASSERT(fp != NULL); ASSERT_EQ(cd_builder_init(&ctx, fp), CD_BUNDLE_OK); /* has_signature=true but signature=NULL is an error */ ASSERT_EQ(cd_builder_finalize(&ctx, &root, true, NULL), CD_BUNDLE_ERR_ATTESTATION); - fclose(fp); return 1; } TEST(test_builder_state_machine) { cd_builder_ctx_t ctx; - FILE *fp = tmpfile(); + CLEANUP(fclosep) FILE *fp = tmpfile(); cd_hash_t h = {{0}}; cd_hash_t root = {{0xAA}}; uint8_t data[] = "test"; @@ -356,7 +361,6 @@ TEST(test_builder_state_machine) /* Cannot finalize twice */ ASSERT_EQ(cd_builder_finalize(&ctx, &root, false, NULL), CD_BUNDLE_ERR_STATE); - fclose(fp); return 1; } @@ -368,13 +372,13 @@ TEST(test_full_build_read_cycle) { cd_builder_ctx_t builder; cd_reader_ctx_t reader; - FILE *fp; + CLEANUP(fclosep) FILE *fp; uint8_t manifest[] = "{\"version\":1}"; uint8_t weights[] = {0x01, 0x02, 0x03, 0x04}; cd_hash_t mh = {{0x11}}; cd_hash_t wh = {{0x22}}; cd_hash_t root = {{0xAA, 0xBB, 0xCC, 0xDD}}; - uint8_t *bundle; + CLEANUP(freep) uint8_t *bundle; size_t bundle_size; const cd_toc_entry_t *entry; const uint8_t *data_ptr; @@ -396,7 +400,6 @@ TEST(test_full_build_read_cycle) bundle = (uint8_t *)malloc(bundle_size); ASSERT(bundle != NULL); ASSERT_EQ(fread(bundle, 1, bundle_size, fp), bundle_size); - fclose(fp); /* Parse */ ASSERT_EQ(cd_reader_init(&reader, bundle, bundle_size), CD_READ_OK); @@ -432,7 +435,6 @@ TEST(test_full_build_read_cycle) ASSERT_EQ(cd_reader_find_entry(&reader, "nonexistent", &entry), CD_READ_ERR_PATH_NOT_FOUND); - free(bundle); return 1; } @@ -440,12 +442,12 @@ TEST(test_full_cycle_with_signature) { cd_builder_ctx_t builder; cd_reader_ctx_t reader; - FILE *fp; + CLEANUP(fclosep) FILE *fp; uint8_t data[] = "signed payload"; cd_hash_t h = {{0x11}}; cd_hash_t root = {{0xAA, 0xBB, 0xCC, 0xDD}}; uint8_t signature[64]; - uint8_t *bundle; + CLEANUP(freep) uint8_t *bundle; size_t bundle_size; memset(signature, 0x42, sizeof(signature)); @@ -463,7 +465,6 @@ TEST(test_full_cycle_with_signature) bundle = (uint8_t *)malloc(bundle_size); ASSERT(bundle != NULL); ASSERT_EQ(fread(bundle, 1, bundle_size, fp), bundle_size); - fclose(fp); ASSERT_EQ(cd_reader_init(&reader, bundle, bundle_size), CD_READ_OK); ASSERT_EQ(cd_reader_parse_header(&reader), CD_READ_OK); @@ -473,7 +474,6 @@ TEST(test_full_cycle_with_signature) ASSERT_EQ(reader.footer.has_signature, true); ASSERT_EQ(memcmp(reader.footer.signature, signature, 64), 0); - free(bundle); return 1; } @@ -599,7 +599,7 @@ TEST(test_little_endian_format) TEST(test_builder_fault_flags) { cd_builder_ctx_t ctx; - FILE *fp = tmpfile(); + CLEANUP(fclosep) FILE *fp = tmpfile(); cd_hash_t h = {{0}}; uint8_t data[] = "test"; const cd_fault_flags_t *faults; @@ -618,8 +618,6 @@ TEST(test_builder_fault_flags) ASSERT_EQ(cd_builder_add_file(&ctx, "a.bin", data, sizeof(data), &h), CD_BUNDLE_ERR_NOT_SORTED); ASSERT_EQ(faults->domain, 1); - fclose(fp); - /* NULL context */ ASSERT(cd_builder_get_faults(NULL) == NULL); From 9a5697913de814c84d09ba941ec672e8e369af30 Mon Sep 17 00:00:00 2001 From: Brian Shirai Date: Tue, 24 Feb 2026 11:15:39 -0800 Subject: [PATCH 8/9] Fix target name attribute in Actions workflow. --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a688531..96fdac8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,10 +15,10 @@ jobs: build: uses: vivarium-ai/certifiable-github/.github/workflows/ci.yml@master with: - build-target: certifiable-inference + build-target: certifiable-deploy tt-build: uses: vivarium-ai/certifiable-github/.github/workflows/tt-ci.yml@master with: - build-target: certifiable-inference + build-target: certifiable-deploy tt_dev_image: ghcr.io/tenstorrent/tt-metal/tt-metalium/ubuntu-22.04-dev-amd64:d6958801d86fe1e20a07f2be7795fac0b2c9b211 From 93fda47f1661ce5bef0ddbdcfd90d93fbd1b4fe4 Mon Sep 17 00:00:00 2001 From: Brian Shirai Date: Tue, 24 Feb 2026 16:40:11 -0800 Subject: [PATCH 9/9] Ensure variables are initialized. --- tests/unit/test_bundle.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/unit/test_bundle.c b/tests/unit/test_bundle.c index 8d20c5b..20b87e5 100644 --- a/tests/unit/test_bundle.c +++ b/tests/unit/test_bundle.c @@ -372,13 +372,13 @@ TEST(test_full_build_read_cycle) { cd_builder_ctx_t builder; cd_reader_ctx_t reader; - CLEANUP(fclosep) FILE *fp; + CLEANUP(fclosep) FILE *fp = NULL; uint8_t manifest[] = "{\"version\":1}"; uint8_t weights[] = {0x01, 0x02, 0x03, 0x04}; cd_hash_t mh = {{0x11}}; cd_hash_t wh = {{0x22}}; cd_hash_t root = {{0xAA, 0xBB, 0xCC, 0xDD}}; - CLEANUP(freep) uint8_t *bundle; + CLEANUP(freep) uint8_t *bundle = NULL; size_t bundle_size; const cd_toc_entry_t *entry; const uint8_t *data_ptr; @@ -442,12 +442,12 @@ TEST(test_full_cycle_with_signature) { cd_builder_ctx_t builder; cd_reader_ctx_t reader; - CLEANUP(fclosep) FILE *fp; + CLEANUP(fclosep) FILE *fp = NULL; uint8_t data[] = "signed payload"; cd_hash_t h = {{0x11}}; cd_hash_t root = {{0xAA, 0xBB, 0xCC, 0xDD}}; uint8_t signature[64]; - CLEANUP(freep) uint8_t *bundle; + CLEANUP(freep) uint8_t *bundle = NULL; size_t bundle_size; memset(signature, 0x42, sizeof(signature));