📄 build.cxx
字号:
//{{{ Banner //==========================================================================//// build.cxx//// libcdl support for building and for header file generation////==========================================================================//####COPYRIGHTBEGIN####// // ----------------------------------------------------------------------------// Copyright (C) 1999, 2000 Red Hat, Inc.//// This file is part of the eCos host tools.//// This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 of the License, or (at your option) // any later version.// // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details.// // You should have received a copy of the GNU General Public License along with// this program; if not, write to the Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.//// ----------------------------------------------------------------------------// //####COPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN#### //// Author(s): bartv// Contributors: bartv// Date: 1999-06-018////####DESCRIPTIONEND####//==========================================================================//}}}//{{{ #include's // ----------------------------------------------------------------------------#include "cdlconfig.h"// Get the infrastructure types, assertions, tracing and similar// facilities.#include <cyg/infra/cyg_ass.h>#include <cyg/infra/cyg_trac.h>// <cdl.hxx> defines everything implemented in this module.// It implicitly supplies <string>, <vector> and <map> because// the class definitions rely on these headers.#include <cdlcore.hxx>// split_custom_build_step() needs access to isspace() etc.#include <cctype>//}}}//{{{ Statics // ----------------------------------------------------------------------------CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlBuildLoadableBody);CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlBuildableBody);CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlDefineLoadableBody);CYGDBG_DEFINE_MEMLEAK_COUNTER(CdlDefinableBody);//}}}//{{{ CdlBuildableBody //{{{ Basics // ----------------------------------------------------------------------------// There is little data specific to a buildable. The only distinguishing// feature is the set of properties that are supported, plus a handful// of functions to extract that information.CdlBuildableBody::CdlBuildableBody(){ CYG_REPORT_FUNCNAME("CdlBuildable:: default constructor"); CYG_REPORT_FUNCARG1XV(this); // There is no data to initialize yet cdlbuildablebody_cookie = CdlBuildableBody_Magic; CYGDBG_MEMLEAK_CONSTRUCTOR(); CYG_POSTCONDITION_THISC(); CYG_REPORT_RETURN();}CdlBuildableBody::~CdlBuildableBody(){ CYG_REPORT_FUNCNAME("CdlBuildable:: destructor"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); cdlbuildablebody_cookie = CdlBuildableBody_Invalid; CYGDBG_MEMLEAK_DESTRUCTOR(); CYG_REPORT_RETURN();}// ----------------------------------------------------------------------------std::stringCdlBuildableBody::get_class_name() const{ CYG_REPORT_FUNCNAME("CdlBuildable::get_class_name"); CYG_PRECONDITION_THISC(); CYG_REPORT_RETURN(); return "buildable";}// ----------------------------------------------------------------------------boolCdlBuildableBody::check_this(cyg_assert_class_zeal zeal) const{ if (CdlBuildableBody_Magic != cdlbuildablebody_cookie) { return false; } CYGDBG_MEMLEAK_CHECKTHIS(); return CdlNodeBody::check_this(zeal);}//}}}//{{{ Add and check property parsers // ----------------------------------------------------------------------------voidCdlBuildableBody::add_property_parsers(std::vector<CdlInterpreterCommandEntry>& parsers){ CYG_REPORT_FUNCNAME("CdlBuildable::add_property_parsers"); static CdlInterpreterCommandEntry commands[] = { CdlInterpreterCommandEntry("compile", &CdlBuildableBody::parse_compile ), CdlInterpreterCommandEntry("object", &CdlBuildableBody::parse_object ), CdlInterpreterCommandEntry("make_object", &CdlBuildableBody::parse_make_object), CdlInterpreterCommandEntry("make", &CdlBuildableBody::parse_make ), CdlInterpreterCommandEntry("build_proc", &CdlBuildableBody::parse_build_proc ), CdlInterpreterCommandEntry("", 0 ), }; for (int i = 0; commands[i].command != 0; i++) { std::vector<CdlInterpreterCommandEntry>::const_iterator j; for (j = parsers.begin(); j != parsers.end(); j++) { if (commands[i].name == j->name) { if (commands[i].command != j->command) { CYG_FAIL("Property names are being re-used"); } break; } } if (j == parsers.end()) { parsers.push_back(commands[i]); } } CdlNodeBody::add_property_parsers(parsers); CYG_REPORT_RETURN();}voidCdlBuildableBody::check_properties(CdlInterpreter interp){ CYG_REPORT_FUNCNAME("CdlBuildable::check_properties"); CYG_REPORT_FUNCARG2XV(this, interp); CYG_PRECONDITION_THISC(); CYG_PRECONDITION_CLASSC(interp); // There are no real constraints on the number of compile // properties etc. // TODO: check that the relevant sources files exist, // unless marked appropriately (build_proc can create // new source files). CdlNodeBody::check_properties(interp); CYG_REPORT_RETURN();}//}}}//{{{ Property parsers // ----------------------------------------------------------------------------// Syntax: compile <file1 file2 ...>//// There are a couple of checks that could be performed here://// 1) does each listed file actually exist? Unfortunately that approach// falls foul of build_proc, which is allowed to generate source files// on the fly.//// 2) does the file have a recognised suffix such as .c or .cxx. This// relies libcdl having some way of knowing how to treat different// files.//// For now there are no validity checks.//// A future extension may allow dependencies to be listed, as an// option. This would allow component vendors to specify that// particular custom build steps should happen before particular// compilations, a more robust approach than the current priority// scheme.intCdlBuildableBody::parse_compile(CdlInterpreter interp, int argc, char** argv){ CYG_REPORT_FUNCNAMETYPE("parse_compile", "result %d"); static char* options[] = { "library:", 0 }; int result = CdlParse::parse_stringvector_property(interp, argc, argv, CdlPropertyId_Compile, options, 0); CYG_REPORT_RETVAL(result); return result;}// ----------------------------------------------------------------------------// A utility to break a custom build step down into its three components.//// A custom build step takes the form:// target : deps// rules//// This utility function takes a single string of this form and breaks// it down into its constituent parts. //// NOTE: this will need lots of extra code in future to allow for// escaped characters, spaces in filenames, etc. For now just keep// things simple.boolCdlBuildableBody::split_custom_build_step(std::string str_data, std::string& target, std::string& deps, std::string& rules, std::string& error_msg){ CYG_REPORT_FUNCNAMETYPE("CdlBuildable::split_custom_build_step", "result %d"); target = ""; deps = ""; rules = ""; error_msg = ""; const char* data = str_data.c_str(); // Skip any leading white space, and make sure that this leaves some real data. while (('\0' != *data) && isspace(*data)) { data++; } if ('\0' == *data) { error_msg = "no data in custom build_step"; CYG_REPORT_RETVAL(false); return false; } // Now extract the target. This consists of any sequence of characters // upto space, tab, colon. for ( ; ('\0' != *data) && (':' != *data) && (' ' != *data) && ('\t' != *data); data++) { target += *data; } // Discard any spaces or tabs, they are of no interest while ((' ' == *data) || ('\t' == *data)) { data++; } // The current character should be a colon if (':' != *data) { error_msg = "expecting a colon `;' after the target `" + target + "'"; CYG_REPORT_RETVAL(false); return false; } // Move past the colon, and skip any further spaces or tabs data++; while (('\0' != *data) && ((' ' == *data) || ('\t' == *data))) { data++; } // Everything from here until the end of line should be part of the deps field, // including white space. while (('\0' != *data) && ('\n' != *data) && (';' != *data)) { deps += *data++; } if ("" == deps) { error_msg = "expecting dependency list after `" + target + ":'"; CYG_REPORT_RETVAL(false); return false; } // Having some rules is compulsory. if ('\0' == *data) { error_msg = "expecting one or more rules after the dependency list"; CYG_REPORT_RETVAL(false); return false; } else { // We are currently at \n or ;, move on to the actual rules data++; } // Rules consist of one or more lines. Any leading white space on a given // line should be discarded. while ('\0' != *data) { // Processing the current rule. Skip leading spaces and tabs while ((' ' == *data) || ('\t' == *data)) { data++; } // Now add everything up to the next newline or EOD to the rules. while (('\0' != *data) && ('\n' != *data)) { rules += *data++; } // Terminate this line of the rules with a newline, even if that // character is absent from the raw data. rules += '\n'; // And ignore the newline in the raw data itself if ('\n' == *data) { data++; } } // Better make sure that there are some rules. All of the looping above // may just have left white space if ("" == rules) { error_msg = "no rules provided"; CYG_REPORT_RETVAL(false); return false; } // Everything is ok. CYG_REPORT_RETVAL(true); return true;}// ----------------------------------------------------------------------------// syntax: make <target> <rules>//// There is rather a lot of checking to be done.//// 1) the priority should be valid. In particular it should be a number// within a reasonable range.//// 2) the rules should take the form:// <target> : <deps> ;|\n rules//// Where the target should be a single file, identical to the// first property argument.static voidparse_make_final_check(CdlInterpreter interp, CdlProperty_String prop){ CYG_REPORT_FUNCNAME("parse_make_final_check"); CYG_PRECONDITION_CLASSC(interp); CYG_PRECONDITION_CLASSC(prop); std::string prio_string = prop->get_option("priority"); if ("" != prio_string) { cdl_int tmp = 1; if (!Cdl::string_to_integer(prio_string, tmp)) { CdlParse::report_property_parse_error(interp, prop,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -