// PopulateStringHelper //------------------------------------------------------------------------------ bool Function::PopulateStringHelper( const BFFIterator & iter, const Meta_Path * pathMD, const Meta_File * fileMD, const BFFVariable * variable, const AString & string, Array< AString > & outStrings ) const { // Full paths to files can support aliases if ( fileMD && ( !fileMD->IsRelative() ) ) { // Is it an Alias? Node * node = FBuild::Get().GetDependencyGraph().FindNode( string ); if ( node && ( node->GetType() == Node::ALIAS_NODE ) ) { AliasNode * aliasNode = node->CastTo< AliasNode >(); for ( const auto& aliasedNode : aliasNode->GetAliasedNodes() ) { if ( !PopulateStringHelper( iter, pathMD, fileMD, variable, aliasedNode.GetNode()->GetName(), outStrings ) ) { return false; // PopulateStringHelper will have emitted an error } } return true; } // Not an alias - fall through to normal handling } AStackString<> stringToFix( string ); if ( !PopulatePathAndFileHelper( iter, pathMD, fileMD, variable->GetName(), stringToFix ) ) { return false; // PopulatePathAndFileHelper will have emitted an error } outStrings.Append( stringToFix ); return true; }
// GetCompilerNode //------------------------------------------------------------------------------ bool FunctionObjectList::GetCompilerNode( const BFFIterator & iter, const AString & compiler, CompilerNode * & compilerNode ) const { NodeGraph & ng = FBuild::Get().GetDependencyGraph(); Node * cn = ng.FindNode( compiler ); compilerNode = nullptr; if ( cn != nullptr ) { if ( cn->GetType() == Node::ALIAS_NODE ) { AliasNode * an = cn->CastTo< AliasNode >(); cn = an->GetAliasedNodes()[ 0 ].GetNode(); } if ( cn->GetType() != Node::COMPILER_NODE ) { Error::Error_1102_UnexpectedType( iter, this, "Compiler", cn->GetName(), cn->GetType(), Node::COMPILER_NODE ); return false; } compilerNode = cn->CastTo< CompilerNode >(); } else { // create a compiler node - don't allow distribution // (only explicitly defined compiler nodes can be distributed) #ifdef USE_NODE_REFLECTION compilerNode = ng.CreateCompilerNode( compiler ); VERIFY( compilerNode->GetReflectionInfoV()->SetProperty( compilerNode, "AllowDistribution", false ) ); #else const bool allowDistribution = false; compilerNode = ng.CreateCompilerNode( compiler, Dependencies( 0, false ), allowDistribution ); #endif } return true; }
// GetSourceNodes //------------------------------------------------------------------------------ bool FunctionCopy::GetSourceNodes( const BFFIterator & iter, Node * node, Array< Node * > & nodes ) const { if ( node->GetType() == Node::ALIAS_NODE ) { // resolve aliases to real nodes AliasNode * aliasNode = node->CastTo< AliasNode >(); const Dependencies & aliasedNodes = aliasNode->GetAliasedNodes(); const Dependency * const end = aliasedNodes.End(); for ( const Dependency * it = aliasedNodes.Begin(); it != end; ++it ) { if ( !GetSourceNodes( iter, it->GetNode(), nodes ) ) { return false; } } return true; } else if ( node->IsAFile() ) { // anything that results in a file is ok nodes.Append( node ); return true; } // something we don't know how to handle Error::Error_1005_UnsupportedNodeType( iter, this, ".Source", node->GetName(), node->GetType() ); return false; }
// GetCompilerNode //------------------------------------------------------------------------------ bool FunctionObjectList::GetCompilerNode( NodeGraph & nodeGraph, const BFFIterator & iter, const AString & compiler, CompilerNode * & compilerNode ) const { Node * cn = nodeGraph.FindNode( compiler ); compilerNode = nullptr; if ( cn != nullptr ) { if ( cn->GetType() == Node::ALIAS_NODE ) { AliasNode * an = cn->CastTo< AliasNode >(); cn = an->GetAliasedNodes()[ 0 ].GetNode(); } if ( cn->GetType() != Node::COMPILER_NODE ) { Error::Error_1102_UnexpectedType( iter, this, "Compiler", cn->GetName(), cn->GetType(), Node::COMPILER_NODE ); return false; } compilerNode = cn->CastTo< CompilerNode >(); } else { // create a compiler node - don't allow distribution // (only explicitly defined compiler nodes can be distributed) AStackString<> compilerClean; NodeGraph::CleanPath( compiler, compilerClean ); compilerNode = nodeGraph.CreateCompilerNode( compilerClean ); VERIFY( compilerNode->GetReflectionInfoV()->SetProperty( compilerNode, "AllowDistribution", false ) ); } return true; }
// Commit //------------------------------------------------------------------------------ /*virtual*/ bool FunctionAlias::Commit( NodeGraph & nodeGraph, const BFFIterator & funcStartIter ) const { if ( nodeGraph.FindNode( m_AliasForFunction ) ) { Error::Error_1100_AlreadyDefined( funcStartIter, this, m_AliasForFunction ); return false; } AliasNode * aliasNode = nodeGraph.CreateAliasNode( m_AliasForFunction ); if ( !PopulateProperties( nodeGraph, funcStartIter, aliasNode ) ) { return false; } return aliasNode->Initialize( nodeGraph, funcStartIter, this ); }
// Commit //------------------------------------------------------------------------------ /*virtual*/ bool FunctionAlias::Commit( const BFFIterator & funcStartIter ) const { NodeGraph & ng = FBuild::Get().GetDependencyGraph(); if ( ng.FindNode( m_AliasForFunction ) ) { Error::Error_1100_AlreadyDefined( funcStartIter, this, m_AliasForFunction ); return false; } AliasNode * aliasNode = ng.CreateAliasNode( m_AliasForFunction ); if ( !PopulateProperties( funcStartIter, aliasNode ) ) { return false; } return aliasNode->Initialize( funcStartIter, this ); }
// Load //------------------------------------------------------------------------------ /*static*/ Node * AliasNode::Load( IOStream & stream ) { #ifdef USE_NODE_REFLECTION NODE_LOAD( AStackString<>, name ); NodeGraph & ng = FBuild::Get().GetDependencyGraph(); AliasNode * an = ng.CreateAliasNode( name ); if ( an->Deserialize( stream ) == false ) { return nullptr; } return an; #else NODE_LOAD( AStackString<>, name ); NODE_LOAD_DEPS( 0, targets ); NodeGraph & ng = FBuild::Get().GetDependencyGraph(); return ng.CreateAliasNode( name, targets ); #endif }
// GetNodeListRecurse //------------------------------------------------------------------------------ bool Function::GetNodeListRecurse( const BFFIterator & iter, const char * name, Dependencies & nodes, const AString & nodeName, bool allowCopyDirNodes, bool allowUnityNodes, bool allowRemoveDirNodes ) const { NodeGraph & ng = FBuild::Get().GetDependencyGraph(); // get node Node * n = ng.FindNode( nodeName ); if ( n == nullptr ) { // not found - create a new file node n = ng.CreateFileNode( nodeName ); nodes.Append( Dependency( n ) ); return true; } // found - is it a file? if ( n->IsAFile() ) { // found file - just use as is nodes.Append( Dependency( n ) ); return true; } // found - is it an ObjectList? if ( n->GetType() == Node::OBJECT_LIST_NODE ) { // use as-is nodes.Append( Dependency( n ) ); return true; } // extra types if ( allowCopyDirNodes ) { // found - is it an ObjectList? if ( n->GetType() == Node::COPY_DIR_NODE ) { // use as-is nodes.Append( Dependency( n ) ); return true; } } if ( allowRemoveDirNodes ) { // found - is it a RemoveDirNode? if ( n->GetType() == Node::REMOVE_DIR_NODE ) { // use as-is nodes.Append( Dependency( n ) ); return true; } } if ( allowUnityNodes ) { // found - is it an ObjectList? if ( n->GetType() == Node::UNITY_NODE ) { // use as-is nodes.Append( Dependency( n ) ); return true; } } // found - is it a group? if ( n->GetType() == Node::ALIAS_NODE ) { AliasNode * an = n->CastTo< AliasNode >(); const Dependencies & aNodes = an->GetAliasedNodes(); for ( const Dependency * it = aNodes.Begin(); it != aNodes.End(); ++it ) { // TODO:C by passing as string we'll be looking up again for no reason const AString & subName = it->GetNode()->GetName(); if ( !GetNodeListRecurse( iter, name, nodes, subName, allowCopyDirNodes, allowUnityNodes, allowRemoveDirNodes ) ) { return false; } } return true; } // don't know how to handle this type of node Error::Error_1005_UnsupportedNodeType( iter, this, name, n->GetName(), n->GetType() ); return false; }
// DependOnNode //------------------------------------------------------------------------------ /*static*/ bool LinkerNode::DependOnNode( const BFFIterator & iter, const Function * function, Node * node, Dependencies & nodes ) { ASSERT( node ); // a previously declared library? if ( node->GetType() == Node::LIBRARY_NODE ) { // can link directly to it nodes.Append( Dependency( node ) ); return true; } // a previously declared object list? if ( node->GetType() == Node::OBJECT_LIST_NODE ) { // can link directly to it nodes.Append( Dependency( node ) ); return true; } // a dll? if ( node->GetType() == Node::DLL_NODE ) { // TODO:B Depend on import lib nodes.Append( Dependency( node, true ) ); // NOTE: Weak dependency return true; } // a previously declared external file? if ( node->GetType() == Node::FILE_NODE ) { // can link directy against it nodes.Append( Dependency( node ) ); return true; } // a file copy? if ( node->GetType() == Node::COPY_FILE_NODE ) { // depend on copy - will use input at build time nodes.Append( Dependency( node ) ); return true; } // an external executable? if ( node->GetType() == Node::EXEC_NODE ) { // depend on ndoe - will use exe output at build time nodes.Append( Dependency( node ) ); return true; } // a group (alias)? if ( node->GetType() == Node::ALIAS_NODE ) { // handle all targets in alias AliasNode * an = node->CastTo< AliasNode >(); const Dependencies & aliasNodeList = an->GetAliasedNodes(); const Dependencies::Iter end = aliasNodeList.End(); for ( Dependencies::Iter it = aliasNodeList.Begin(); it != end; ++it ) { if ( DependOnNode( iter, function, it->GetNode(), nodes ) == false ) { return false; // something went wrong lower down } } return true; // all nodes in group handled ok } // don't know how to handle this type of node Error::Error_1005_UnsupportedNodeType( iter, function, "Libraries", node->GetName(), node->GetType() ); return false; }