diff --git a/CMakeLists.txt b/CMakeLists.txt index 20a050f..24bfdb2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ set(CMAKE_CXX_STANDARD 11) option(RUNCPP2_UPDATE_DEFAULT_YAMLS "Update default yaml files" OFF) -set(RUNCPP2_CONFIG_VERSION "1" CACHE STRING "Default Config Version") +set(RUNCPP2_CONFIG_VERSION "2") if (CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) option(RUNCPP2_WARNINGS_AS_ERRORS "Treat warnings as errors" ON) diff --git a/DefaultYAMLs/Default/g++.yaml b/DefaultYAMLs/Default/g++.yaml index 3b0be5d..b7ca7eb 100644 --- a/DefaultYAMLs/Default/g++.yaml +++ b/DefaultYAMLs/Default/g++.yaml @@ -1,21 +1,5 @@ # DO NOT modify this file. Changes will be overwritten when there's a reset or update -# List of anchors that will be aliased later. `Template` is **NOT** part of a profile -Templates: - "g++_CompileRunParts": &g++_CompileRunParts - - Type: Once - CommandPart: "{Executable} -c {CompileFlags}" - - Type: Repeats - CommandPart: " -D{DefineNameOnly}=" - - Type: Repeats - CommandPart: " \"-D{DefineName}={DefineValue}\"" - - Type: Repeats - CommandPart: " -I\"{IncludeDirectoryPath}\"" - - Type: Once - CommandPart: " \"{InputFilePath}\" -o \"{OutputFileDirectory}{/}{ObjectLinkFile.Prefix}{InputFileName}{ObjectLinkFile.Extension}\"" - "g++_CompileExpectedOutputFiles": &g++_CompileExpectedOutputFiles - - "{OutputFileDirectory}{/}{ObjectLinkFile.Prefix}{InputFileName}{ObjectLinkFile.Extension}" - # Name (case sensitive) of the profile that can be queried from a script Name: "g++" @@ -47,7 +31,7 @@ Languages: ["c++"] # All the fields in the imported yaml files will be merged together Import: "./CommonFileTypes.yaml" -# Specify the compiler settings +# Compiler settings, run once per input file Compiler: # (Optional) The command to be prepend for each compile command in **shell** for each platform # PreRun: @@ -60,47 +44,71 @@ Compiler: # Here are a list of substitution strings for RunParts, Setup and Cleanup. # To escape '{' and '}' to avoid substitutioon, simply repeat the '{' or '}' character again. # So "${MyBashVariable}" will become "${{MyBashVariable}}" + + # Constants: -------------------------------------------------------------------------------------- + # {Stage.SharedLibraryFile.Prefix} + # {Stage.SharedLinkFile.Prefix} + # {Stage.StaticLinkFile.Prefix} + # {Stage.ObjectLinkFile.Prefix} + # {Stage.DebugSymbolFile.Prefix} + # {Stage.SharedLibraryFile.Extension} + # {Stage.SharedLinkFile.Extension} + # {Stage.StaticLinkFile.Extension} + # {Stage.ObjectLinkFile.Extension} + # {Stage.DebugSymbolFile.Extension} + # {/}: Filesystem separator for the host platform + + + # Stage Info: -------------------------------------------------------------------------------------- + # {Stage.Executable}: Compiler executable + # {Stage.CompileFlags}: Compile flags from config and override + + + # Input/Output Info: -------------------------------------------------------------------------------------- + # {Stage.Input.Name}: Name of the current input source file (without directory path and extension) + # {Stage.Input.Extension}: Extension of the current input source file + # {Stage.Input.Directory}: Directory of the current input source file + # {Stage.Input.Path}: Full path to the current input source file + # {Stage.Output.Directory}: Directory of all the output files + - # {Executable}: Compiler executable - # {CompileFlags}: Compile flags from config and override - # {InputFileName}: Name of the input file (without directory path and extension) - # {InputFileExtension}: Extension of the input file - # {InputFileDirectory}: Directory of the input file - # {InputFilePath}: Full path to the input file - # {OutputFileDirectory}: Directory of all the output files - # {/}: Filesystem separator for the host platform - - # {SharedLibraryFile.Prefix} - # {SharedLinkFile.Prefix} - # {StaticLinkFile.Prefix} - # {ObjectLinkFile.Prefix} - # {DebugSymbolFile.Prefix} - - # {SharedLibraryFile.Extension} - # {SharedLinkFile.Extension} - # {StaticLinkFile.Extension} - # {ObjectLinkFile.Extension} - # {DebugSymbolFile.Extension} - - # Below are iterable substitution strings, must be inside "Repeats" run type: - # {IncludeDirectoryPath}: Path to all the include directories - # {DefineNameOnly}: All the defines without a value specified (equivalent to #define X) - # {DefineName}: Name of all the defines that has a value specified - # {DefineValue}: Value of all the defines that has a value specified (use together with {DefineName}) + # Iterable variables, must be inside "Repeats" run type: -------------------------------------------------------------------------------------- + # {Stage.DefineNameOnly}: All the defines without a value specified (equivalent to #define X) + # {Stage.DefineName}: Name of all the defines that has a value specified + # {Stage.DefineValue}: Value of all the defines that has a value specified (use together with {Stage.DefineName}) + + # {Stage.IncludeDirectory.Path}: Path to all the include directories + # +-> {Stage.IncludeDirectory.Source.Path}: Path to source include directories, sub array + # L-> {Stage.IncludeDirectory.Dep.Path}: Path to dependencies include directories, sub array CompileTypes: Executable: DefaultPlatform: - # Default flags to be substituted as {CompileFlags} + # Default flags to be substituted as {Stage.CompileFlags} Flags: "-std=c++17 -Wall -g" - # The executable to be substituted as {Executable} + # The executable to be substituted as {Stage.Executable} Executable: "g++" # The components for the command to be run - RunParts: *g++_CompileRunParts + RunParts: &g++_CompileRunParts + - Type: Once + CommandPart: "{Stage.Executable} -c {Stage.CompileFlags}" + - Type: Repeats + CommandPart: " -D{Stage.DefineNameOnly}=" + # (Optional) A separator (such as ",") which will be inserted between each repeating parts + # Separator: "" + - Type: Repeats + CommandPart: " \"-D{Stage.DefineName}={Stage.DefineValue}\"" + - Type: Repeats + CommandPart: " -isystem \"{Stage.IncludeDirectory.Dep.Path}\"" + - Type: Repeats + CommandPart: " -I\"{Stage.IncludeDirectory.Source.Path}\"" + - Type: Once + CommandPart: " \"{Stage.Input.Path}\" -o \"{Stage.Output.Directory}{/}{Stage.ObjectLinkFile.Prefix}{Stage.Input.Name}{Stage.ObjectLinkFile.Extension}\"" # What files to be expected as output for the command - ExpectedOutputFiles: *g++_CompileExpectedOutputFiles + ExpectedOutputFiles: &g++_CompileExpectedOutputFiles + - "{Stage.Output.Directory}{/}{Stage.ObjectLinkFile.Prefix}{Stage.Input.Name}{Stage.ObjectLinkFile.Extension}" # (Optional) The commands to run in **shell** BEFORE compiling # This is run inside the .runcpp2 directory where the build happens. @@ -134,50 +142,74 @@ Compiler: # Setup: [] # Cleanup: [] -# Specify the linker settings +# Linker settings, run once Linker: CheckExistence: DefaultPlatform: "g++ -v" # Here are a list of substitution strings for RunParts, Setup and Cleanup - # {Executable}: Linker executable - # {LinkFlags}: Link flags from config and override - # {OutputFileName}: Name of all the output files (without directory path and extension) - # {OutputFileDirectory}: Directory of all the output files - # {/}: Filesystem separator for the host platform - - # {SharedLibraryFile.Prefix} - # {SharedLinkFile.Prefix} - # {StaticLinkFile.Prefix} - # {ObjectLinkFile.Prefix} - # {DebugSymbolFile.Prefix} - - # {SharedLibraryFile.Extension} - # {SharedLinkFile.Extension} - # {StaticLinkFile.Extension} - # {ObjectLinkFile.Extension} - # {DebugSymbolFile.Extension} - - # Below are iterable substitution strings, must be inside "Repeats" run type: - # {LinkFileName}: Name of the file to be linked, regardless of the build type - # {LinkFileExtension}: File Extension of the file to be linked, regardless of the build type - # {LinkFileDirectory}: Directory of the file to be linked, regardless of the build type - # {LinkFilePath}: Full path to the file to be linked, regardless of the build type - - # {LinkObjectFileName}: Name of the object file to be linked - # {LinkObjectFileExtension}: File Extension of the object file to be linked - # {LinkObjectFileDirectory}: Directory of the object file to be linked - # {LinkObjectFilePath}: Full path to the object file to be linked - - # {LinkSharedFileName}: Name of the shared file to be linked - # {LinkSharedFileExtension}: File Extension of the shared file to be linked - # {LinkSharedFileDirectory}: Directory of the shared file to be linked - # {LinkSharedFilePath}: Full path to the shared file to be linked - - # {LinkStaticFileName}: Name of the static file to be linked - # {LinkStaticFileExtension}: File Extension of the static file to be linked - # {LinkStaticFileDirectory}: Directory of the static file to be linked - # {LinkStaticFilePath}: Full path to the static file to be linked + + # Constants: -------------------------------------------------------------------------------------- + # {Stage.SharedLibraryFile.Prefix} + # {Stage.SharedLinkFile.Prefix} + # {Stage.StaticLinkFile.Prefix} + # {Stage.ObjectLinkFile.Prefix} + # {Stage.DebugSymbolFile.Prefix} + # {Stage.SharedLibraryFile.Extension} + # {Stage.SharedLinkFile.Extension} + # {Stage.StaticLinkFile.Extension} + # {Stage.ObjectLinkFile.Extension} + # {Stage.DebugSymbolFile.Extension} + # {/}: Filesystem separator for the host platform + + + # Stage Info: -------------------------------------------------------------------------------------- + # {Stage.Executable}: Linker executable + # {Stage.LinkFlags}: Link flags from config and override + + + # Output Info: -------------------------------------------------------------------------------------- + # {Stage.Output.Name}: Name of the output file (without directory path and extension) + # {Stage.Output.Directory}: Directory of all the output files + + + # Iterable variables, must be inside "Repeats" run type: -------------------------------------------------------------------------------------- + # {Stage.Input.Name}: Name of the files to be linked, regardless of the build type + # +-> {Stage.Input.Dep.Name}: Name of the dependencies files to be linked, regardless of the build type, sub array + # +-> {Stage.Input.Source.Name}: Name of the source files to be linked, regardless of the build type, sub array + # +-> {Stage.Input.Object.Name}: Name of the object files to be linked, sub array + # | +-> {Stage.Input.Dep.Object.Name}: Name of the dependencies object files to be linked, Sub array + # | L-> {Stage.Input.Source.Object.Name}: Name of the source object files to be linked, Sub array + # +-> {Stage.Input.Shared.Name}: Name of the shared dependencies files to be linked, sub array + # L-> {Stage.Input.Static.Name}: Name of the static dependencies files to be linked, sub array + + # {Stage.Input.Extension}: File Extensions of the files to be linked, regardless of the build type + # +-> {Stage.Input.Dep.Extension}: File Extensions of the dependencies files to be linked, regardless of the build type + # +-> {Stage.Input.Source.Extension}: File Extensions of the source files to be linked, regardless of the build type + # +-> {Stage.Input.Object.Extension}: File Extensions of the object files to be linked, sub array + # | +-> {Stage.Input.Dep.Object.Extension}: File Extensions of the dependencies object files to be linked, sub array + # | L-> {Stage.Input.Source.Object.Extension}: File Extensions of the source object files to be linked, sub array + # +-> {Stage.Input.Shared.Extension}: File Extensions of the shared dependencies files to be linked, sub array + # L-> {Stage.Input.Static.Extension}: File Extensions of the static dependencies files to be linked, sub array + + # {Stage.Input.Directory}: Directories of the files to be linked, regardless of the build type + # +-> {Stage.Input.Dep.Directory}: Directories of the dependencies files to be linked, regardless of the build type + # +-> {Stage.Input.Source.Directory}: Directories of the source files to be linked, regardless of the build type + # +-> {Stage.Input.Object.Directory}: Directories of the object files to be linked, sub array + # | +-> {Stage.Input.Dep.Object.Directory}: Directories of the dependencies object files to be linked, sub array + # | L-> {Stage.Input.Source.Object.Directory}: Directories of the source object files to be linked, sub array + # +-> {Stage.Input.Shared.Directory}: Directories of the shared dependencies files to be linked, sub array + # L-> {Stage.Input.Static.Directory}: Directories of the static dependencies files to be linked, sub array + + # {Stage.Input.Path}: Full paths to the files to be linked, regardless of the build type + # +-> {Stage.Input.Dep.Path}: Full paths to the dependencies files to be linked, regardless of the build type + # +-> {Stage.Input.Source.Path}: Full paths to the source files to be linked, regardless of the build type + # +-> {Stage.Input.Object.Path}: Full paths to the object files to be linked, sub array + # | +-> {Stage.Input.Dep.Object.Path}: Full paths to the dependencies object files to be linked, sub array + # | L-> {Stage.Input.Source.Object.Path}: Full paths to the source object files to be linked, sub array + # +-> {Stage.Input.Shared.Path}: Full paths to the shared dependencies files to be linked, sub array + # L-> {Stage.Input.Static.Path}: Full paths to the static dependencies files to be linked, sub array + LinkTypes: Executable: Unix: @@ -185,10 +217,10 @@ Linker: Executable: "g++" RunParts: - Type: Once - CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{OutputFileName}\"" + CommandPart: "{Stage.Executable} {Stage.LinkFlags} -o \"{Stage.Output.Directory}{/}{Stage.Output.Name}\"" - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{OutputFileName}"] + CommandPart: " \"{Stage.Input.Path}\"" + ExpectedOutputFiles: ["{Stage.Output.Directory}{/}{Stage.Output.Name}"] # Setup: [] # Cleanup: [] Windows: @@ -196,10 +228,10 @@ Linker: Executable: "g++" RunParts: - Type: Once - CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{OutputFileName}.exe\"" + CommandPart: "{Stage.Executable} {Stage.LinkFlags} -o \"{Stage.Output.Directory}{/}{Stage.Output.Name}.exe\"" - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{OutputFileName}.exe"] + CommandPart: " \"{Stage.Input.Path}\"" + ExpectedOutputFiles: ["{Stage.Output.Directory}{/}{Stage.Output.Name}.exe"] # Setup: [] # Cleanup: [] ExecutableShared: @@ -208,10 +240,10 @@ Linker: Executable: "g++" RunParts: - Type: Once - CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}\"" + CommandPart: "{Stage.Executable} {Stage.LinkFlags} -o \"{Stage.Output.Directory}{/}{Stage.SharedLibraryFile.Prefix}{Stage.Output.Name}{Stage.SharedLibraryFile.Extension}\"" - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}"] + CommandPart: " \"{Stage.Input.Path}\"" + ExpectedOutputFiles: ["{Stage.Output.Directory}{/}{Stage.SharedLibraryFile.Prefix}{Stage.Output.Name}{Stage.SharedLibraryFile.Extension}"] # Setup: [] # Cleanup: [] Static: @@ -220,10 +252,10 @@ Linker: Executable: "g++" RunParts: - Type: Once - CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{StaticLinkFile.Prefix}{OutputFileName}{StaticLinkFile.Extension}\"" + CommandPart: "{Stage.Executable} {Stage.LinkFlags} -o \"{Stage.Output.Directory}{/}{Stage.StaticLinkFile.Prefix}{Stage.Output.Name}{Stage.StaticLinkFile.Extension}\"" - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{StaticLinkFile.Prefix}{OutputFileName}{StaticLinkFile.Extension}"] + CommandPart: " \"{Stage.Input.Path}\"" + ExpectedOutputFiles: ["{Stage.Output.Directory}{/}{Stage.StaticLinkFile.Prefix}{Stage.Output.Name}{Stage.StaticLinkFile.Extension}"] # Setup: [] # Cleanup: [] Shared: @@ -232,9 +264,9 @@ Linker: Executable: "g++" RunParts: - Type: Once - CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}\"" + CommandPart: "{Stage.Executable} {Stage.LinkFlags} -o \"{Stage.Output.Directory}{/}{Stage.SharedLibraryFile.Prefix}{Stage.Output.Name}{Stage.SharedLibraryFile.Extension}\"" - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}"] + CommandPart: " \"{Stage.Input.Path}\"" + ExpectedOutputFiles: ["{Stage.Output.Directory}{/}{Stage.SharedLibraryFile.Prefix}{Stage.Output.Name}{Stage.SharedLibraryFile.Extension}"] # Setup: [] # Cleanup: [] diff --git a/DefaultYAMLs/Default/vs2022_v17+.yaml b/DefaultYAMLs/Default/vs2022_v17+.yaml index b92d5c6..8da2e7a 100644 --- a/DefaultYAMLs/Default/vs2022_v17+.yaml +++ b/DefaultYAMLs/Default/vs2022_v17+.yaml @@ -1,25 +1,9 @@ # DO NOT modify this file. Changes will be overwritten when there's a reset or update -# List of anchors that will be aliased later. `Template` is **NOT** part of a profile +# List of YAML anchors that will be aliased later. `Template` is **NOT** part of a profile Templates: vs2022_v17+_CompileFlags: &vs2022_v17+_CompileFlags - Flags: "/nologo /W4 /diagnostics:caret /utf-8 /Gm- /MDd /EHar /TP /std:c++17 /GR /RTC1 /Zc:inline /Zi" - "vs2022_v17+_CompileRunParts": &vs2022_v17+_CompileRunParts - - Type: Once - CommandPart: "{Executable} /c {CompileFlags}" - - Type: Repeats - CommandPart: " /D{DefineNameOnly}=" - - Type: Repeats - CommandPart: " \"/D{DefineName}={DefineValue}\"" - - Type: Repeats - CommandPart: " /I\"{IncludeDirectoryPath}\"" - - Type: Once - CommandPart: " /Fo\"{OutputFileDirectory}{/}{ObjectLinkFile.Prefix}{InputFileName}{ObjectLinkFile.Extension}\" \ - /Fd\"{OutputFileDirectory}{/}{DebugSymbolFile.Prefix}{InputFileName}{DebugSymbolFile.Extension}\" \ - \"{InputFilePath}\"" - "vs2022_v17+_CompileExpectedOutputFiles": &vs2022_v17+_CompileExpectedOutputFiles - - "{OutputFileDirectory}{/}{ObjectLinkFile.Prefix}{InputFileName}{ObjectLinkFile.Extension}" - - "{OutputFileDirectory}{/}{DebugSymbolFile.Prefix}{InputFileName}{DebugSymbolFile.Extension}" + Flags: "/nologo /W4 /diagnostics:caret /utf-8 /Gm- /MDd /EHar /TP /std:c++17 /GR /RTC1 /Zc:inline /Zi /external:W0" # https://learn.microsoft.com/en-us/cpp/overview/compiler-versions?view=msvc-170 Name: "vs2022_v17+" @@ -46,8 +30,24 @@ Compiler: Windows: <<: *vs2022_v17+_CompileFlags Executable: "CL.exe" - RunParts: *vs2022_v17+_CompileRunParts - ExpectedOutputFiles: *vs2022_v17+_CompileExpectedOutputFiles + RunParts: &vs2022_v17+_CompileRunParts + - Type: Once + CommandPart: "{Stage.Executable} /c {Stage.CompileFlags}" + - Type: Repeats + CommandPart: " /D{Stage.DefineNameOnly}=" + - Type: Repeats + CommandPart: " \"/D{Stage.DefineName}={Stage.DefineValue}\"" + - Type: Repeats + CommandPart: " /external:I\"{Stage.IncludeDirectory.Dep.Path}\"" + - Type: Repeats + CommandPart: " /I\"{Stage.IncludeDirectory.Source.Path}\"" + - Type: Once + CommandPart: " /Fo\"{Stage.Output.Directory}{/}{Stage.ObjectLinkFile.Prefix}{Stage.Input.Name}{Stage.ObjectLinkFile.Extension}\" \ + /Fd\"{Stage.Output.Directory}{/}{Stage.DebugSymbolFile.Prefix}{Stage.Input.Name}{Stage.DebugSymbolFile.Extension}\" \ + \"{Stage.Input.Path}\"" + ExpectedOutputFiles: &vs2022_v17+_CompileExpectedOutputFiles + - "{Stage.Output.Directory}{/}{Stage.ObjectLinkFile.Prefix}{Stage.Input.Name}{Stage.ObjectLinkFile.Extension}" + - "{Stage.Output.Directory}{/}{Stage.DebugSymbolFile.Prefix}{Stage.Input.Name}{Stage.DebugSymbolFile.Extension}" ExecutableShared: Windows: <<: *vs2022_v17+_CompileFlags @@ -82,11 +82,11 @@ Linker: RunParts: - Type: Once CommandPart: >- - {Executable} {LinkFlags} - /OUT:"{OutputFileDirectory}{/}{OutputFileName}.exe" + {Stage.Executable} {Stage.LinkFlags} + /OUT:"{Stage.Output.Directory}{/}{Stage.Output.Name}.exe" - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{OutputFileName}.exe"] + CommandPart: " \"{Stage.Input.Path}\"" + ExpectedOutputFiles: ["{Stage.Output.Directory}{/}{Stage.Output.Name}.exe"] ExecutableShared: Windows: Flags: >- @@ -97,13 +97,13 @@ Linker: RunParts: - Type: Once CommandPart: >- - {Executable} {LinkFlags} - /OUT:"{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}" - /IMPLIB:"{OutputFileDirectory}{/}{SharedLinkFile.Prefix}{OutputFileName}{SharedLinkFile.Extension}" + {Stage.Executable} {Stage.LinkFlags} + /OUT:"{Stage.Output.Directory}{/}{Stage.SharedLibraryFile.Prefix}{Stage.Output.Name}{Stage.SharedLibraryFile.Extension}" + /IMPLIB:"{Stage.Output.Directory}{/}{Stage.SharedLinkFile.Prefix}{Stage.Output.Name}{Stage.SharedLinkFile.Extension}" /DEF:".\temp.def" - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}"] + CommandPart: " \"{Stage.Input.Path}\"" + ExpectedOutputFiles: ["{Stage.Output.Directory}{/}{Stage.SharedLibraryFile.Prefix}{Stage.Output.Name}{Stage.SharedLibraryFile.Extension}"] Setup: [ "echo EXPORTS > .\\temp.def", "echo. main @1 >> .\\temp.def" ] Cleanup: [ "del .\\temp.def" ] Static: @@ -113,12 +113,12 @@ Linker: RunParts: - Type: Once CommandPart: >- - {Executable} {LinkFlags} - /OUT:"{OutputFileDirectory}{/}{StaticLinkFile.Prefix}{OutputFileName}{StaticLinkFile.Extension}" - /IMPLIB:"{OutputFileDirectory}{/}{SharedLinkFile.Prefix}{OutputFileName}{SharedLinkFile.Extension}" + {Stage.Executable} {Stage.LinkFlags} + /OUT:"{Stage.Output.Directory}{/}{Stage.StaticLinkFile.Prefix}{Stage.Output.Name}{Stage.StaticLinkFile.Extension}" + /IMPLIB:"{Stage.Output.Directory}{/}{Stage.SharedLinkFile.Prefix}{Stage.Output.Name}{Stage.SharedLinkFile.Extension}" - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{StaticLinkFile.Prefix}{OutputFileName}{StaticLinkFile.Extension}"] + CommandPart: " \"{Stage.Input.Path}\"" + ExpectedOutputFiles: ["{Stage.Output.Directory}{/}{Stage.StaticLinkFile.Prefix}{Stage.Output.Name}{Stage.StaticLinkFile.Extension}"] Shared: Windows: Flags: >- @@ -129,9 +129,9 @@ Linker: RunParts: - Type: Once CommandPart: >- - {Executable} {LinkFlags} - /OUT:"{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}" - /IMPLIB:"{OutputFileDirectory}{/}{SharedLinkFile.Prefix}{OutputFileName}{SharedLinkFile.Extension}" + {Stage.Executable} {Stage.LinkFlags} + /OUT:"{Stage.Output.Directory}{/}{Stage.SharedLibraryFile.Prefix}{Stage.Output.Name}{Stage.SharedLibraryFile.Extension}" + /IMPLIB:"{Stage.Output.Directory}{/}{Stage.SharedLinkFile.Prefix}{Stage.Output.Name}{Stage.SharedLinkFile.Extension}" - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}"] + CommandPart: " \"{Stage.Input.Path}\"" + ExpectedOutputFiles: ["{Stage.Output.Directory}{/}{Stage.SharedLibraryFile.Prefix}{Stage.Output.Name}{Stage.SharedLibraryFile.Extension}"] diff --git a/Src/Tests/Data/ProfileTest.cpp b/Src/Tests/Data/ProfileTest.cpp index aadb003..45a6768 100644 --- a/Src/Tests/Data/ProfileTest.cpp +++ b/Src/Tests/Data/ProfileTest.cpp @@ -70,6 +70,7 @@ DS::Result TestMain() CommandPart: "{Executable} -c {CompileFlags}" - Type: Repeats CommandPart: " -I\"{IncludeDirectoryPath}\"" + Separator: " " - Type: Once CommandPart: " \"{InputFilePath}\" -o \"{OutputFilePath}\"" ExpectedOutputFiles: ["TestOutputFile", "TestOutputFile2"] @@ -199,6 +200,7 @@ DS::Result TestMain() DS_ASSERT_EQ(executableCompile.Flags, "-std=c++17 -Wall -g"); DS_ASSERT_EQ(executableCompile.Executable, "g++"); DS_ASSERT_EQ(executableCompile.RunParts.size(), 3); + DS_ASSERT_EQ(executableCompile.RunParts[1].Separator, " "); DS_ASSERT_EQ(executableCompile.ExpectedOutputFiles.size(), 2); //Verify Compiler ExecutableShared diff --git a/Src/runcpp2/CompilingLinking.hpp b/Src/runcpp2/CompilingLinking.hpp index ca8bf2b..d9fbfa5 100644 --- a/Src/runcpp2/CompilingLinking.hpp +++ b/Src/runcpp2/CompilingLinking.hpp @@ -93,41 +93,40 @@ namespace runcpp2::TrimRight(inOutFlags); } - bool PopulateFilesTypesMap( const runcpp2::Data::FilesTypesInfo& fileTypesInfo, + void PopulateFilesTypesMap( const runcpp2::Data::FilesTypesInfo& fileTypesInfo, std::unordered_map< std::string, std::vector>& outSubstitutionMap) { ssLOG_FUNC_DEBUG(); - #define INTERNAL_STR(a) #a - #define INTERNAL_COMPOSE(a, b) a b - #define INTERNAL_ADD_TO_MAP(target) \ - outSubstitutionMap[ "{" INTERNAL_COMPOSE(INTERNAL_STR, (target)) "}" ] = \ - { *runcpp2::GetValueFromPlatformMap(fileTypesInfo. target) } - - INTERNAL_ADD_TO_MAP(SharedLibraryFile.Prefix); - INTERNAL_ADD_TO_MAP(SharedLinkFile.Prefix); - INTERNAL_ADD_TO_MAP(StaticLinkFile.Prefix); - INTERNAL_ADD_TO_MAP(ObjectLinkFile.Prefix); - INTERNAL_ADD_TO_MAP(DebugSymbolFile.Prefix); - - INTERNAL_ADD_TO_MAP(SharedLibraryFile.Extension); - INTERNAL_ADD_TO_MAP(SharedLinkFile.Extension); - INTERNAL_ADD_TO_MAP(StaticLinkFile.Extension); - INTERNAL_ADD_TO_MAP(ObjectLinkFile.Extension); - INTERNAL_ADD_TO_MAP(DebugSymbolFile.Extension); - - #undef INTERNAL_STR - #undef INTERNAL_COMPOSE - #undef INTERNAL_ADD_TO_MAP + outSubstitutionMap[ "{Stage.SharedLibraryFile.Prefix}" ] = + { *runcpp2::GetValueFromPlatformMap(fileTypesInfo. SharedLibraryFile.Prefix) }; + outSubstitutionMap[ "{Stage.SharedLinkFile.Prefix}" ] = + { *runcpp2::GetValueFromPlatformMap(fileTypesInfo. SharedLinkFile.Prefix) }; + outSubstitutionMap[ "{Stage.StaticLinkFile.Prefix}" ] = + { *runcpp2::GetValueFromPlatformMap(fileTypesInfo. StaticLinkFile.Prefix) }; + outSubstitutionMap[ "{Stage.ObjectLinkFile.Prefix}" ] = + { *runcpp2::GetValueFromPlatformMap(fileTypesInfo. ObjectLinkFile.Prefix) }; + outSubstitutionMap[ "{Stage.DebugSymbolFile.Prefix}" ] = + { *runcpp2::GetValueFromPlatformMap(fileTypesInfo. DebugSymbolFile.Prefix) }; - return true; + outSubstitutionMap[ "{Stage.SharedLibraryFile.Extension}" ] = + { *runcpp2::GetValueFromPlatformMap(fileTypesInfo. SharedLibraryFile.Extension) }; + outSubstitutionMap[ "{Stage.SharedLinkFile.Extension}" ] = + { *runcpp2::GetValueFromPlatformMap(fileTypesInfo. SharedLinkFile.Extension) }; + outSubstitutionMap[ "{Stage.StaticLinkFile.Extension}" ] = + { *runcpp2::GetValueFromPlatformMap(fileTypesInfo. StaticLinkFile.Extension) }; + outSubstitutionMap[ "{Stage.ObjectLinkFile.Extension}" ] = + { *runcpp2::GetValueFromPlatformMap(fileTypesInfo. ObjectLinkFile.Extension) }; + outSubstitutionMap[ "{Stage.DebugSymbolFile.Extension}" ] = + { *runcpp2::GetValueFromPlatformMap(fileTypesInfo. DebugSymbolFile.Extension) }; } bool CompileScript( const ghc::filesystem::path& buildDir, const ghc::filesystem::path& scriptDirectory, const std::vector& sourceFiles, - const std::vector& includePaths, + const std::vector& sourceIncludePaths, + const std::vector& depIncludePaths, const runcpp2::Data::ScriptInfo& scriptInfo, const runcpp2::Data::Profile& profile, std::vector& outObjectsFilesPaths, @@ -181,27 +180,34 @@ namespace } std::unordered_map> substitutionMapTemplate; - substitutionMapTemplate["{Executable}"] = {(*currentOutputTypeInfo).Executable}; + substitutionMapTemplate["{Stage.Executable}"] = {(*currentOutputTypeInfo).Executable}; //Compile flags { std::string compileFlags = (*currentOutputTypeInfo).Flags; AppendAndRemoveFlags(profile, scriptInfo.OverrideCompileFlags, compileFlags); - substitutionMapTemplate["{CompileFlags}"] = {compileFlags}; + substitutionMapTemplate["{Stage.CompileFlags}"] = {compileFlags}; } - //Add script and dependency include paths - substitutionMapTemplate["{IncludeDirectoryPath}"] = {}; - for(const ghc::filesystem::path& includePath : includePaths) + //Add source and dependency include paths + substitutionMapTemplate["{Stage.IncludeDirectory.Path}"] = {}; + for(const ghc::filesystem::path& includePath : sourceIncludePaths) + { + std::string processedInclude = runcpp2::ProcessPath(includePath.string()); + substitutionMapTemplate["{Stage.IncludeDirectory.Path}"].push_back(processedInclude); + substitutionMapTemplate["{Stage.IncludeDirectory.Source.Path}"].push_back(processedInclude); + } + for(const ghc::filesystem::path& includePath : depIncludePaths) { std::string processedInclude = runcpp2::ProcessPath(includePath.string()); - substitutionMapTemplate["{IncludeDirectoryPath}"].push_back(processedInclude); + substitutionMapTemplate["{Stage.IncludeDirectory.Path}"].push_back(processedInclude); + substitutionMapTemplate["{Stage.IncludeDirectory.Dep.Path}"].push_back(processedInclude); } //Add defines - substitutionMapTemplate["{DefineName}"] = {}; - substitutionMapTemplate["{DefineValue}"] = {}; - substitutionMapTemplate["{DefineNameOnly}"] = {}; + substitutionMapTemplate["{Stage.DefineName}"] = {}; + substitutionMapTemplate["{Stage.DefineValue}"] = {}; + substitutionMapTemplate["{Stage.DefineNameOnly}"] = {}; if(runcpp2::HasValueFromPlatformMap(scriptInfo.Defines)) { const runcpp2::Data::ProfilesDefines& platformDefines = @@ -217,18 +223,16 @@ namespace const runcpp2::Data::Define& define = profileDefines->at(i); if(define.HasValue) { - substitutionMapTemplate["{DefineName}"].push_back(define.Name); - substitutionMapTemplate["{DefineValue}"].push_back(define.Value); + substitutionMapTemplate["{Stage.DefineName}"].push_back(define.Name); + substitutionMapTemplate["{Stage.DefineValue}"].push_back(define.Value); } else - substitutionMapTemplate["{DefineNameOnly}"].push_back(define.Name); + substitutionMapTemplate["{Stage.DefineNameOnly}"].push_back(define.Name); } } } - if(!PopulateFilesTypesMap(profile.FilesTypes, substitutionMapTemplate)) - return false; - + PopulateFilesTypesMap(profile.FilesTypes, substitutionMapTemplate); substitutionMapTemplate["{/}"] = {runcpp2::ProcessPath("/")}; std::unordered_map> substitutionMap; @@ -269,15 +273,15 @@ namespace std::string sourceExt = currentSource.extension().string(); //Input File { - substitutionMap["{InputFileName}"] = {sourceName}; - substitutionMap["{InputFileExtension}"] = {sourceExt}; - substitutionMap["{InputFileDirectory}"] = {sourceDirectory}; - substitutionMap["{InputFilePath}"] = {currentSource.string()}; + substitutionMap["{Stage.Input.Name}"] = {sourceName}; + substitutionMap["{Stage.Input.Extension}"] = {sourceExt}; + substitutionMap["{Stage.Input.Directory}"] = {sourceDirectory}; + substitutionMap["{Stage.Input.Path}"] = {currentSource.string()}; } //Output File { - substitutionMap["{OutputFileDirectory}"] = + substitutionMap["{Stage.Output.Directory}"] = {runcpp2::ProcessPath( (buildDir / relativeSourcePath.parent_path()).string() )}; if(!runcpp2::HasValueFromPlatformMap(profile.FilesTypes.ObjectLinkFile.Extension)) @@ -524,12 +528,20 @@ namespace return !failedAny; } + struct LinkPriorities + { + ghc::filesystem::path* Path; + int Priority; + bool IsSource; + }; + bool LinkScript(const ghc::filesystem::path& buildDir, const std::string& outputName, const runcpp2::Data::ScriptInfo& scriptInfo, const std::string& additionalLinkFlags, const runcpp2::Data::Profile& profile, - const std::vector& objectsFilesPaths) + const std::vector priorities) + //const std::vector& objectsFilesPaths) { ssLOG_FUNC_INFO(); const runcpp2::Data::OutputTypeInfo* currentOutputTypeInfo = nullptr; @@ -568,7 +580,7 @@ namespace return false; } std::unordered_map> substitutionMap; - substitutionMap["{Executable}"] = {(*currentOutputTypeInfo).Executable}; + substitutionMap["{Stage.Executable}"] = {(*currentOutputTypeInfo).Executable}; //Link Flags { @@ -583,27 +595,27 @@ namespace linkFlags += std::string(" ") + additionalLinkFlags; } - substitutionMap["{LinkFlags}"] = {linkFlags}; + substitutionMap["{Stage.LinkFlags}"] = {linkFlags}; } //Output File - substitutionMap["{OutputFileName}"] = {outputName}; - substitutionMap["{OutputFileDirectory}"] = {buildDir.string()}; - - if(!PopulateFilesTypesMap(profile.FilesTypes, substitutionMap)) - return false; + substitutionMap["{Stage.Output.Name}"] = {outputName}; + substitutionMap["{Stage.Output.Directory}"] = {buildDir.string()}; + PopulateFilesTypesMap(profile.FilesTypes, substitutionMap); substitutionMap["{/}"] = {runcpp2::ProcessPath("/")}; //Link Files { - for(int i = 0; i < objectsFilesPaths.size(); ++i) + for(int i = 0; i < priorities.size(); ++i) { - ssLOG_INFO("Trying to link " << objectsFilesPaths.at(i)); + const LinkPriorities& currentLinkTarget = priorities.at(i); + + ssLOG_INFO("Trying to link " << *(currentLinkTarget.Path)); using namespace runcpp2; //Check if this is a file we can link - std::string extension = GetFileExtensionWithoutVersion(objectsFilesPaths.at(i)); + std::string extension = GetFileExtensionWithoutVersion(*(currentLinkTarget.Path)); Data::DependencyLibraryType currentLinkType = Data::DependencyLibraryType::COUNT; if(!HasValueFromPlatformMap(profile.FilesTypes.ObjectLinkFile.Extension)) @@ -661,76 +673,105 @@ namespace processLinkFile:; if(currentLinkType == Data::DependencyLibraryType::COUNT) { - ssLOG_WARNING("Skip linking " << objectsFilesPaths.at(i)); + ssLOG_WARNING("Skip linking " << *(currentLinkTarget.Path)); continue; } - auto depLinkParsedPath = objectsFilesPaths.at(i); - std::string depLinkDirectory = depLinkParsedPath.parent_path().string(); - std::string depLinkName = depLinkParsedPath.stem().string(); - std::string depLinkExt = depLinkParsedPath.extension().string(); + ghc::filesystem::path linkParsedPath = *(currentLinkTarget.Path); + std::string linkDir = linkParsedPath.parent_path().string(); + std::string linkName = linkParsedPath.stem().string(); + std::string linkExt = linkParsedPath.extension().string(); - substitutionMap["{LinkFileName}"].push_back(depLinkName); - substitutionMap["{LinkFileExt}"].push_back(depLinkExt); - substitutionMap["{LinkFileDirectory}"].push_back(depLinkDirectory); + substitutionMap["{Stage.Input.Name}"].push_back(linkName); + substitutionMap["{Stage.Input.Extension}"].push_back(linkExt); + substitutionMap["{Stage.Input.Directory}"].push_back(linkDir); const std::string processedLinkFilePath = - runcpp2::ProcessPath(objectsFilesPaths.at(i)); - substitutionMap["{LinkFilePath}"].push_back(processedLinkFilePath); + runcpp2::ProcessPath(*(currentLinkTarget.Path)); + substitutionMap["{Stage.Input.Path}"].push_back(processedLinkFilePath); + + if(currentLinkTarget.IsSource) + { + substitutionMap["{Stage.Input.Source.Name}"].push_back(linkName); + substitutionMap["{Stage.Input.Source.Extension}"].push_back(linkExt); + substitutionMap["{Stage.Input.Source.Directory}"].push_back(linkDir); + substitutionMap["{Stage.Input.Source.Path}"].push_back(processedLinkFilePath); + } + else + { + substitutionMap["{Stage.Input.Dep.Name}"].push_back(linkName); + substitutionMap["{Stage.Input.Dep.Extension}"].push_back(linkExt); + substitutionMap["{Stage.Input.Dep.Directory}"].push_back(linkDir); + substitutionMap["{Stage.Input.Dep.Path}"].push_back(processedLinkFilePath); + } static_assert( static_cast(Data::DependencyLibraryType::COUNT) == 4, "Add new type to be processed"); - - substitutionMap["{LinkStaticFileName}"] = {}; - substitutionMap["{LinkStaticFileExt}"] = {}; - substitutionMap["{LinkStaticFileDirectory}"] = {}; - substitutionMap["{LinkStaticFilePath}"] = {}; - substitutionMap["{LinkSharedFileName}"] = {}; - substitutionMap["{LinkSharedFileExt}"] = {}; - substitutionMap["{LinkSharedFileDirectory}"] = {}; - substitutionMap["{LinkSharedFilePath}"] = {}; - substitutionMap["{LinkObjectFileName}"] = {}; - substitutionMap["{LinkObjectFileExt}"] = {}; - substitutionMap["{LinkObjectFileDirectory}"] = {}; - substitutionMap["{LinkObjectFilePath}"] = {}; switch(currentLinkType) { case Data::DependencyLibraryType::STATIC: { - substitutionMap["{LinkStaticFileName}"].push_back(depLinkName); - substitutionMap["{LinkStaticFileExt}"].push_back(depLinkExt); - substitutionMap["{LinkStaticFileDirectory}"].push_back(depLinkDirectory); - substitutionMap["{LinkStaticFilePath}"].push_back(processedLinkFilePath); + if(!currentLinkTarget.IsSource) + { + ssLOG_ERROR("Static as source?"); + return false; + } + + substitutionMap["{Stage.Input.Static.Name}"].push_back(linkName); + substitutionMap["{Stage.Input.Static.Extension}"].push_back(linkExt); + substitutionMap["{Stage.Input.Static.Directory}"].push_back(linkDir); + substitutionMap["{Stage.Input.Static.Path}"].push_back(processedLinkFilePath); break; } case Data::DependencyLibraryType::SHARED: { - substitutionMap["{LinkSharedFileName}"].push_back(depLinkName); - substitutionMap["{LinkSharedFileExt}"].push_back(depLinkExt); - substitutionMap["{LinkSharedFileDirectory}"].push_back(depLinkDirectory); - substitutionMap["{LinkSharedFilePath}"].push_back(processedLinkFilePath); + if(!currentLinkTarget.IsSource) + { + ssLOG_ERROR("Shared as source?"); + return false; + } + + substitutionMap["{Stage.Input.Shared.Name}"].push_back(linkName); + substitutionMap["{Stage.Input.Shared.Extension}"].push_back(linkExt); + substitutionMap["{Stage.Input.Shared.Directory}"].push_back(linkDir); + substitutionMap["{Stage.Input.Shared.Path}"].push_back(processedLinkFilePath); break; } case Data::DependencyLibraryType::OBJECT: { - substitutionMap["{LinkObjectFileName}"].push_back(depLinkName); - substitutionMap["{LinkObjectFileExt}"].push_back(depLinkExt); - substitutionMap["{LinkObjectFileDirectory}"].push_back(depLinkDirectory); - substitutionMap["{LinkObjectFilePath}"].push_back(processedLinkFilePath); + substitutionMap["{Stage.Input.Object.Name}"].push_back(linkName); + substitutionMap["{Stage.Input.Object.Extension}"].push_back(linkExt); + substitutionMap["{Stage.Input.Object.Directory}"].push_back(linkDir); + substitutionMap["{Stage.Input.Object.Path}"].push_back(processedLinkFilePath); + + if(currentLinkTarget.IsSource) + { + substitutionMap["{Stage.Input.Source.Object.Name}"].push_back(linkName); + substitutionMap["{Stage.Input.Source.Object.Extension}"].push_back(linkExt); + substitutionMap["{Stage.Input.Source.Object.Directory}"].push_back(linkDir); + substitutionMap["{Stage.Input.Source.Object.Path}"].push_back(processedLinkFilePath); + } + else + { + substitutionMap["{Stage.Input.Dep.Object.Name}"].push_back(linkName); + substitutionMap["{Stage.Input.Dep.Object.Extension}"].push_back(linkExt); + substitutionMap["{Stage.Input.Dep.Object.Directory}"].push_back(linkDir); + substitutionMap["{Stage.Input.Dep.Object.Path}"].push_back(processedLinkFilePath); + } break; } case Data::DependencyLibraryType::HEADER: case Data::DependencyLibraryType::COUNT: { - ssLOG_WARNING( "Unexpected currentLinkType: " << - static_cast(currentLinkType) << - " for " << objectsFilesPaths.at(i)); - break; + ssLOG_ERROR("Unexpected currentLinkType: " << + static_cast(currentLinkType) << + " for " << *(currentLinkTarget.Path)); + return false; } } - } + } //for(int i = 0; i < objectsFilesPaths.size(); ++i) } - //Use ExpectedOutputFiles? + //TODO: Use ExpectedOutputFiles? #if 0 for(int i = 0; i < currentOutputTypeInfo->ExpectedOutputFiles.size(); ++i) { @@ -897,7 +938,8 @@ namespace runcpp2 const ghc::filesystem::path& scriptDirectory, const std::vector& sourceFiles, const std::vector& sourceHasCache, - const std::vector& includePaths, + const std::vector& sourceIncludePaths, + const std::vector& depIncludePaths, const Data::ScriptInfo& scriptInfo, const Data::Profile& profile, const int maxThreads) @@ -918,7 +960,8 @@ namespace runcpp2 if(!CompileScript( buildDir, scriptDirectory, sourceFilesNeededToCompile, - includePaths, + sourceIncludePaths, + depIncludePaths, scriptInfo, profile, objectsFilesPaths, @@ -943,15 +986,19 @@ namespace runcpp2 const std::string& outputName, const std::vector& sourceFiles, const std::vector& sourceHasCache, - const std::vector& includePaths, + const std::vector& sourceIncludePaths, + const std::vector& depIncludePaths, const Data::ScriptInfo& scriptInfo, const std::vector& availableDependencies, const Data::Profile& profile, - const std::vector& binaryFilesPaths, - const std::vector& binaryFilesPriorities, + const std::vector& sourceBinaryFilesPaths, + const std::vector& sourceBinaryFilesPriorities, + const std::vector& depBinaryFilesPaths, + const std::vector& depBinaryFilesPriorities, const int maxThreads) { - DS_ASSERT_EQ(binaryFilesPaths.size(), binaryFilesPriorities.size()); + DS_ASSERT_EQ(sourceBinaryFilesPaths.size(), sourceBinaryFilesPriorities.size()); + DS_ASSERT_EQ(depBinaryFilesPaths.size(), depBinaryFilesPriorities.size()); if(!RunGlobalSteps(buildDir, profile.Setup)) return DS_ERROR_MSG("Failed to run profile global setup steps"); @@ -963,16 +1010,17 @@ namespace runcpp2 sourceFilesNeededToCompile.push_back(sourceFiles.at(i)); } - std::vector objectsFilesPaths; + std::vector compiledObjectsFilesPaths; //Compile source files that don't have cache if(!CompileScript( buildDir, scriptDirectory, sourceFilesNeededToCompile, - includePaths, + sourceIncludePaths, + depIncludePaths, scriptInfo, profile, - objectsFilesPaths, + compiledObjectsFilesPaths, maxThreads)) { if(!RunGlobalSteps(buildDir, profile.Cleanup)) @@ -981,35 +1029,41 @@ namespace runcpp2 return DS_ERROR_MSG("CompileScript failed"); } - struct PathPriorities - { - ghc::filesystem::path* Path; - int Priority; - }; //Priorities for source files - std::vector priorities; - for(int i = 0; i < objectsFilesPaths.size(); ++i) - priorities.push_back({&objectsFilesPaths[i], 0}); + std::vector priorities; + for(int i = 0; i < compiledObjectsFilesPaths.size(); ++i) + priorities.push_back({&compiledObjectsFilesPaths[i], 0, true}); //Add compiled object files - for(int i = 0; i < binaryFilesPaths.size(); ++i) + for(int i = 0; i < sourceBinaryFilesPaths.size(); ++i) { priorities.push_back( { - (ghc::filesystem::path*)&binaryFilesPaths.at(i), - binaryFilesPriorities.at(i) + (ghc::filesystem::path*)&sourceBinaryFilesPaths.at(i), + sourceBinaryFilesPriorities.at(i), + true }); } + //Add dependencies files + for(int i = 0; i < depBinaryFilesPaths.size(); ++i) + { + priorities.push_back( { + (ghc::filesystem::path*)&depBinaryFilesPaths.at(i), + depBinaryFilesPriorities.at(i), + false + }); + } + qsort( priorities.data(), priorities.size(), - sizeof(PathPriorities), + sizeof(LinkPriorities), [](const void* a, const void* b) -> int { //Higher priority comes first - if(((const PathPriorities*)a)->Priority > ((const PathPriorities*)b)->Priority) + if(((const LinkPriorities*)a)->Priority > ((const LinkPriorities*)b)->Priority) return -1; - else if(((const PathPriorities*)a)->Priority < - ((const PathPriorities*)b)->Priority) + else if(((const LinkPriorities*)a)->Priority < + ((const LinkPriorities*)b)->Priority) { return +1; } @@ -1017,10 +1071,6 @@ namespace runcpp2 return 0; }); - std::vector sortedObjectsFilesPaths; - for(int i = 0; i < priorities.size(); ++i) - sortedObjectsFilesPaths.push_back(*priorities[i].Path); - //Skip linking if build type doesn't need it if(!Data::BuildTypeHelper::NeedsLinking(scriptInfo.CurrentBuildType)) { @@ -1029,7 +1079,7 @@ namespace runcpp2 return {}; } - std::string dependenciesLinkFlags; + std::string dependenciesLinkFlags; //TODO: Does the order matter? //Add link flags for the dependencies for(int i = 0; i < availableDependencies.size(); ++i) @@ -1052,15 +1102,8 @@ namespace runcpp2 runcpp2::TrimRight(dependenciesLinkFlags); - if(!LinkScript( buildDir, - outputName, - scriptInfo, - dependenciesLinkFlags, - profile, - sortedObjectsFilesPaths)) - { + if(!LinkScript(buildDir, outputName, scriptInfo, dependenciesLinkFlags, profile, priorities)) return DS_ERROR_MSG("LinkScript failed"); - } if(!RunGlobalSteps(buildDir, profile.Cleanup)) return DS_ERROR_MSG("Failed to run profile global cleanup steps"); diff --git a/Src/runcpp2/Data/StageInfo.hpp b/Src/runcpp2/Data/StageInfo.hpp index 8dfbd6f..381bb37 100644 --- a/Src/runcpp2/Data/StageInfo.hpp +++ b/Src/runcpp2/Data/StageInfo.hpp @@ -54,6 +54,7 @@ namespace Data RunType Type; std::string CommandPart; + std::string Separator; }; struct OutputTypeInfo @@ -150,7 +151,14 @@ namespace Data return false); for(int j = 0; j < substitutedParts.size(); ++j) + { outCommand += substitutedParts[j]; + if( !currentRunParts.at(i).Separator.empty() && + j != substitutedParts.size() - 1) + { + outCommand += currentRunParts.at(i).Separator; + } + } } } @@ -366,7 +374,8 @@ namespace Data for(size_t i = 0; i < info.RunParts.size(); ++i) { if( info.RunParts[i].Type != otherInfo.RunParts[i].Type || - info.RunParts[i].CommandPart != otherInfo.RunParts[i].CommandPart) + info.RunParts[i].CommandPart != otherInfo.RunParts[i].CommandPart || + info.RunParts[i].Separator != otherInfo.RunParts[i].Separator) { return false; } @@ -438,7 +447,8 @@ namespace std::vector currentRunPartRequirements = { NodeRequirement("Type", YAML::NodeType::Scalar, true, false), - NodeRequirement("CommandPart", YAML::NodeType::Scalar, true, false) + NodeRequirement("CommandPart", YAML::NodeType::Scalar, true, false), + NodeRequirement("Separator", YAML::NodeType::Scalar, false, false) }; if(!CheckNodeRequirements(currentPartNode, currentRunPartRequirements)) @@ -468,6 +478,13 @@ namespace outInfos[platformName].RunParts.back().CommandPart = currentPartNode ->GetMapValueScalar("CommandPart") .DS_TRY_ACT(return false); + + if(ExistAndHasChild(currentPartNode, "Separator")) + { + outInfos[platformName].RunParts.back().Separator = + currentPartNode ->GetMapValueScalar("Separator") + .DS_TRY_ACT(return false); + } } //Setup @@ -504,7 +521,7 @@ namespace .DS_TRY_ACT(return false); outInfos[platformName].ExpectedOutputFiles.push_back(outputFileVal); } - } + } //for(int i = 0; i < outputTypesSubNode->GetChildrenCount(); ++i) return true; } @@ -539,6 +556,12 @@ namespace outString += indentation + " CommandPart: " + GetEscapedYAMLString(it->second.RunParts.at(i).CommandPart) + "\n"; + + if(!it->second.RunParts.at(i).Separator.empty()) + { + outString += indentation + " Separator: " + + GetEscapedYAMLString(it->second.RunParts.at(i).Separator) + "\n"; + } } outString += indentation + " ExpectedOutputFiles: \n"; diff --git a/Src/runcpp2/DependenciesHelper.hpp b/Src/runcpp2/DependenciesHelper.hpp index 10d7fca..c8fb874 100644 --- a/Src/runcpp2/DependenciesHelper.hpp +++ b/Src/runcpp2/DependenciesHelper.hpp @@ -412,7 +412,8 @@ namespace runcpp2 availableDependencies.at(i)->Build, dependenciesLocalCopiesPaths.at(i), true, - false); + true); //TODO: Make this (and others) + // configurable later if(!depResult.HasValue()) { depResult.Error().Message += "\nFailed to build dependency " + @@ -1179,7 +1180,7 @@ namespace int returnCode = 0; std::string output; if(!runcpp2::RunCommand(gitCloneCommand, - false, + false, //TODO: Make this configurable later buildDir.string(), output, returnCode)) diff --git a/Src/runcpp2/PipelineSteps.hpp b/Src/runcpp2/PipelineSteps.hpp index a8553f6..01e52be 100644 --- a/Src/runcpp2/PipelineSteps.hpp +++ b/Src/runcpp2/PipelineSteps.hpp @@ -1032,11 +1032,13 @@ namespace runcpp2 const Data::ScriptInfo& scriptInfo, const Data::Profile& currentProfile, const std::vector& dependencies, - std::vector& outIncludePaths) + std::vector& outSourceIncludePaths, + std::vector& outDepIncludePaths) { ssLOG_FUNC_INFO(); - outIncludePaths.clear(); + outSourceIncludePaths.clear(); + outDepIncludePaths.clear(); if(!scriptDirectory.is_absolute()) return DS_ERROR_MSG("Script directory is not absolute: " + DS_STR(scriptDirectory)); @@ -1045,7 +1047,7 @@ namespace runcpp2 const Data::ProfilesProcessPaths* includePaths = GetValueFromPlatformMap(scriptInfo.IncludePaths); - outIncludePaths.push_back(scriptDirectory); + outSourceIncludePaths.push_back(scriptDirectory); if(includePaths != nullptr) { @@ -1086,7 +1088,7 @@ namespace runcpp2 return DS_ERROR_MSG(errMsg); } - outIncludePaths.push_back(resolvedPath); + outSourceIncludePaths.push_back(resolvedPath); } } } @@ -1095,9 +1097,8 @@ namespace runcpp2 for(const Data::DependencyInfo* dependency : dependencies) { for(const std::string& includePath : dependency->AbsoluteIncludePaths) - outIncludePaths.push_back(ghc::filesystem::path(includePath)); + outDepIncludePaths.push_back(ghc::filesystem::path(includePath)); } - return {}; } @@ -1106,14 +1107,14 @@ namespace runcpp2 GatherFilesIncludes(const std::vector& sourceFiles, const std::vector& sourceHasCache, const std::vector& includePaths, - SourceIncludeMap& outSourceIncludes) + SourceIncludeMap& outSourceIncludeMap) { ssLOG_FUNC_INFO(); if(sourceFiles.size() != sourceHasCache.size()) return DS_ERROR_MSG("Size of sourceFiles and sourceHasCache not matching"); - outSourceIncludes.clear(); + outSourceIncludeMap.clear(); for(int i = 0; i < sourceFiles.size(); ++i) { @@ -1125,7 +1126,7 @@ namespace runcpp2 std::unordered_set visitedFiles; ssLOG_INFO("Gathering includes for " << source.string()); - std::vector& currentIncludes = outSourceIncludes[source.string()]; + std::vector& currentIncludes = outSourceIncludeMap[source.string()]; std::queue filesToProcess; filesToProcess.push(source); diff --git a/Src/runcpp2/runcpp2.hpp b/Src/runcpp2/runcpp2.hpp index cf39cbd..6ce14c9 100644 --- a/Src/runcpp2/runcpp2.hpp +++ b/Src/runcpp2/runcpp2.hpp @@ -568,14 +568,6 @@ namespace runcpp2 params.profiles.at(profileIndex), sourceFiles).DS_TRY(); - //Get all include paths - std::vector includePaths; - GatherIncludePaths( scriptDirectory, - scriptInfo, - params.profiles.at(profileIndex), - availableDependencies, - includePaths).DS_TRY(); - //Check if we have already compiled before. std::vector sourceHasCache; std::vector cachedObjectsFiles; @@ -706,12 +698,14 @@ namespace runcpp2 sourceFiles).DS_TRY(); //Get all include paths - std::vector includePaths; + std::vector sourceIncludePaths; + std::vector depIncludePaths; GatherIncludePaths( scriptDirectory, scriptInfo, runParams.Core.profiles.at(profileIndex), availableDependencies, - includePaths).DS_TRY(); + sourceIncludePaths, + depIncludePaths).DS_TRY(); //Check if we have already compiled before. std::vector sourceHasCache; @@ -733,17 +727,23 @@ namespace runcpp2 outFinalIncludeWriteTime).DS_TRY(); } - runcpp2::SourceIncludeMap sourcesIncludes; - runcpp2::GatherFilesIncludes( sourceFiles, - sourceHasCache, - includePaths, - sourcesIncludes).DS_TRY(); + runcpp2::SourceIncludeMap sourceIncludeMap; + { + std::vector allIncludePaths = sourceIncludePaths; + allIncludePaths.insert( allIncludePaths.end(), + depIncludePaths.begin(), + depIncludePaths.end()); + runcpp2::GatherFilesIncludes( sourceFiles, + sourceHasCache, + allIncludePaths, + sourceIncludeMap).DS_TRY(); + } for(int i = 0; i < sourceFiles.size(); ++i) { if(!sourceHasCache.at(i)) { ssLOG_DEBUG("Updating include record for " << sourceFiles.at(i).string()); - if(sourcesIncludes.count(sourceFiles.at(i)) == 0) + if(sourceIncludeMap.count(sourceFiles.at(i)) == 0) { ssLOG_WARNING("Includes not gathered for " << sourceFiles.at(i).string()); continue; @@ -752,7 +752,7 @@ namespace runcpp2 bool writeResult = includeManager.WriteIncludeRecord ( sourceFiles.at(i), - sourcesIncludes.at(sourceFiles.at(i)) + sourceIncludeMap.at(sourceFiles.at(i)) ); if(!writeResult) { @@ -767,30 +767,31 @@ namespace runcpp2 } } - std::vector linkFilesPaths; + std::vector depLinkFilesPaths; SeparateDependencyFiles(runParams.Core.profiles.at(profileIndex).FilesTypes, gatheredBinariesPaths, - linkFilesPaths, + depLinkFilesPaths, filesToCopyPaths); + //TODO: Allow user to pass the priorities outside //Set dependencies files to be lower priority - std::vector binaryFilesPriorities; - for(int i = 0; i < linkFilesPaths.size(); ++i) - binaryFilesPriorities.push_back(-100); + std::vector depBinaryFilesPriorities; + for(int i = 0; i < depLinkFilesPaths.size(); ++i) + depBinaryFilesPriorities.push_back(-100); //Get finalBinaryWriteTime by combining final object and dependencies write times std::error_code e; ghc::filesystem::file_time_type finalBinaryWriteTime = finalObjectWriteTime; - for(int i = 0; i < linkFilesPaths.size(); ++i) + for(int i = 0; i < depLinkFilesPaths.size(); ++i) { - if(!ghc::filesystem::exists(linkFilesPaths.at(i), e)) + if(!ghc::filesystem::exists(depLinkFilesPaths.at(i), e)) { - return DS_ERROR_MSG(linkFilesPaths.at(i).string() + + return DS_ERROR_MSG(depLinkFilesPaths.at(i).string() + " reported as cached but doesn't exist"); } ghc::filesystem::file_time_type lastWriteTime = - ghc::filesystem::last_write_time(linkFilesPaths.at(i), e); + ghc::filesystem::last_write_time(depLinkFilesPaths.at(i), e); if(lastWriteTime > finalBinaryWriteTime) finalBinaryWriteTime = lastWriteTime; @@ -815,10 +816,12 @@ namespace runcpp2 if(!outputCache || relinkNeeded) { + std::vector sourceLinkFilesPaths; + std::vector sourceBinaryFilesPriorities; for(int i = 0; i < cachedObjectsFiles.size(); ++i) { - linkFilesPaths.push_back(cachedObjectsFiles.at(i)); - binaryFilesPriorities.push_back(0); + sourceLinkFilesPaths.push_back(cachedObjectsFiles.at(i)); + sourceBinaryFilesPriorities.push_back(0); } //TODO: Compile and link for watch as well. Load library as well @@ -828,7 +831,8 @@ namespace runcpp2 scriptDirectory, sourceFiles, sourceHasCache, - includePaths, + sourceIncludePaths, + depIncludePaths, scriptInfo, runParams.Core.profiles.at(profileIndex), maxThreads).DS_TRY(); @@ -841,12 +845,15 @@ namespace runcpp2 ghc::filesystem::path(scriptName), sourceFiles, sourceHasCache, - includePaths, + sourceIncludePaths, + depIncludePaths, scriptInfo, availableDependencies, runParams.Core.profiles.at(profileIndex), - linkFilesPaths, - binaryFilesPriorities, + depLinkFilesPaths, + depBinaryFilesPriorities, + sourceLinkFilesPaths, + sourceBinaryFilesPriorities, maxThreads) .DS_TRY_ACT(DS_TMP_ERROR.Message += "\nFailed to compile or link script."; DS_APPEND_TRACE(DS_TMP_ERROR); diff --git a/mkdocs/docs/TODO.md b/mkdocs/docs/TODO.md index 9e35771..188941c 100644 --- a/mkdocs/docs/TODO.md +++ b/mkdocs/docs/TODO.md @@ -10,6 +10,10 @@ - Migrate to DSResult and remove ssTest - Parameters for build config/script - Ability to compile runcpp2 as single cpp +- Parameters for dependencies +- System include +- Dot access groups for built-in profile variables +- Separator for repeat RunPart ### v0.3.1 - Check last run is shared lib or executable. Reset cache when necessary if different type @@ -34,14 +38,13 @@ ### v0.4.0 - Allow runcpp2 to be library for scriptable pipeline -- Parameters for dependencies - Parameters for profiles - Add more default profiles - Ditch cmake - Move to variant-lite instead of mpark-variant ## High Priority - +- External Source (curl download) for dependency - Expose/rename "InternalExecutableShared" and change BuildType to be platform map - This ties to the warning in `CompilingLinking.cpp:619` - Update `FileProperties.hpp` to use list of string for prefix and extension @@ -94,8 +97,7 @@ endfunction() print_target_properties(matplot) --> -- Add the ability to specify link order for source files and dependencies -- Auto link order for source files, heuristically from include maps +- Add the ability to specify link order for dependencies - Add the ability to specify different profiles(?)/defines for different source files - Use `` to handle potential segfaults - Use System2 subprocess if no prepend commands to be safer