示例#1
0
// GetOtherLibrary
//------------------------------------------------------------------------------
bool LinkerNode::GetOtherLibrary( NodeGraph & nodeGraph,
                                  const BFFIterator & iter,
                                  const Function * function,
                                  Dependencies & libs,
                                  const AString & path,
                                  const AString & lib,
                                  bool & found ) const
{
    found = false;

    AStackString<> potentialNodeName( path );
    if ( !potentialNodeName.IsEmpty() )
    {
        PathUtils::EnsureTrailingSlash( potentialNodeName );
    }
    potentialNodeName += lib;
    AStackString<> potentialNodeNameClean;
    NodeGraph::CleanPath( potentialNodeName, potentialNodeNameClean );

    // see if a node already exists
    Node * node = nodeGraph.FindNode( potentialNodeNameClean );
    if ( node )
    {
        // aliases not supported - must point to something that provides a file
        if ( node->IsAFile() == false )
        {
            Error::Error_1103_NotAFile( iter, function, ".LinkerOptions", potentialNodeNameClean, node->GetType() );
            return false;
        }

        // found existing node
        libs.Append( Dependency( node ) );
        found = true;
        return true; // no error
    }

    // see if the file exists on disk at this location
    if ( FileIO::FileExists( potentialNodeNameClean.Get() ) )
    {
        node = nodeGraph.CreateFileNode( potentialNodeNameClean );
        libs.Append( Dependency( node ) );
        found = true;
        FLOG_INFO( "Additional library '%s' assumed to be '%s'\n", lib.Get(), potentialNodeNameClean.Get() );
        return true; // no error
    }

    return true; // no error
}
示例#2
0
// GetObjectListNodes
//------------------------------------------------------------------------------
bool Function::GetObjectListNodes( const BFFIterator & iter,
                                   const Array< AString > & objectLists,
                                   const char * inputVarName,
                                   Dependencies & nodes ) const
{
    NodeGraph & ng = FBuild::Get().GetDependencyGraph();

	const AString * const  end = objectLists.End();
	for ( const AString * it = objectLists.Begin(); it != end; ++it )
	{
		const AString & objectList = *it;

		// get node for the dir we depend on
		Node * node = ng.FindNode( objectList );
		if ( node == nullptr )
		{
            Error::Error_1104_TargetNotDefined( iter, this, inputVarName, objectList );
            return false;
        }
		else if ( node->GetType() != Node::OBJECT_LIST_NODE )
		{
			Error::Error_1102_UnexpectedType( iter, this, inputVarName, node->GetName(), node->GetType(), Node::OBJECT_LIST_NODE );
			return false;
		}

		nodes.Append( Dependency( node ) );
	}
	return true;
}
示例#3
0
// DependOnNode
//------------------------------------------------------------------------------
/*static*/ bool LinkerNode::DependOnNode( NodeGraph & nodeGraph,
                                          const BFFIterator & iter,
                                          const Function * function,
                                          const AString & nodeName,
                                          Dependencies & nodes )
{
    // silently ignore empty nodes
    if ( nodeName.IsEmpty() )
    {
        return true;
    }

    Node * node = nodeGraph.FindNode( nodeName );

    // does it exist?
    if ( node != nullptr )
    {
        // process it
        return DependOnNode( iter, function, node, nodes );
    }

    // node not found - create a new FileNode, assuming we are
    // linking against an externally built library
    node = nodeGraph.CreateFileNode( nodeName );
    nodes.Append( Dependency( node ) );
    return true;
}
示例#4
0
// GetDirectoryNodeList
//------------------------------------------------------------------------------
bool Function::GetDirectoryListNodeList( const BFFIterator & iter,
										 const Array< AString > & paths,
										 const Array< AString > & excludePaths,
                                         const Array< AString > & filesToExclude,
										 bool recurse,
										 const Array< AString > * patterns,
										 const char * inputVarName,
										 Dependencies & nodes ) const
{
	NodeGraph & ng = FBuild::Get().GetDependencyGraph();

	// Handle special case of excluded files beginning with ../
	// Since they can be used seinsibly by matching just the end
	// of a path, assume they are relative to the working dir.
	// TODO:C Move this during bff parsing when everything is using reflection
	Array< AString > filesToExcludeCleaned( filesToExclude.GetSize(), true );
	for ( const AString& file : filesToExclude )
	{
		if ( file.BeginsWith( ".." ) )
		{
			AStackString<> fullPath;
			NodeGraph::CleanPath( file, fullPath );
			filesToExcludeCleaned.Append( fullPath );
		}
		else
		{
			filesToExcludeCleaned.Append( file );
		}
	}

	const AString * const  end = paths.End();
	for ( const AString * it = paths.Begin(); it != end; ++it )
	{
		const AString & path = *it;

		// get node for the dir we depend on
		AStackString<> name;
		DirectoryListNode::FormatName( path, patterns, recurse, excludePaths, filesToExcludeCleaned, name );
		Node * node = ng.FindNode( name );
		if ( node == nullptr )
		{
			node = ng.CreateDirectoryListNode( name,
											   path,
											   patterns,
											   recurse,
											   excludePaths, 
                                               filesToExcludeCleaned );
		}
		else if ( node->GetType() != Node::DIRECTORY_LIST_NODE )
		{
			Error::Error_1102_UnexpectedType( iter, this, inputVarName, node->GetName(), node->GetType(), Node::DIRECTORY_LIST_NODE );
			return false;
		}

		nodes.Append( Dependency( node ) );
	}
	return true;
}
示例#5
0
// GetFileNode
//------------------------------------------------------------------------------
bool Function::GetFileNode( NodeGraph & nodeGraph,
							const BFFIterator & iter,
                            const AString & file,
                            const char * inputVarName,
                            Dependencies & nodes ) const
{
	// get node for the dir we depend on
	Node * node = nodeGraph.FindNode( file );
	if ( node == nullptr )
	{
		node = nodeGraph.CreateFileNode( file );
    }
	else if ( node->IsAFile() == false )
	{
		Error::Error_1005_UnsupportedNodeType( iter, this, inputVarName, node->GetName(), node->GetType() );
		return false;
	}

	nodes.Append( Dependency( node ) );
	return true;
}
示例#6
0
// GetDirectoryNodeList
//------------------------------------------------------------------------------
bool Function::GetDirectoryListNodeList( const BFFIterator & iter,
										 const Array< AString > & paths,
										 const Array< AString > & excludePaths,
                                         const Array< AString > & filesToExclude,
										 bool recurse,
										 const AString & pattern,
										 const char * inputVarName,
										 Dependencies & nodes ) const
{
	NodeGraph & ng = FBuild::Get().GetDependencyGraph();

	const AString * const  end = paths.End();
	for ( const AString * it = paths.Begin(); it != end; ++it )
	{
		const AString & path = *it;

		// get node for the dir we depend on
		AStackString<> name;
		DirectoryListNode::FormatName( path, pattern, recurse, excludePaths, filesToExclude, name );
		Node * node = ng.FindNode( name );
		if ( node == nullptr )
		{
			node = ng.CreateDirectoryListNode( name,
											   path,
											   pattern,
											   recurse,
											   excludePaths, 
                                               filesToExclude );
		}
		else if ( node->GetType() != Node::DIRECTORY_LIST_NODE )
		{
			Error::Error_1102_UnexpectedType( iter, this, inputVarName, node->GetName(), node->GetType(), Node::DIRECTORY_LIST_NODE );
			return false;
		}

		nodes.Append( Dependency( node ) );
	}
	return true;
}
示例#7
0
// GetInputs
//------------------------------------------------------------------------------
bool FunctionObjectList::GetInputs( const BFFIterator & iter, Dependencies & inputs ) const
{
	NodeGraph & ng = FBuild::Get().GetDependencyGraph();

	// do we want to build files via a unity blob?
    Array< AString > inputUnities;
    if ( !GetStrings( iter, inputUnities, ".CompilerInputUnity", false ) ) // not required
	{
		return false;
	}
    for ( const auto& unity : inputUnities )
    {
        Node * n = ng.FindNode( unity );
		if ( n == nullptr )
		{
			Error::Error_1104_TargetNotDefined( iter, this, "CompilerInputUnity", unity );
			return false;
		}
		if ( n->GetType() != Node::UNITY_NODE )
		{
			Error::Error_1102_UnexpectedType( iter, this, "CompilerInputUnity", unity, n->GetType(), Node::UNITY_NODE );
			return false;
		}
		inputs.Append( Dependency( n ) );
    }

	// do we want to build a files in a directory?
	const BFFVariable * inputPath = BFFStackFrame::GetVar( ".CompilerInputPath" );
	if ( inputPath )
	{
		// get the optional pattern and recurse options related to InputPath
		Array< AString > patterns;
		if ( !GetStrings( iter, patterns, ".CompilerInputPattern", false ) )
		{
			return false; // GetString will have emitted an error
		}
		if ( patterns.IsEmpty() )
		{
			patterns.Append( AStackString<>( "*.cpp" ) );
		}

		// recursive?  default to true
		bool recurse = true;
		if ( !GetBool( iter, recurse, ".CompilerInputPathRecurse", true, false ) )
		{
			return false; // GetBool will have emitted an error
		}

		// Support an exclusion path
		Array< AString > excludePaths;
		if ( !GetFolderPaths( iter, excludePaths, ".CompilerInputExcludePath", false ) )
		{
			return false; // GetFolderPaths will have emitted an error
		}

        Array< AString > filesToExclude;
        if ( !GetStrings( iter, filesToExclude, ".CompilerInputExcludedFiles", false ) ) // not required
        {
            return false; // GetStrings will have emitted an error
        }
	    CleanFileNames( filesToExclude );

		// Input paths
		Array< AString > inputPaths;
		if ( !GetFolderPaths( iter, inputPaths, ".CompilerInputPath", false ) )
		{
			return false; // GetFolderPaths will have emitted an error
		}

		Dependencies dirNodes( inputPaths.GetSize() );
		if ( !GetDirectoryListNodeList( iter, inputPaths, excludePaths, filesToExclude, recurse, &patterns, "CompilerInputPath", dirNodes ) )
		{
			return false; // GetDirectoryListNodeList will have emitted an error
		}
		inputs.Append( dirNodes );
	}

	// do we want to build a specific list of files?
	if ( !GetNodeList( iter, ".CompilerInputFiles", inputs, false ) )
	{
		// helper will emit error
		return false;
	}

	return true;
}
示例#8
0
// 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;
}
示例#9
0
// 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;
}