From d77943f953a7c7bdc46c7ffa6815670b82e4f3b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Sat, 2 Dec 2017 18:38:34 +0100 Subject: [PATCH] Demo building - Build configurations --- Makefile | 1 + c-buildcfg.cc | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++ c-buildcfg.hh | 59 ++++++++++++++++ c-opcomp.hh | 4 +- m-builder.cc | 71 +++++++++++++++++-- 5 files changed, 319 insertions(+), 7 deletions(-) create mode 100644 c-buildcfg.cc create mode 100644 c-buildcfg.hh diff --git a/Makefile b/Makefile index e5c417e..ae437f8 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,7 @@ IMGUI = imgui.cpp imgui_draw.cpp COMMON = \ common.cc \ + c-buildcfg.cc \ c-camera.cc \ c-filewatcher.cc \ c-project.cc \ diff --git a/c-buildcfg.cc b/c-buildcfg.cc new file mode 100644 index 0000000..97b2a53 --- /dev/null +++ b/c-buildcfg.cc @@ -0,0 +1,191 @@ +#include "externals.hh" +#include "c-buildcfg.hh" + +#include +#include +#include +#include +#include + +using namespace ebcl; + +namespace { + +/*= SRD PARSER FOR BUILD CONFIGURATIONS ======================================*/ + +using SP_Table_ = T_SharedPtr< T_BuildConfigurations >; + +bool BCLStartConfig_( T_SRDParserData const& data ) +{ + *( data.targetData ) = T_BuildConfiguration{ }; + return true; +} + +bool BCLEndConfig_( T_SRDParserData const& data ) +{ + auto const& in{ *data.input }; + auto& table{ *( data.targetData->value< SP_Table_ >( ) ) }; + auto& bCfg{ data.currentData->value< T_BuildConfiguration >( ) }; + if ( !table.add( in[ 1 ].stringValue( ) , std::move( bCfg ) ) ) { + data.errors.add( "duplicate configuration" , in[ 1 ] ); + } + return true; +} + +/*----------------------------------------------------------------------------*/ + +bool BCLResolutions_( T_SRDParserData const& data ) +{ + auto const& in{ *data.input }; + auto& bCfg{ data.currentData->value< T_BuildConfiguration >( ) }; + const uint32_t nin{ in.size( ) }; + if ( nin == 2 && in[ 1 ].type( ) == E_SRDTokenType::WORD ) { + bCfg.resolutionChooser = true; + bCfg.resolutions.clear( ); + return true; + } + + for ( auto i = 1u ; i < nin ; i ++ ) { + auto const& l{ in[ i ].list( ) }; + const auto w{ l[ 0 ].longValue( ) }; + const auto h{ l[ 1 ].longValue( ) }; + bool fail{ false }; + + if ( w <= 0 || w >= 16384 ) { + fail = true; + data.errors.add( "invalid width" , l[ 0 ] ); + } + if ( h <= 0 || h >= 16384 ) { + fail = true; + data.errors.add( "invalid height" , l[ 1 ] ); + } + if ( fail ) { + continue; + } + + const auto res{ std::make_pair< uint32_t , uint32_t >( w , h ) }; + if ( bCfg.resolutions.contains( res ) ) { + data.errors.add( InPlace( ) , + "duplicate resolution" , + in[ i ].location( ) , + E_SRDErrorType::WARNING ); + } else { + bCfg.resolutions.add( res ); + } + } + + return true; +} + +/*----------------------------------------------------------------------------*/ + +T_SRDParserConfig BCLInitDefinitions_( ) noexcept +{ + using namespace ebcl::SRD; + T_SRDParserDefs defs{ "default" }; + defs.enumeration( "on-off" ) << "off" << "on"; + defs << OnStart( []( T_SRDParserData const& data ) -> bool { + *( data.currentData ) = NewShared< T_BuildConfigurations >( ); + return true; + } ); + + defs.context( "default" ) + << ( Rule( ) << "cfg" << Text( ) << EnterContext( "config" ) + << OnEnter( BCLStartConfig_ ) + << OnExit( BCLEndConfig_ ) ) + ; + + defs.context( "config" ) + << ( Rule( ) << "resolutions" + << ( Alt( ) << "chooser" + << ( AtLeast( 1 ) << ( List( ) << Int32( ) << Int32( ) ) ) ) + << BCLResolutions_ ) + << ( Rule( ) << "optimizer" << "off" ) + << ( Rule( ) << "optimizer" << "on" << EnterContext( "optim" ) ) + ; + + defs.context( "optim" ) + << ( Rule( ) << "constant-folding" << "off" + << []( T_SRDParserData const& d ) -> bool { + auto& bCfg{ d.currentData->value< T_BuildConfiguration >( ) }; + bCfg.constantFolding = false; + return true; + } ) + << ( Rule( ) << "constant-folding" << "on" << EnterContext( "opt-cf" ) + << []( T_SRDParserData const& d ) -> bool { + auto& bCfg{ d.currentData->value< T_BuildConfiguration >( ) }; + bCfg.constantFolding = true; + return true; + } ) + << ( Rule( ) << "dead-code-elimination" << Enum( "on-off" ) + << []( T_SRDParserData const& d ) -> bool { + auto& bCfg{ d.currentData->value< T_BuildConfiguration >( ) }; + bCfg.deadCodeElimination = true; + return true; + } ) + ; + + defs.context( "opt-cf" ) + << ( Rule( ) << "fixed-resolution" << Enum( "on-off" ) + << []( T_SRDParserData const& d ) -> bool { + auto& bCfg{ d.currentData->value< T_BuildConfiguration >( ) }; + bCfg.cfFixedSize = true; + return true; + } ) + << ( Rule( ) << "inputs" << Enum( "on-off" ) + << []( T_SRDParserData const& d ) -> bool { + auto& bCfg{ d.currentData->value< T_BuildConfiguration >( ) }; + bCfg.cfInputs = true; + return true; + } ) + ; + + return T_SRDParserConfig{ defs }; +} + + +/*= BUILD CONFIGURATIONS LOADER ==============================================*/ + +struct T_BCLImpl_ +{ + T_SRDParserConfig pConfig; + + T_BCLImpl_( ) noexcept; + + T_BuildConfigurations load( T_String const& path ); +}; + +/*----------------------------------------------------------------------------*/ + +T_BCLImpl_::T_BCLImpl_( ) noexcept + : pConfig{ BCLInitDefinitions_( ) } +{ } + +T_BuildConfigurations T_BCLImpl_::load( + T_String const& path ) +{ + // TODO: keep errors so we get warnings/notes too + T_SRDParser parser{ pConfig }; + T_SRDTextReader srdReader{ parser }; + + T_File input{ path , E_FileMode::READ_ONLY }; + T_FileInputStream fis{ input }; + srdReader.read( path , fis ); + + return std::move( *parser.getData< T_SharedPtr< T_BuildConfigurations > >( ) ); +} + +} // namespace + +/*----------------------------------------------------------------------------*/ + +T_BuildConfigurationLoader::T_BuildConfigurationLoader( ) noexcept + : A_PrivateImplementation( new T_BCLImpl_( ) ) +{ } + + +T_BuildConfigurations T_BuildConfigurationLoader::load( + T_String const& path ) +{ + return p< T_BCLImpl_ >( ).load( path ); +} diff --git a/c-buildcfg.hh b/c-buildcfg.hh new file mode 100644 index 0000000..aa908e4 --- /dev/null +++ b/c-buildcfg.hh @@ -0,0 +1,59 @@ +#pragma once +#ifndef REAL_BUILD +# include "externals.hh" +#endif + + +/*= BUILD CONFIGURATIONS =====================================================*/ + +// Build configuration +struct T_BuildConfiguration +{ + // Targets ------------------------------------------------------------- + + // Resolutions + bool resolutionChooser{ true }; + T_Array< std::pair< uint32_t , uint32_t > > resolutions; + + // Enable optimizer? + bool optimize{ false }; + + // Constant folding ---------------------------------------------------- + + // Main toggle + bool constantFolding{ false }; + // Optimize $width and $height away if the size is fixed + bool cfFixedSize{ false }; + // Get rid of (get-input) for constant or undefined curves + bool cfInputs{ false }; + + // Dead code elimination ----------------------------------------------- + + bool deadCodeElimination{ false }; +}; + +// Table of avaiable build configurations +using T_BuildConfigurations = T_KeyValueTable< T_String , T_BuildConfiguration >; + +// Build configurations loader +struct T_BuildConfigurationLoader : public ebcl::A_PrivateImplementation +{ + T_BuildConfigurationLoader( ) noexcept; + + // Load build configurations from the specified path; may throw + // X_StreamError or X_SRDErrors + T_BuildConfigurations load( T_String const& path ); +}; + +/*----------------------------------------------------------------------------*/ + +// Logger +using F_OPGenLog = std::function< T_StringBuilder( ) >; +using F_OPLogger = std::function< void( F_OPGenLog , uint32_t ) >; + +// Runtime configuration (logger, etc.) +struct T_BuildRuntimeConfiguration +{ + F_OPLogger logger{ [](auto,auto){} }; +}; + diff --git a/c-opcomp.hh b/c-opcomp.hh index 69ae2b6..bf36a81 100644 --- a/c-opcomp.hh +++ b/c-opcomp.hh @@ -1,4 +1,5 @@ #pragma once +#include "c-buildcfg.hh" #include "c-filewatcher.hh" #include "c-opast.hh" #include "c-project.hh" @@ -7,9 +8,6 @@ /*= PARSER ===================================================================*/ -using F_OPGenLog = std::function< T_StringBuilder( ) >; -using F_OPLogger = std::function< void( F_OPGenLog , uint32_t ) >; - // Parser output. Consists in a root node as well as other details (table of // constants, data types, etc...) struct T_OpsParserOutput diff --git a/m-builder.cc b/m-builder.cc index bdddbfb..aef625b 100644 --- a/m-builder.cc +++ b/m-builder.cc @@ -44,7 +44,18 @@ void WriteSRDError( T_StringBuilder& sb , T_SRDError const& error ) { - sb << error.location( ) << " - " << error.error( ) << "\n"; + switch ( error.type( ) ) { + case E_SRDErrorType::ERROR: + sb << "[ERROR"; + break; + case E_SRDErrorType::WARNING: + sb << " [WARN"; + break; + case E_SRDErrorType::NOTE: + sb << " [NOTE"; + break; + } + sb << '(' << error.location( ) << ")] " << error.error( ) << '\n'; } @@ -57,6 +68,7 @@ int main( int argc , char** argv ) // Parse command line T_Optional< uint32_t > oLogLevel; T_String oSrcPath; + T_String oBuildCfg; int c; while ( ( c = getopt_long( argc , argv , "L:s:c:" , CmdLineOpts_ , nullptr ) ) != -1 ) { switch ( c ) { @@ -68,13 +80,17 @@ int main( int argc , char** argv ) case 's': if ( oSrcPath ) { fprintf( stderr , "Duplicate source path\n" ); - exit( EXIT_FAILURE ); + return EXIT_FAILURE; } oSrcPath = optarg; break; case 'c': - fprintf( stderr , "-c/--config option ignored for now\n" ); + if ( oSrcPath ) { + fprintf( stderr , "Duplicate build configuration\n" ); + return EXIT_FAILURE; + } + oBuildCfg = optarg; break; } @@ -88,9 +104,56 @@ int main( int argc , char** argv ) } auto sb{ func( ) }; sb << '\0'; - printf( "LOG{%d} %s\n" , level , sb.data( ) ); + printf( "(%d) %s\n" , level , sb.data( ) ); } }; + // Build configurations + const T_String bcfgFile( [&]() { + T_StringBuilder sb; + if ( oSrcPath ) { + sb << oSrcPath; + if ( !oSrcPath.endsWith( "/" ) ) { + sb << '/'; + } + } + sb << "build.srd"; + return T_String{ std::move( sb ) }; + }( ) ); + const T_BuildConfiguration cfg{ [&]() { + try { + T_BuildConfigurationLoader bcfgLoader; + T_BuildConfigurations cfs{ bcfgLoader.load( bcfgFile ) }; + if ( oBuildCfg && !cfs.contains( oBuildCfg ) ) { + fprintf( stderr , "===== BUILD CONFIGURATIONS\n" ); + fprintf( stderr , "Build configuration not found\n" ); + exit( EXIT_FAILURE ); + } + if ( oBuildCfg ) { + return *cfs.get( oBuildCfg ); + } + if ( cfs.size( ) ) { + return cfs[ 0 ]; + } + return T_BuildConfiguration{ }; + + } catch ( X_StreamError const& e ) { + fprintf( stderr , "===== BUILD CONFIGURATIONS\n" ); + PrintStreamError( "Could not open" , bcfgFile , e ); + exit( EXIT_FAILURE ); + + } catch ( X_SRDErrors const& e ) { + T_StringBuilder sb; + sb << "===== BUILD CONFIGURATIONS\n"; + const auto nErrors( e.errors.size( ) ); + for ( auto i = 0u ; i < nErrors ; i ++ ) { + WriteSRDError( sb , e.errors[ i ] ); + } + sb << '\0'; + fprintf( stderr , "%s" , sb.data( ) ); + exit( EXIT_FAILURE ); + } + } () }; + // Open file const T_String inputName( [&]() { T_StringBuilder sb;