Exemplo n.º 1
0
// Generate
//------------------------------------------------------------------------------
bool ToolManifest::Generate( const Node * mainExecutable, const Dependencies & dependencies )
{
	m_Files.Clear();
	m_TimeStamp = 0;
	m_Files.SetCapacity( 1 + dependencies.GetSize() );

	// unify "main executable" and "extra files"
	// (loads contents of file into memory, and creates hashes)
    if ( !AddFile( mainExecutable ) )
    {
        return false; // AddFile will have emitted error
    }
	for ( size_t i=0; i<dependencies.GetSize(); ++i )
	{
		const FileNode & n = *( dependencies[ i ].GetNode()->CastTo< FileNode >() );
		if ( !AddFile( &n ) )
		{
			return false; // AddFile will have emitted error
		}
	}

	// create a hash for the whole tool chain
	const size_t numFiles( m_Files.GetSize() );
	const size_t memSize( numFiles * sizeof( uint32_t ) * 2 );
	uint32_t * mem = (uint32_t *)ALLOC( memSize );
	uint32_t * pos = mem;
	for ( size_t i=0; i<numFiles; ++i )
	{
		const File & f = m_Files[ i ];

		// file contents
		*pos = f.m_Hash;
		++pos;

		// file name & sub-path (relative to remote folder)
		AStackString<> relativePath;
		GetRemoteFilePath( (uint32_t)i, relativePath, false ); // false = don't use full path
		*pos = xxHash::Calc32( relativePath );
		++pos;
	}
	m_ToolId = xxHash::Calc64( mem, memSize );
	FREE( mem );

	// update time stamp (most recent file in manifest)
	for ( size_t i=0; i<numFiles; ++i )
	{
		const File & f = m_Files[ i ];
		ASSERT( f.m_TimeStamp ); // should have had an error before if the file was missing
		m_TimeStamp = Math::Max( m_TimeStamp, f.m_TimeStamp );
	}

	return true;
}
Exemplo n.º 2
0
// GetNodeList
//------------------------------------------------------------------------------
bool Function::GetNodeList( NodeGraph & nodeGraph, const BFFIterator & iter, const char * propertyName, Dependencies & nodes, bool required,
							bool allowCopyDirNodes, bool allowUnityNodes, bool allowRemoveDirNodes ) const
{
	ASSERT( propertyName );

	const BFFVariable * var = BFFStackFrame::GetVar( propertyName );
	if ( !var )
	{
		// missing
		if ( required )
		{
			Error::Error_1101_MissingProperty( iter, this, AStackString<>( propertyName ) );
			return false; // required!
		}
		return true; // missing but not required
	}

	if ( var->IsArrayOfStrings() )
	{
		// an array of references
		const Array< AString > & nodeNames = var->GetArrayOfStrings();
		nodes.SetCapacity( nodes.GetSize() + nodeNames.GetSize() );
		for ( const AString & nodeName : nodeNames )
		{
			if ( nodeName.IsEmpty() )
			{
				Error::Error_1004_EmptyStringPropertyNotAllowed( iter, this, propertyName );
				return false;
			}

			if ( !GetNodeList( nodeGraph, iter, this, propertyName, nodeName, nodes, allowCopyDirNodes, allowUnityNodes, allowRemoveDirNodes ) )
			{
				// child func will have emitted error
				return false;
			}
		}
	}
	else if ( var->IsString() )
	{
		if ( var->GetString().IsEmpty() )
		{
			Error::Error_1004_EmptyStringPropertyNotAllowed( iter, this, propertyName );
			return false;
		}

		if ( !GetNodeList( nodeGraph, iter, this, propertyName, var->GetString(), nodes, allowCopyDirNodes, allowUnityNodes, allowRemoveDirNodes ) )
		{
			// child func will have emitted error
			return false;
		}
	}
	else
	{
		// unsupported type
		Error::Error_1050_PropertyMustBeOfType( iter, this, propertyName, var->GetType(), BFFVariable::VAR_STRING, BFFVariable::VAR_ARRAY_OF_STRINGS );
		return false;
	}

	return true;
}
Exemplo n.º 3
0
// CONSTRUCTOR
//------------------------------------------------------------------------------
LinkerNode::LinkerNode( const AString & linkerOutputName,
                         const Dependencies & inputLibraries,
                         const Dependencies & otherLibraries,
                         const AString & linkerType,
                         const AString & linker,
                         const AString & linkerArgs,
                         uint32_t flags,
                         const Dependencies & assemblyResources,
                         const AString & importLibName,
                         Node * linkerStampExe,
                         const AString & linkerStampExeArgs )
: FileNode( linkerOutputName, Node::FLAG_NONE )
, m_Flags( flags )
, m_AssemblyResources( assemblyResources )
, m_OtherLibraries( otherLibraries )
, m_ImportLibName( importLibName )
, m_LinkerStampExe( linkerStampExe )
, m_LinkerStampExeArgs( linkerStampExeArgs )
{
    m_LastBuildTimeMs = 20000;

    // presize vector
    size_t numStaticDeps = inputLibraries.GetSize() + assemblyResources.GetSize() + otherLibraries.GetSize();
    if ( linkerStampExe )
    {
        numStaticDeps++;
    }
    m_StaticDependencies.SetCapacity( numStaticDeps );

    // depend on everything we'll link together
    m_StaticDependencies.Append( inputLibraries );
    m_StaticDependencies.Append( assemblyResources );
    m_StaticDependencies.Append( otherLibraries );

    // manage optional LinkerStampExe
    if ( linkerStampExe )
    {
        m_StaticDependencies.Append( Dependency( linkerStampExe ) );
    }

    // store options we'll need to use dynamically
    m_LinkerType = linkerType;
    m_Linker = linker; // TODO:C This should be a node
    m_LinkerArgs = linkerArgs;
}
Exemplo n.º 4
0
// CONSTRUCTOR
//------------------------------------------------------------------------------
CSNode::CSNode( const AString & compilerOutput,
				const Dependencies & inputNodes,
				const AString & compiler,
				const AString & compilerArgs,
				const Dependencies & extraRefs )
: FileNode( compilerOutput, Node::FLAG_NONE )
, m_ExtraRefs( extraRefs )
{
	ASSERT( !inputNodes.IsEmpty() );

	m_StaticDependencies.SetCapacity( inputNodes.GetSize() + extraRefs.GetSize() );
	m_StaticDependencies.Append( inputNodes );
	m_StaticDependencies.Append( extraRefs );

	// store options we'll need to use when building
	m_CompilerPath = compiler; // TODO:C This should be a node we statically depend on
	m_CompilerArgs = compilerArgs;

	m_Type = CS_NODE;
	m_LastBuildTimeMs = 5000; // higher default than a file node
}
Exemplo n.º 5
0
// Commit
//------------------------------------------------------------------------------
/*virtual*/ bool FunctionCopy::Commit( NodeGraph & nodeGraph, const BFFIterator & funcStartIter ) const
{
    // make sure all required variables are defined
    Array< AString > sources( 16, true );
    const BFFVariable * dstFileV;
    if ( !GetStrings( funcStartIter, sources, ".Source", true ) ||
         !GetString( funcStartIter, dstFileV, ".Dest", true ) )
    {
        return false; // GetString will have emitted errors
    }

    // Optional
    AStackString<> sourceBasePath;
    if ( !GetString( funcStartIter, sourceBasePath, ".SourceBasePath", false ) )
    {
        return false; // GetString will have emitted errors
    }

    // Canonicalize the SourceBasePath
    if ( !sourceBasePath.IsEmpty() )
    {
        AStackString<> cleanValue;
        NodeGraph::CleanPath( sourceBasePath, cleanValue );
        PathUtils::EnsureTrailingSlash( cleanValue );
        sourceBasePath = cleanValue;
    }

    // check sources are not paths
    {
        const AString * const end = sources.End();
        for ( const AString * it = sources.Begin(); it != end; ++it )
        {
            const AString & srcFile( *it );

            // source must be a file, not a  path
            if ( PathUtils::IsFolderPath( srcFile ) )
            {
                Error::Error_1105_PathNotAllowed( funcStartIter, this, ".Source", srcFile );
                return false;
            }
        }
    }

    // Pre-build dependencies
    Dependencies preBuildDependencies;
    if ( !GetNodeList( nodeGraph, funcStartIter, ".PreBuildDependencies", preBuildDependencies, false ) )
    {
        return false; // GetNodeList will have emitted an error
    }
    Array< AString > preBuildDependencyNames( preBuildDependencies.GetSize(), false );
    for ( const auto & dep : preBuildDependencies )
    {
        preBuildDependencyNames.Append( dep.GetNode()->GetName() );
    }

    // get source node
    Array< Node * > srcNodes;
    {
        const AString * const end = sources.End();
        for ( const AString * it = sources.Begin(); it != end; ++it )
        {

            Node * srcNode = nodeGraph.FindNode( *it );
            if ( srcNode )
            {
                if ( GetSourceNodes( funcStartIter, srcNode, srcNodes ) == false )
                {
                    return false;
                }
            }
            else
            {
                // source file not defined by use - assume an external file
                srcNodes.Append( nodeGraph.CreateFileNode( *it ) );
            }
        }
    }

    AStackString<> dstFile;
    NodeGraph::CleanPath( dstFileV->GetString(), dstFile );
    const bool dstIsFolderPath = PathUtils::IsFolderPath( dstFile );

    // make all the nodes for copies
    Dependencies copyNodes( srcNodes.GetSize(), false );
    for ( const Node * srcNode : srcNodes )
    {
        AStackString<> dst( dstFile );

        // dest can be a file OR a path.  If it's a path, use the source filename part
        if ( dstIsFolderPath )
        {
            // find filename part of source
            const AString & srcName = srcNode->GetName();

            // If the sourceBasePath is specified (and valid) use the name relative to that
            if ( !sourceBasePath.IsEmpty() && PathUtils::PathBeginsWith( srcName, sourceBasePath ) )
            {
                // Use everything relative to the SourceBasePath
                dst += srcName.Get() + sourceBasePath.GetLength();
            }
            else
            {
                // Use just the file name
                const char * lastSlash = srcName.FindLast( NATIVE_SLASH );
                dst += lastSlash ? ( lastSlash + 1 )    // append filename part if found
                                     : srcName.Get();   // otherwise append whole thing
            }
        }

        // check node doesn't already exist
        if ( nodeGraph.FindNode( dst ) )
        {
            // TODO:C could have a specific error for multiple sources with only 1 output
            // to differentiate from two rules creating the same dst target
            Error::Error_1100_AlreadyDefined( funcStartIter, this, dst );
            return false;
        }

        // create our node
        CopyFileNode * copyFileNode = nodeGraph.CreateCopyFileNode( dst );
        copyFileNode->m_Source = srcNode->GetName();
        copyFileNode->m_PreBuildDependencyNames = preBuildDependencyNames;
        if ( !copyFileNode->Initialize( nodeGraph, funcStartIter, this ) )
        {
            return false; // Initialize will have emitted an error
        }

        copyNodes.Append( Dependency( copyFileNode ) );
    }

    // handle alias creation
    return ProcessAlias( nodeGraph, funcStartIter, copyNodes );
}