Beispiel #1
0
        /// <summary>
        /// Link the resulting object files
        /// </summary>
        private async Task CheckLinkLibraryAsync(
            string path,
            Recipe recipe,
            string objectDirectory,
            string binaryDirectory,
            bool force)
        {
            var allFiles = new List <string>(recipe.Source);

            if (recipe.Type == RecipeType.Library)
            {
                allFiles.Add(recipe.Public);
            }

            // Convert all source files into objects
            var objectFiles = recipe.Source.Select(file => $"{objectDirectory.EnsureTrailingSlash()}{Path.GetFileNameWithoutExtension(file)}.{_compiler.ObjectFileExtension}").ToList();

            // Add the modules object too
            objectFiles.Add($"{objectDirectory.EnsureTrailingSlash()}{Path.GetFileNameWithoutExtension(recipe.Public)}.{_compiler.ObjectFileExtension}");

            var targetLibraryFile = Path.Combine(binaryDirectory, $"{recipe.Name}.{_compiler.StaticLibraryFileExtension}");

            if (force || BuildRequiredChecker.IsOutdated(path, targetLibraryFile, objectFiles))
            {
                Log.Info("Link library");
                var args = new LinkerArguments()
                {
                    Name            = recipe.Name,
                    RootDirectory   = path,
                    OutputDirectory = binaryDirectory,
                    SourceFiles     = objectFiles,
                };

                // Ensure the object directory exists
                var objectDirectry = Path.Combine(args.RootDirectory, binaryDirectory);
                if (!Directory.Exists(objectDirectry))
                {
                    Directory.CreateDirectory(objectDirectry);
                }

                // Link
                await _compiler.LinkLibraryAsync(args);
            }
            else
            {
                Log.Info("Static library up to date.");
            }
        }
Beispiel #2
0
        /// <summary>
        /// Compile the module file
        /// </summary>
        private async Task <bool> CheckCompileModuleAsync(
            string path,
            Recipe recipe,
            BuildState buildState,
            IList <string> includePaths,
            string objectDirectory,
            string binaryDirectory,
            bool force)
        {
            var  outputFilename = $"{Path.GetFileNameWithoutExtension(recipe.Public)}.{_compiler.ModuleFileExtension}";
            var  outputFile     = Path.Combine(objectDirectory, outputFilename);
            bool requiresBuild  = true;

            if (!force)
            {
                // Add all of the direct dependencies as module references
                var  modules     = new List <string>();
                var  defines     = new List <string>();
                bool isRecursive = false;
                await BuildDependencyModuleReferences(path, binaryDirectory, recipe, modules, defines, isRecursive);

                // The dependencies for this file are all of the direct module references
                var dependencies = new List <string>();
                dependencies.AddRange(modules);

                if (!BuildRequiredChecker.IsSourceFileOutdated(path, buildState, outputFile, recipe.Public, dependencies))
                {
                    // TODO : This is a hack. We need to actually look through all of the imports for the module file
                    Log.Info("Module file is up to date.");
                    requiresBuild = false;
                }
            }

            if (requiresBuild)
            {
                await CompileModuleAsync(
                    path,
                    recipe,
                    buildState,
                    includePaths,
                    objectDirectory,
                    binaryDirectory);
            }

            return(requiresBuild);
        }
Beispiel #3
0
        /// <summary>
        /// Compile the supporting source files
        /// </summary>
        private async Task <bool> CheckCompileSourceAsync(
            string path,
            Recipe recipe,
            BuildState buildState,
            IList <string> includePaths,
            string objectDirectory,
            string binaryDirectory,
            bool force)
        {
            var modules = new List <string>();
            var defines = new List <string>();

            defines.Add("SOUP_BUILD");
            if (recipe.Type == RecipeType.Library)
            {
                // Add a reference to our own modules interface definition
                var modulePath = Path.Combine(
                    objectDirectory,
                    $"{Path.GetFileNameWithoutExtension(recipe.Public)}.{_compiler.ModuleFileExtension}");
                modules.Add(modulePath);
                defines.Add(BuildRecipeNamespaceDefine(recipe));
            }

            // Add all of the direct dependencies as module references
            // and set their version defintions
            // TODO: MSVC requires all trasnsitive modules also
            bool isRecursive = _compiler.Name == "MSVC";

            await BuildDependencyModuleReferences(path, binaryDirectory, recipe, modules, defines, isRecursive);

            var source = new List <string>();

            // All files are dependent on the parent module and all referenced modules
            var sharedDependecies = new List <string>();

            sharedDependecies.AddRange(modules);

            // Check if the precompiled module should be compiled
            if (recipe.Type == RecipeType.Library)
            {
                // Add the precompile module to the list of shared dependencies
                // TODO: Could optimize this to not do file datetime checks over again
                var moduleFile = Path.Combine(path, objectDirectory, $"{Path.GetFileNameWithoutExtension(recipe.Public)}.{_compiler.ModuleFileExtension}");
                sharedDependecies.Add(moduleFile);

                var moduleOutputFile = Path.Combine(path, objectDirectory, $"{Path.GetFileNameWithoutExtension(recipe.Public)}.{_compiler.ObjectFileExtension}");
                if (force || BuildRequiredChecker.IsOutdated(path, moduleOutputFile, sharedDependecies))
                {
                    // HACK
                    if (_compiler.Name == "Clang")
                    {
                        source.Add(moduleFile);
                    }
                }
            }

            // Check if each source file is out of date and requires a rebuild
            foreach (var sourceFile in recipe.Source)
            {
                var outputFile = Path.Combine(objectDirectory, $"{Path.GetFileNameWithoutExtension(sourceFile)}.{_compiler.ObjectFileExtension}");
                if (force || BuildRequiredChecker.IsSourceFileOutdated(path, buildState, outputFile, sourceFile, sharedDependecies))
                {
                    source.Add(sourceFile);
                }
            }

            if (source.Count == 0)
            {
                Log.Info("All source is up to date.");
                return(false);
            }
            else
            {
                Log.Info("Compile Source");
                var args = new CompileArguments()
                {
                    Standard                = Compiler.LanguageStandard.Latest,
                    RootDirectory           = path,
                    OutputDirectory         = objectDirectory,
                    PreprocessorDefinitions = defines,
                    SourceFiles             = source,
                    IncludeDirectories      = includePaths,
                    Modules             = modules,
                    GenerateIncludeTree = true,
                };

                // Ensure the object directory exists
                var objectDirectry = Path.Combine(args.RootDirectory, objectDirectory);
                if (!Directory.Exists(objectDirectry))
                {
                    Directory.CreateDirectory(objectDirectry);
                }


                // Compile each file
                var result = await _compiler.CompileAsync(args);

                // Save the build state
                if (result.HeaderIncludeFiles != null)
                {
                    buildState.UpdateIncludeTree(result.HeaderIncludeFiles);
                }

                return(true);
            }
        }