📄 compiler_status.cpp
字号:
const fs::path find_bin_path(const string& relative){ fs::path bin_path; if (boost_build_v2) { bin_path = locate_root / "bin.v2" / relative; if (!fs::exists(bin_path)) { std::cerr << "warning: could not find build results for '" << relative << "'.\n"; std::cerr << "warning: tried directory " << bin_path.native_directory_string() << "\n"; bin_path = ""; } } else { bin_path = locate_root / "bin/boost" / relative; if (!fs::exists(bin_path)) { bin_path = locate_root / "bin" / relative / "bin"; if (!fs::exists(bin_path)) { bin_path = fs::path( locate_root / relative / "bin" ); if (!fs::exists(bin_path)) { bin_path = fs::path( locate_root / "bin/boost/libs" / relative.substr( relative.find( '/' )+1 ) ); } } } if (!fs::exists(bin_path)) { std::cerr << "warning: could not find build results for '" << relative << "'.\n"; bin_path = ""; } } return bin_path;}// generate_report ---------------------------------------------------------// // return 0 if nothing generated, 1 otherwise, except 2 if compiler msgs int generate_report( const xml::element & db, const string & source_library_name, const string & test_type, const string & test_name, // possibly object library name const string & toolset, bool pass, bool always_show_run_output = false ) { // 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=\"" << source_library_name << "-" << test_name << "-" << toolset << "\">" << source_library_name << " - " << test_name << " - " << toolset << "</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"; // for an object library failure, generate a reference to the object // library failure message, and (once only) generate the object // library failure message itself static std::set< string > failed_lib_target_dirs; // only generate once if ( !lib.empty() ) { if ( lib[0] == '\n' ) lib.erase( 0, 1 ); string object_library_name( extract_object_library_name( lib ) ); // changing the target directory naming scheme breaks // extract_object_library_name() assert( !object_library_name.empty() ); if ( object_library_name.empty() ) std::cerr << "Failed to extract object library name from " << lib << "\n"; links_file << "<h3>Library build failure: </h3>\n" "See <a href=\"#" << source_library_name << "-" << object_library_name << "-" << toolset << "\">" << source_library_name << " - " << object_library_name << " - " << toolset << "</a>"; if ( failed_lib_target_dirs.find( lib ) == failed_lib_target_dirs.end() ) { failed_lib_target_dirs.insert( lib ); fs::path pth( locate_root / lib / "test_log.xml" ); fs::ifstream file( pth ); if ( file ) { xml::element_ptr db = xml::parse( file, pth.string() ); generate_report( *db, source_library_name, test_type, object_library_name, toolset, false ); } else { links_file << "<h2><a name=\"" << object_library_name << "-" << toolset << "\">" << object_library_name << " - " << toolset << "</a></h2>\n" "test_log.xml not found\n"; } } } return result; } // add_notes --------------------------------------------------------------// void add_notes( const string & key, bool fail, string & sep, string & target ) { notes_map::const_iterator itr = notes.lower_bound( key ); if ( itr != notes.end() && itr->first == key ) { for ( ; itr != notes.end() && itr->first == key; ++itr ) { string note_desc( itr->second[0] == '-' ? itr->second.substr( 1 ) : itr->second ); if ( fail || itr->second[0] == '-' ) { target += sep; sep = ","; target += "<a href=\""; target += "#"; target += note_desc; target += "\">"; target += note_desc; target += "</a>"; } } } } // get_notes -------------------------------------------------------------// string get_notes( const string & toolset, const string & library, const string & test, bool fail ) { string sep; string target( "<sup>" ); add_notes( toolset + "/" + library + "/" + test, fail, sep, target ); add_notes( "*/" + library + "/" + test, fail, sep, target ); add_notes( toolset + "/" + library + "/*", fail, sep, target ); add_notes( "*/" + library + "/*", fail, sep, target ); if ( target == "<sup>" ) target.clear(); else target += "</sup>"; return target; } // do_cell ---------------------------------------------------------------// bool do_cell( int compiler, const string & lib_name, const fs::path & test_dir, const string & test_type, const string & test_name, const string & toolset, string & target, bool always_show_run_output ) // return true if any results except simple pass_msg { fs::path target_dir( target_directory( test_dir / toolset ) ); bool pass = false; if ( !fs::exists( target_dir / "test_log.xml" ) ) { std::cerr << "Missing jam_log.xml in target:\n " << target_dir.string() << "\n"; target += "<td>" + missing_residue_msg + "</td>"; return true; } int anything_generated = 0; bool note = false; fs::path pth( target_dir / "test_log.xml" ); fs::ifstream file( pth ); if ( !file ) // could not open jam_log.xml { std::cerr << "Can't open jam_log.xml in target:\n " << target_dir.string() << "\n"; target += "<td>" + missing_residue_msg + "</td>"; return false; } xml::element_ptr dbp = xml::parse( file, pth.string() ); const xml::element & db( *dbp ); std::string test_type_base( test_type ); if ( test_type_base == "run_pyd" ) test_type_base = "run"; else if ( test_type_base.size() > 5 ) { const string::size_type trailer = test_type_base.size() - 5; if ( test_type_base.substr( trailer ) == "_fail" ) { test_type_base.erase( trailer ); } } const xml::element & test_type_element( find_element( db, test_type_base ) ); pass = !test_type_element.name.empty() && attribute_value( test_type_element, "result" ) != "fail"; if ( !no_links ) { note = attribute_value( test_type_element, "result" ) == "note"; // generate bookmarked report of results, and link to it anything_generated = generate_report( db, lib_name, test_type, test_name, toolset, pass, always_show_run_output || note ); } target += "<td>"; // generate the status table cell pass/warn/fail HTML if ( anything_generated != 0 ) { target += "<a href=\""; target += links_name; target += "#"; target += lib_name; target += "-"; target += test_name; target += "-"; target += toolset; target += "\">"; target += pass ? (anything_generated < 2 ? pass_msg : warn_msg) : fail_msg; target += "</a>"; if ( pass && note ) target += note_msg; } else target += pass ? pass_msg : fail_msg; // if notes, generate the superscript HTML if ( !notes.empty() ) target += get_notes( toolset, lib_name, test_name, !pass ); // generate compile-time if requested if ( compile_time ) { const xml::element & compile_element( find_element( db, "compile" ) ); if ( !compile_element.name.empty() ) { string times = attribute_value( compile_element, "timings" ); if ( !times.empty() ) { target += "<br>"; target += times.substr( 0, times.find( " " ) ); } } } // generate run-time if requested if ( run_time ) { const xml::element & run_element( find_element( db, "run" ) ); if ( !run_element.name.empty() ) { string times = attribute_value( run_element, "timings" ); if ( !times.empty() ) { target += "<br>"; target += times.substr( 0, times.find( " " ) ); } } } if ( !pass ) ++error_count[compiler]; target += "</td>"; return (anything_generated != 0) || !pass; }// do_row ------------------------------------------------------------------// void do_row( const fs::path & test_dir, // locate_root / "status/bin/any_test.test" const string & test_name, // "any_test" string & target ) { // get library name, test-type, test-program path, etc., from the .xml file string lib_name; string test_path( test_name ); // test_name is default if missing .test string test_type( "unknown" ); bool always_show_run_output( false ); fs::path xml_file_path; if ( find_file( test_dir, "test_log.xml", xml_file_path ) ) { fs::ifstream file( xml_file_path ); if ( file ) { xml::element_ptr dbp = xml::parse( file, xml_file_path.string() ); const xml::element & db( *dbp ); test_path = attribute_value( db, "test-program" ); lib_name = attribute_value( db, "library" ); test_type = attribute_value( db, "test-type" ); always_show_run_output = attribute_value( db, "show-run-output" ) == "true"; } } // generate the library name, test name, and test type table data string::size_type row_start_pos = target.size(); target += "<tr><td><a href=\"" + url_prefix_dir_view + "/libs/" + lib_name + "\">" + lib_name + "</a></td>"; target += "<td><a href=\"" + url_prefix_checkout_view + "/" + test_path + url_suffix_text_view + "\">" + test_name + "</a>";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -