📄 library_status.cpp
字号:
// Generate Compiler Status HTML from jam regression test output -----------//// Copyright Beman Dawes 2002. Distributed under the Boost// Software License, Version 1.0. (See accompanying file// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)// See http://www.boost.org/tools/regression/ for documentation.//Note: This version of the original program builds a large table//which includes all build variations such as build/release, static/dynamic, etc./*******************************************************************************This program was designed to work unchanged on all platforms andconfigurations. All output which is platform or configuration dependentis obtained from external sources such as the .xml file fromprocess_jam_log execution, the tools/build/xxx-tools.jam files, or theoutput of the config_info tests.Please avoid adding platform or configuration dependencies duringprogram maintenance.*******************************************************************************/#include "boost/filesystem/operations.hpp"#include "boost/filesystem/fstream.hpp"namespace fs = boost::filesystem;#include "detail/tiny_xml.hpp"namespace xml = boost::tiny_xml;#include "boost/iterator/transform_iterator.hpp"#include <cstdlib> // for abort, exit#include <string>#include <vector>#include <set>#include <utility> // for make_pair on STLPort#include <map>#include <algorithm>#include <iostream>#include <fstream>#include <ctime>#include <stdexcept>#include <cassert>#include <utility>using std::string;const string pass_msg( "Pass" );const string warn_msg( "<i>Warn</i>" );const string fail_msg( "<font color=\"#FF0000\"><i>Fail</i></font>" );const string note_msg( "<sup>*</sup>" );const string missing_residue_msg( "<i>Missing</i>" );const std::size_t max_compile_msg_size = 10000;namespace{ fs::path boost_root; // boost-root complete path fs::path locate_root; // locate-root (AKA ALL_LOCATE_TARGET) complete path bool ignore_pass = false; bool no_warn = false; bool no_links = false; fs::directory_iterator end_itr; // transform pathname to something html can accept struct char_xlate { typedef char result_type; result_type operator()(char c) const{ if(c == '/') return '-'; return c; } }; typedef boost::transform_iterator<char_xlate, std::string::const_iterator> html_from_path; template<class I1, class I2> std::ostream & operator<<( std::ostream &os, std::pair<I1, I2> p ){ while(p.first != p.second) os << *p.first++; return os; } struct col_node { int rows, cols; bool has_leaf; typedef std::map<std::string, col_node> subcolumns_t; subcolumns_t m_subcolumns; bool operator<(const col_node &cn) const; col_node() : has_leaf(false) {} std::pair<int, int> get_spans(); }; std::pair<int, int> col_node::get_spans(){ rows = 1; cols = 0; if(has_leaf){ cols = 1; } if(! m_subcolumns.empty()){ subcolumns_t::iterator itr; for(itr = m_subcolumns.begin(); itr != m_subcolumns.end(); ++itr){ std::pair<int, int> spans; spans = itr->second.get_spans(); rows = std::max(rows, spans.first); cols += spans.second; } ++rows; } return std::make_pair(rows, cols); } void build_node_tree(const fs::path & dir_root, col_node & node){ fs::path xml_file_path( dir_root / "test_log.xml" ); if (fs::exists( xml_file_path ) ) { node.has_leaf = true; } fs::directory_iterator itr(dir_root); while(itr != end_itr){ if(fs::is_directory(*itr)){ std::pair<col_node::subcolumns_t::iterator, bool> result = node.m_subcolumns.insert( std::make_pair(itr->leaf(), col_node()) ); build_node_tree(*itr, result.first->second); } ++itr; } } fs::ofstream report; fs::ofstream links_file; string links_name; fs::path notes_path; string notes_html; fs::path notes_map_path; typedef std::multimap< string, string > notes_map; // key is test_name-toolset, // value is note bookmark notes_map notes; string specific_compiler; // if running on one toolset only const string empty_string; // build notes_bookmarks from notes HTML -----------------------------------// void build_notes_bookmarks() { if ( notes_map_path.empty() ) return; fs::ifstream notes_map_file( notes_map_path ); if ( !notes_map_file ) { std::cerr << "Could not open --notes-map input file: " << notes_map_path.string() << std::endl; std::exit( 1 ); } string line; while( std::getline( notes_map_file, line ) ) { string::size_type pos = 0; if ( (pos = line.find( ',', pos )) == string::npos ) continue; string key(line.substr( 0, pos ) ); string bookmark( line.substr( pos+1 ) ); // std::cout << "inserting \"" << key << "\",\"" << bookmark << "\"\n"; notes.insert( notes_map::value_type( key, bookmark ) ); } } // load_notes_html ---------------------------------------------------------// bool load_notes_html() { if ( notes_path.empty() ) return false; fs::ifstream notes_file( notes_path ); if ( !notes_file ) { std::cerr << "Could not open --notes input file: " << notes_path.string() << std::endl; std::exit( 1 ); } string line; bool in_body( false ); while( std::getline( notes_file, line ) ) { if ( in_body && line.find( "</body>" ) != string::npos ) in_body = false; if ( in_body ) notes_html += line; else if ( line.find( "<body>" ) ) in_body = true; } return true; } // extract object library name from target directory string ----------------// string extract_object_library_name( const string & s ) { string t( s ); string::size_type pos = t.find( "/build/" ); if ( pos != string::npos ) pos += 7; else if ( (pos = t.find( "/test/" )) != string::npos ) pos += 6; else return ""; return t.substr( pos, t.find( "/", pos ) - pos ); } // element_content ---------------------------------------------------------// const string & element_content( const xml::element & root, const string & name ) { const static string empty_string; xml::element_list::const_iterator itr; for ( itr = root.elements.begin(); itr != root.elements.end() && (*itr)->name != name; ++itr ) {} return itr != root.elements.end() ? (*itr)->content : empty_string; } // find_element ------------------------------------------------------------// const xml::element & find_element( const xml::element & root, const string & name ) { static const xml::element empty_element; xml::element_list::const_iterator itr; for ( itr = root.elements.begin(); itr != root.elements.end() && (*itr)->name != name; ++itr ) {} return itr != root.elements.end() ? *((*itr).get()) : empty_element; } // attribute_value ----------------------------------------------------------// const string & attribute_value( const xml::element & element, const string & attribute_name ){ xml::attribute_list::const_iterator atr; for( atr = element.attributes.begin(); atr != element.attributes.end(); ++atr ){ if(atr->name == attribute_name) return atr->value; } static const string empty_string; return empty_string; } // generate_report ---------------------------------------------------------// // return 0 if nothing generated, 1 otherwise, except 2 if compiler msgs int generate_report( const xml::element & db, const std::string source_library_name, const string & test_type, const fs::path & target_dir, bool pass, bool always_show_run_output ) { // compile msgs sometimes modified, so make a local copy string compile( ((pass && no_warn) ? empty_string : element_content( db, "compile" )) ); const string & link( pass ? empty_string : element_content( db, "link" ) ); const string & run( (pass && !always_show_run_output) ? empty_string : element_content( db, "run" ) ); string lib( (pass ? empty_string : element_content( db, "lib" )) ); // some compilers output the filename even if there are no errors or // warnings; detect this if one line of output and it contains no space. string::size_type pos = compile.find( '\n', 1 ); if ( pos != string::npos && compile.size()-pos <= 2 && compile.find( ' ' ) == string::npos ) compile.clear(); if ( lib.empty() && ( compile.empty() || test_type == "compile_fail" ) && link.empty() && run.empty() ) return 0; int result = 1; // some kind of msg for sure // limit compile message length if ( compile.size() > max_compile_msg_size ) { compile.erase( max_compile_msg_size ); compile += "...\n (remainder deleted because of excessive size)\n"; } links_file << "<h2><a name=\""; links_file << std::make_pair( html_from_path(target_dir.string().begin()), html_from_path(target_dir.string().end()) ) << "\">" << std::make_pair( html_from_path(target_dir.string().begin()), html_from_path(target_dir.string().end()) ) ; links_file << "</a></h2>\n";; if ( !compile.empty() ) { ++result; links_file << "<h3>Compiler output:</h3><pre>" << compile << "</pre>\n"; } if ( !link.empty() ) links_file << "<h3>Linker output:</h3><pre>" << link << "</pre>\n"; if ( !run.empty() ) links_file << "<h3>Run output:</h3><pre>" << run << "</pre>\n";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -