예제 #1
0
파일: CSNode.cpp 프로젝트: ClxS/fastbuild
// DoDynamicDependencies
//------------------------------------------------------------------------------
/*virtual*/ bool CSNode::DoDynamicDependencies( bool UNUSED( forceClean ) )
{
	ASSERT( m_DynamicDependencies.GetSize() == 0 );

	NodeGraph & ng = FBuild::Get().GetDependencyGraph();

	// preallocate a reasonable amount of space
	m_DynamicDependencies.SetCapacity( m_StaticDependencies.GetSize() );

	// convert static deps to dynamic deps
	// (ignore the extra refs here)
	size_t numDeps = m_StaticDependencies.GetSize() - m_ExtraRefs.GetSize();
	for ( size_t i=0; i<numDeps; ++i ) 
	{
		Node * n = m_StaticDependencies[ i ].GetNode();

		if ( n->IsAFile() )
		{
			m_DynamicDependencies.Append( Dependency( n ) );
			continue;
		}

		if ( n->GetType() == Node::DIRECTORY_LIST_NODE )
		{
			// get the list of files
			DirectoryListNode * dln = n->CastTo< DirectoryListNode >();
			const Array< FileIO::FileInfo > & files = dln->GetFiles();
			m_DynamicDependencies.SetCapacity( m_DynamicDependencies.GetSize() + files.GetSize() );
			for ( Array< FileIO::FileInfo >::Iter fIt = files.Begin();
					fIt != files.End();
					fIt++ )
			{
				// Create the file node (or find an existing one)
				Node * sn = ng.FindNode( fIt->m_Name );
				if ( sn == nullptr )
				{
					sn = ng.CreateFileNode( fIt->m_Name );
				}
				else if ( sn->IsAFile() == false )
				{
					FLOG_ERROR( "CSAssembly() .CompilerInputFile '%s' is not a FileNode (type: %s)", n->GetName().Get(), n->GetTypeName() );
					return false;
				}

				m_DynamicDependencies.Append( Dependency( sn ) );
			}
			continue;
		}

		FLOG_ERROR( "'%s' is not a supported node type (type: %s)", n->GetName().Get(), n->GetTypeName() );
		return false;
	}

	return true;
}
예제 #2
0
// DoBuild
//------------------------------------------------------------------------------
/*virtual*/ Node::BuildResult RemoveDirNode::DoBuild( Job * UNUSED( job ) )
{
    ASSERT( !m_StaticDependencies.IsEmpty() );

    m_Stamp = 0; // Trigger DoBuild() every time

    // Iterate all the DirectoryListNodes
    const Dependency * const depEnd = m_StaticDependencies.End();
    for ( const Dependency * dep = m_StaticDependencies.Begin();
          dep != depEnd;
          ++dep )
    {
        // Grab the files
        DirectoryListNode * dln = dep->GetNode()->CastTo< DirectoryListNode >();
        const Array< FileIO::FileInfo > & files = dln->GetFiles();
        const FileIO::FileInfo * const fEnd = files.End();
        for ( const FileIO::FileInfo * fIt = files.Begin();
              fIt != fEnd;
              ++fIt )
        {
            // source file (full path)
            const AString & srcFile = fIt->m_Name;

            // remove the file
            if ( FileIO::FileDelete( srcFile.Get() ) == false )
            {
                FLOG_ERROR( "Remove failed (error %i) '%s'", Env::GetLastErr(), srcFile.Get() );
                return NODE_RESULT_FAILED; // remove failed
            }

            // we combine everything into one string to ensure it is contiguous in
            // the output
            AStackString<> output;
            output += "Remove: ";
            output += srcFile;
            output += '\n';
            FLOG_BUILD_DIRECT( output.Get() );
        }
    }

    return NODE_RESULT_OK;
}
예제 #3
0
// GatherDynamicDependencies
//------------------------------------------------------------------------------
/*virtual*/ bool ObjectListNode::GatherDynamicDependencies( NodeGraph & nodeGraph, bool forceClean )
{
    (void)forceClean; // dynamic deps are always re-added here, so this is meaningless

    // clear dynamic deps from previous passes
    m_DynamicDependencies.Clear();

#if defined( __WINDOWS__ )
    // On Windows, with MSVC we compile a cpp file to generate the PCH
    // Filter here to ensure that doesn't get compiled twice
    Node * pchCPP = nullptr;
    if ( m_PrecompiledHeader && m_PrecompiledHeader->IsMSVC() )
    {
        pchCPP = m_PrecompiledHeader->GetPrecompiledHeaderCPPFile();
    }
#endif

    // if we depend on any directory lists, we need to use them to get our files
    for ( Dependencies::Iter i = m_StaticDependencies.Begin();
            i != m_StaticDependencies.End();
            i++ )
    {
        // is this a dir list?
        if ( i->GetNode()->GetType() == Node::DIRECTORY_LIST_NODE )
        {
            // get the list of files
            DirectoryListNode * dln = i->GetNode()->CastTo< DirectoryListNode >();
            const Array< FileIO::FileInfo > & files = dln->GetFiles();
            m_DynamicDependencies.SetCapacity( m_DynamicDependencies.GetSize() + files.GetSize() );
            for ( Array< FileIO::FileInfo >::Iter fIt = files.Begin();
                    fIt != files.End();
                    fIt++ )
            {
                // Create the file node (or find an existing one)
                Node * n = nodeGraph.FindNode( fIt->m_Name );
                if ( n == nullptr )
                {
                    n = nodeGraph.CreateFileNode( fIt->m_Name );
                }
                else if ( n->IsAFile() == false )
                {
                    FLOG_ERROR( "Library() .CompilerInputFile '%s' is not a FileNode (type: %s)", n->GetName().Get(), n->GetTypeName() );
                    return false;
                }

                // ignore the precompiled header as a convenience for the user
                // so they don't have to exclude it explicitly
#if defined( __WINDOWS__ )
                if ( n == pchCPP )
                {
                    continue;
                }
#endif

                // create the object that will compile the above file
                if ( CreateDynamicObjectNode( nodeGraph, n, dln->GetPath() ) == false )
                {
                    return false; // CreateDynamicObjectNode will have emitted error
                }
            }
        }
        else if ( i->GetNode()->GetType() == Node::UNITY_NODE )
        {
            // get the dir list from the unity node
            UnityNode * un = i->GetNode()->CastTo< UnityNode >();

            // unity files
            const Array< AString > & unityFiles = un->GetUnityFileNames();
            for ( Array< AString >::Iter it = unityFiles.Begin();
                    it != unityFiles.End();
                    it++ )
            {
                Node * n = nodeGraph.FindNode( *it );
                if ( n == nullptr )
                {
                    n = nodeGraph.CreateFileNode( *it );
                }
                else if ( n->IsAFile() == false )
                {
                    FLOG_ERROR( "Library() .CompilerInputUnity '%s' is not a FileNode (type: %s)", n->GetName().Get(), n->GetTypeName() );
                    return false;
                }

                // create the object that will compile the above file
                if ( CreateDynamicObjectNode( nodeGraph, n, AString::GetEmpty(), true ) == false )
                {
                    return false; // CreateDynamicObjectNode will have emitted error
                }
            }

            // files from unity to build individually
            const Array< UnityNode::FileAndOrigin > & isolatedFiles = un->GetIsolatedFileNames();
            for ( Array< UnityNode::FileAndOrigin >::Iter it = isolatedFiles.Begin();
                    it != isolatedFiles.End();
                    it++ )
            {
                Node * n = nodeGraph.FindNode( it->GetName() );
                if ( n == nullptr )
                {
                    n = nodeGraph.CreateFileNode( it->GetName() );
                }
                else if ( n->IsAFile() == false )
                {
                    FLOG_ERROR( "Library() Isolated '%s' is not a FileNode (type: %s)", n->GetName().Get(), n->GetTypeName() );
                    return false;
                }

                // create the object that will compile the above file
                const AString & baseDir = it->GetDirListOrigin() ? it->GetDirListOrigin()->GetPath() : AString::GetEmpty();
                if ( CreateDynamicObjectNode( nodeGraph, n, baseDir, false, true ) == false )
                {
                    return false; // CreateDynamicObjectNode will have emitted error
                }
            }
        }
        else if ( i->GetNode()->IsAFile() )
        {
            // a single file, create the object that will compile it
            if ( CreateDynamicObjectNode( nodeGraph, i->GetNode(), AString::GetEmpty() ) == false )
            {
                return false; // CreateDynamicObjectNode will have emitted error
            }
        }
        else
        {
            ASSERT( false ); // unexpected node type
        }
    }

    // If we have a precompiled header, add that to our dynamic deps so that
    // any symbols in the PCH's .obj are also linked, when either:
    // a) we are a static library
    // b) a DLL or executable links our .obj files
    if ( m_PrecompiledHeader )
    {
        m_DynamicDependencies.Append( Dependency( m_PrecompiledHeader ) );
    }

    return true;
}
예제 #4
0
// DoDynamicDependencies
//------------------------------------------------------------------------------
/*virtual*/ bool CopyDirNode::DoDynamicDependencies( NodeGraph & nodeGraph, bool forceClean )
{
    (void)forceClean; // dynamic deps are always re-added here, so this is meaningless

    ASSERT( !m_StaticDependencies.IsEmpty() );

    Array< AString > preBuildDependencyNames( m_PreBuildDependencies.GetSize(), false );
    for ( const auto & dep : m_PreBuildDependencies )
    {
        preBuildDependencyNames.Append( dep.GetNode()->GetName() );
    }

    // Iterate all the DirectoryListNodes
    const Dependency * const depEnd = m_StaticDependencies.End();
    for ( const Dependency * dep = m_StaticDependencies.Begin();
          dep != depEnd;
          ++dep )
    {
        // Grab the files
        DirectoryListNode * dln = dep->GetNode()->CastTo< DirectoryListNode >();
        const Array< FileIO::FileInfo > & files = dln->GetFiles();
        const FileIO::FileInfo * const fEnd = files.End();
        for ( const FileIO::FileInfo * fIt = files.Begin();
              fIt != fEnd;
              ++fIt )
        {
            // Create a CopyFileNode for each dynamically discovered file

            // source file (full path)
            const AString & srcFile = fIt->m_Name;

            // source file (relative to base path)
            const AStackString<> srcFileRel( srcFile.Get() + dln->GetPath().GetLength() );

            // source file (as a node)
            Node * srcFileNode = nodeGraph.FindNode( srcFile );
            if ( srcFileNode == nullptr )
            {
                srcFileNode = nodeGraph.CreateFileNode( srcFile );
            }
            else if ( srcFileNode->IsAFile() == false )
            {
                FLOG_ERROR( "CopyDir() Node '%s' is not a FileNode (type: %s)", srcFile.Get(), srcFileNode->GetTypeName() );
                return false;
            }

            // generate dest file name
            const AStackString<> dstFile( m_DestPath );
            (AString &)dstFile += (AString &)srcFileRel;

            // make sure dest doesn't already exist
            Node * n = nodeGraph.FindNode( dstFile );
            if ( n == nullptr )
            {
                CopyFileNode * copyFileNode = nodeGraph.CreateCopyFileNode( dstFile );
                copyFileNode->m_Source = srcFileNode->GetName();
                copyFileNode->m_PreBuildDependencyNames = preBuildDependencyNames; // inherit PreBuildDependencies
                BFFIterator iter;
                if ( !copyFileNode->Initialize( nodeGraph, iter, nullptr ) )
                {
                    return false; // Initialize will have emitted an error
                }
                n = copyFileNode;
            }
            else if ( n->GetType() != Node::COPY_FILE_NODE )
            {
                FLOG_ERROR( "Node '%s' is not a CopyFileNode (type: %s)", n->GetName().Get(), n->GetTypeName() );
                return false;
            }
            else
            {
                CopyFileNode * cn = n->CastTo< CopyFileNode >();
                if ( srcFileNode != cn->GetSourceNode() )
                {
                    FLOG_ERROR( "Conflicting objects found during CopyDir:\n"
                                " File A: %s\n"
                                " File B: %s\n"
                                " Both copy to: %s\n",
                                srcFile.Get(),
                                cn->GetSourceNode()->GetName().Get(),
                                dstFile.Get() );
                    return false;
                }
            }

            m_DynamicDependencies.Append( Dependency( n ) );
        }
    }
    return true;
}