10 #include "../bscript/compiler.h" 11 #include "../bscript/compilercfg.h" 12 #include "../bscript/escriptv.h" 13 #include "../bscript/executor.h" 14 #include "../bscript/executortype.h" 15 #include "../bscript/filefmt.h" 16 #include "../bscript/parser.h" 17 #include "../clib/Program/ProgramConfig.h" 18 #include "../clib/Program/ProgramMain.h" 19 #include "../clib/dirlist.h" 20 #include "../clib/esignal.h" 21 #include "../clib/fileutil.h" 22 #include "../clib/logfacility.h" 23 #include "../clib/mdump.h" 24 #include "../clib/passert.h" 25 #include "../clib/threadhelp.h" 26 #include "../clib/timer.h" 27 #include "../plib/pkg.h" 28 #include "../plib/systemstate.h" 29 #include <format/format.h> 53 <<
" ECOMPILE [options] filespec [filespec ...]\n" 55 <<
" Output is : filespec.ecl\n" 58 <<
" -a compile *.asp pages also\n" 59 <<
" -A automatically compile scripts in main and enabled packages\n" 60 <<
" -Au (as '-A' but only compile updated files)\n" 61 <<
" -b keep building other scripts after errors\n" 62 <<
" -C cfgpath path to configuration (replaces ecompile.cfg)\n" 63 <<
" -d display confusing compiler parse information\n" 64 <<
" -D write dependency information\n" 65 <<
" -e report error on successful compilation (used for testing)\n" 67 <<
" -Ecfgpath set or change the ECOMPILE_CFG_PATH evironment variable\n" 69 <<
" -i include intrusive debug info in .ecl file\n" 70 <<
" -l generate listfile\n" 71 <<
" -m don't optimize object members\n" 73 <<
" -Pdir set or change the EM and INC files Environment Variables\n" 75 <<
" -q quiet mode (suppress normal output)\n" 76 <<
" -r [dir] recurse folder [from 'dir'] (defaults to current folder)\n" 77 <<
" -ri [dir] (as '-r' but only compile .inc files)\n" 78 <<
" -t[v] show timing/profiling information [override quiet mode]\n" 79 <<
" -u compile only updated scripts (.src newer than .ecl)\n" 80 <<
" -f force compile even if up-to-date\n" 81 <<
" -s display summary if -q is not set\n" 82 <<
" -T[N] use threaded compilation, force N threads to run\n" 83 <<
" -vN verbosity level\n" 84 <<
" -w display warnings\n" 85 <<
" -W generate wordfile\n" 86 <<
" -y treat warnings as errors\n" 87 <<
" -x write external .dbg file\n" 88 <<
" -xt write external .dbg.txt info file\n" 91 <<
" If <filespec> are required after an empty -r[i] option, you MUST specify\n" 92 <<
" a literal [dir] of '.' (no quotes) or options will not parse correctly.\n";
114 unsigned UpToDateScripts = 0;
115 unsigned CompiledScripts = 0;
116 unsigned ScriptsWithCompileErrors = 0;
117 size_t ThreadCount = 0;
122 INFO_PRINT <<
"Writing word list to wordlist.txt\n";
123 std::ofstream ofs(
"wordlist.txt", std::ios::out | std::ios::trunc );
139 throw std::runtime_error(
"Error compiling file" );
152 std::string fname( path );
153 std::string filename_src = fname, ext(
"" );
155 std::string::size_type pos = fname.rfind(
'.' );
156 if ( pos != std::string::npos )
157 ext = fname.substr( pos );
159 if ( !ext.compare(
".inc" ) )
165 if ( ext.compare(
".src" ) != 0 && ext.compare(
".hsr" ) != 0 && ext.compare(
".asp" ) != 0 )
167 INFO_PRINT <<
"Didn't find '.src', '.hsr', or '.asp' extension on source filename '" << path
169 throw std::runtime_error(
"Error in source filename" );
171 std::string filename_ecl = fname.replace( pos, 4,
".ecl" );
172 std::string filename_lst = fname.replace( pos, 4,
".lst" );
173 std::string filename_dep = fname.replace( pos, 4,
".dep" );
174 std::string filename_dbg = fname.replace( pos, 4,
".dbg" );
183 INFO_PRINT << filename_src <<
" is newer than " << filename_ecl <<
"\n";
189 std::ifstream ifs( filename_dep.c_str() );
194 while ( getline( ifs, depname ) )
199 INFO_PRINT << depname <<
" is newer than " << filename_ecl <<
"\n";
208 INFO_PRINT << filename_dep <<
" does not exist." 216 INFO_PRINT << filename_ecl <<
" is up-to-date." 231 if ( expect_compile_failure )
236 INFO_PRINT <<
"Compilation failed as expected." 242 throw std::runtime_error(
"Compilation succeeded (-e indicates failure was expected)" );
247 throw std::runtime_error(
"Error compiling file" );
251 INFO_PRINT <<
"Writing: " << filename_ecl <<
"\n";
253 if ( C.
write( filename_ecl.c_str() ) )
255 throw std::runtime_error(
"Error writing output file" );
261 INFO_PRINT <<
"Writing: " << filename_lst <<
"\n";
262 std::ofstream ofs( filename_lst.c_str() );
268 INFO_PRINT <<
"Deleting: " << filename_lst <<
"\n";
276 INFO_PRINT <<
"Writing: " << filename_dbg <<
"\n";
278 INFO_PRINT <<
"Writing: " << filename_dbg <<
".txt" 286 INFO_PRINT <<
"Deleting: " << filename_dbg <<
"\n";
293 INFO_PRINT <<
"Writing: " << filename_dep <<
"\n";
299 INFO_PRINT <<
"Deleting: " << filename_dep <<
"\n";
315 catch ( std::exception& )
319 if ( !keep_building )
327 if ( arg[2] ==
'\0' )
329 else if ( arg[2] ==
'-' )
331 else if ( arg[2] ==
'+' )
340 bool unknown_opt =
false;
342 for (
int i = 1; i < argc; i++ )
344 const char* arg = argv[i];
348 if ( arg[0] ==
'/' || arg[0] ==
'-' )
369 expect_compile_failure =
true;
375 std::string path = &argv[i][2];
376 CfgPathEnv =
"ECOMPILE_CFG_PATH=" + path;
377 _putenv( CfgPathEnv.c_str() );
388 if ( argv[i][2] ==
'P' )
405 if ( argv[i][2] && argv[i][2] !=
'i' )
414 if ( i + 1 < argc && argv[i + 1][0] !=
'-' )
416 if ( i + 1 < argc && argv[i + 1][0] !=
'/' && argv[i + 1][0] !=
'-' )
422 show_timing_details =
true;
423 if ( argv[i][2] ==
'v' )
424 timing_quiet_override =
true;
433 opt_generate_wordlist =
true;
445 keep_building =
true;
461 vlev = atoi( &argv[i][2] );
475 std::string path = &argv[i][2];
476 EmPathEnv =
"ECOMPILE_PATH_EM=" + path;
477 IncPathEnv =
"ECOMPILE_PATH_INC=" + path;
478 _putenv( EmPathEnv.c_str() );
479 _putenv( IncPathEnv.c_str() );
486 int count = atoi( &argv[i][2] );
498 ERROR_PRINT <<
"Unknown option: " << argv[i] <<
"\n";
513 int s_compiled, s_uptodate, s_errors;
514 clock_t
start, finish;
519 s_compiled = s_uptodate = s_errors = 0;
525 std::string
name = dl.name(), ext;
526 if ( name[0] ==
'.' )
529 std::string::size_type pos = name.rfind(
'.' );
530 if ( pos != std::string::npos )
531 ext = name.substr( pos );
535 if ( pos != std::string::npos &&
536 ( !ext.compare(
".src" ) || !ext.compare(
".hsr" ) ||
540 if ( files ==
nullptr )
553 files->push_back( ( basedir + name ) );
560 catch ( std::exception& )
564 if ( !keep_building )
569 if ( files ==
nullptr )
573 if ( ( !quiet || timing_quiet_override ) && show_timing_details && s_compiled > 0 &&
576 INFO_PRINT <<
"Compiled " << s_compiled <<
" script" << ( s_compiled == 1 ?
"" :
"s" ) <<
" in " 577 << basedir <<
" in " << (
int)( ( finish -
start ) / CLOCKS_PER_SEC )
579 if ( s_uptodate > 0 )
580 INFO_PRINT <<
" " << s_uptodate <<
" script" << ( s_uptodate == 1 ?
" was" :
"s were" )
581 <<
" already up-to-date.\n";
583 INFO_PRINT <<
" " << s_errors <<
" script" << ( s_errors == 1 ?
"" :
"s" )
593 std::string
name = dl.name(), ext;
594 if ( name[0] ==
'.' )
597 std::string::size_type pos = name.rfind(
'.' );
598 if ( pos != std::string::npos )
599 ext = name.substr( pos );
601 if ( pos != std::string::npos && !ext.compare(
".inc" ) )
603 if ( files ==
nullptr )
606 files->push_back( ( basedir + name ) );
617 std::atomic<unsigned> compiled_scripts( 0 );
618 std::atomic<unsigned> uptodate_scripts( 0 );
619 std::atomic<unsigned> error_scripts( 0 );
620 std::atomic<bool> par_keep_building(
true );
622 unsigned int thread_count = std::max( 2u, std::thread::hardware_concurrency() * 2 );
627 for (
const auto& file : files )
640 catch ( std::exception& e )
644 ERROR_PRINT <<
"failed to compile " << file.c_str() <<
": " << e.what() <<
"\n";
645 if ( !keep_building )
647 par_keep_building =
false;
652 par_keep_building =
false;
673 std::vector<std::string> files;
695 bool run(
int argc,
char** argv )
710 for (
int i = 1; i < argc; i++ )
713 if ( argv[i][0] ==
'-' )
715 if ( argv[i][0] ==
'/' || argv[i][0] ==
'-' )
719 if ( argv[i][1] ==
'A' )
726 else if ( argv[i][1] ==
'r' )
729 std::string dir(
"." );
733 if ( i < argc && argv[i] && argv[i][0] !=
'-' )
734 dir.assign( argv[i] );
738 std::vector<std::string> files;
753 else if ( argv[i][1] ==
'C' )
784 tmp <<
"Compilation Summary:\n";
806 for (
int i = 1; i < argc; i++ )
808 if ( argv[i][0] ==
'/' || argv[i][0] ==
'-' )
811 if ( argv[i][1] ==
'C' )
815 throw std::runtime_error(
"-C specified without pathname" );
824 const char* env_ecompile_cfg_path = getenv(
"ECOMPILE_CFG_PATH" );
825 if ( env_ecompile_cfg_path !=
nullptr )
832 std::string cfgpath = PROG_CONFIG::programDir() +
"ecompile.cfg";
843 ERROR_PRINT <<
"Could not find " << cfgpath <<
"; using defaults.\n";
853 const std::vector<std::string>& binArgs =
programArgs();
858 if ( binArgs.size() == 1 )
881 ERROR_PRINT <<
"EScript Compiler v" << vernum <<
"\n" << POL_COPYRIGHT <<
"\n\n";
909 int main(
int argc,
char* argv[] )
915 ECompileMain->
start( argc, argv );
bool dont_optimize_object_members
void dump(std::ostream &os)
bool timing_quiet_override
static void write_words(std::ostream &os)
const std::vector< std::string > & programArgs() const
bool OnlyCompileUpdatedScripts
void recurse_compile_inc(const std::string &basedir, std::vector< std::string > *files)
#define ESCRIPT_FILE_VER_CURRENT
int readargs(int argc, char **argv)
unsigned ScriptsWithCompileErrors
bool UpdateOnlyOnAutoCompile
void recurse_compile(const std::string &basedir, std::vector< std::string > *files)
void check_package_deps()
unsigned int GetFileTimestamp(const char *fname)
bool opt_generate_wordlist
void setIncludeCompileMode()
void start(int argc, char *argv[])
void force_backtrace(bool complete)
CompilerConfig compilercfg
bool DisplayUpToDateScripts
bool compile_file(const char *path)
void read_config_file(int argc, char *argv[])
bool IsDirectory(const char *dir)
void compile_file_wrapper(const char *path)
bool expect_compile_failure
bool GenerateDebugTextInfo
static void setVerbosityLevel(int vlev)
std::string PolScriptRoot
bool OptimizeObjectMembers
int write_dbg(const char *fname, bool generate_txtfile)
void enable_exit_signaller()
int forspec(const char *spec, void(*func)(const char *pathname))
void compile_inc(const char *path)
void writeIncludedFilenames(const char *fname) const
void parallel_compile(const std::vector< std::string > &files)
bool setting_value(const char *arg)
void RemoveFile(const std::string &fname)
bool GenerateDependencyInfo
struct Pol::ECompile::Summary summary
std::vector< std::string > PackageRoot
void push(const msg &msg)
simply fire and forget only the deconstructor ensures the msg to be finished
std::string normalized_dir_form(const std::string &istr)
bool FileExists(const char *filename)
bool run(int argc, char **argv)
int write(const char *fname)
bool AutoCompileByDefault
std::atomic< bool > exit_signalled
void Read(const std::string &path)
void load_packages(const std::string &basedir, bool quiet)
int compileFile(const char *fname)