├── tests ├── stdafx.cpp ├── DependentCppProject │ ├── dependentheader.h │ ├── DependentCppProject.vcxproj.filters │ ├── main.cpp │ ├── DependentCppPropertySheet.props │ └── DependentCppProject.vcxproj ├── freefunctions.h ├── TestStaticLibrary │ ├── staticlibfunctions.h │ ├── TestStaticLibrary.vcxproj.filters │ ├── staticlibfunctions.cpp │ └── TestStaticLibrary.vcxproj ├── unitytest.cpp ├── stdafx.h ├── TestDynamicLibrary │ ├── dynamiclibfunctions.h │ ├── dynamiclibfunctions.cpp │ ├── TestDynamicLibrary.vcxproj.filters │ └── TestDynamicLibrary.vcxproj ├── main.cpp ├── TestCppProject.vcxproj.filters ├── freefunctions.cpp ├── TestMsfastbuild.sln └── TestCppProject.vcxproj ├── msfastbuildvsix ├── Key.snk ├── Microsoft.Build.dll ├── Resources │ ├── FASTBuild.png │ └── FASTBuildPackage.ico ├── Microsoft.Build.Framework.dll ├── Microsoft.Build.Tasks.Core.dll ├── Microsoft.Build.Utilities.Core.dll ├── System.Collections.Immutable.dll ├── System.Threading.Tasks.Dataflow.dll ├── packages.config ├── app.config ├── license.txt ├── Properties │ └── AssemblyInfo.cs ├── stylesheet.css ├── source.extension.vsixmanifest ├── FASTBuildPackage.cs ├── FASTBuildPackage.vsct ├── VSPackage.resx ├── FASTBuild.cs └── msfastbuildvsix.csproj ├── msfastbuild ├── msfastbuild.snk ├── Microsoft.Build.CPPTasks.Common.dll ├── packages.config ├── App.config ├── Properties │ └── AssemblyInfo.cs ├── msfastbuild.csproj └── msfastbuild.cs ├── license.txt ├── runtests.bat ├── msfastbuild.sln ├── README.md └── .gitignore /tests/stdafx.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" -------------------------------------------------------------------------------- /tests/DependentCppProject/dependentheader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #define DEPENDENT_HEADER 1 -------------------------------------------------------------------------------- /tests/freefunctions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | int NumSquared(int num); 3 | int TemplateAbuserClassFunction(); -------------------------------------------------------------------------------- /msfastbuildvsix/Key.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LendyZhang/msfastbuild/HEAD/msfastbuildvsix/Key.snk -------------------------------------------------------------------------------- /tests/TestStaticLibrary/staticlibfunctions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | int _cdecl StaticLibraryFunction(int arg1); -------------------------------------------------------------------------------- /tests/unitytest.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | int UnityFileFunction() 4 | { 5 | return 0xDEADBEEF; 6 | } -------------------------------------------------------------------------------- /msfastbuild/msfastbuild.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LendyZhang/msfastbuild/HEAD/msfastbuild/msfastbuild.snk -------------------------------------------------------------------------------- /msfastbuildvsix/Microsoft.Build.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LendyZhang/msfastbuild/HEAD/msfastbuildvsix/Microsoft.Build.dll -------------------------------------------------------------------------------- /tests/stdafx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #if _WIN64 4 | #define TRAILINGSPACE 1; 5 | #define SPACEDEFINE " " 6 | #endif -------------------------------------------------------------------------------- /msfastbuildvsix/Resources/FASTBuild.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LendyZhang/msfastbuild/HEAD/msfastbuildvsix/Resources/FASTBuild.png -------------------------------------------------------------------------------- /tests/TestDynamicLibrary/dynamiclibfunctions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | __declspec(dllexport) int __cdecl DynamicLibraryFunction(int argument); -------------------------------------------------------------------------------- /msfastbuildvsix/Microsoft.Build.Framework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LendyZhang/msfastbuild/HEAD/msfastbuildvsix/Microsoft.Build.Framework.dll -------------------------------------------------------------------------------- /msfastbuild/Microsoft.Build.CPPTasks.Common.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LendyZhang/msfastbuild/HEAD/msfastbuild/Microsoft.Build.CPPTasks.Common.dll -------------------------------------------------------------------------------- /msfastbuildvsix/Microsoft.Build.Tasks.Core.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LendyZhang/msfastbuild/HEAD/msfastbuildvsix/Microsoft.Build.Tasks.Core.dll -------------------------------------------------------------------------------- /msfastbuildvsix/Resources/FASTBuildPackage.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LendyZhang/msfastbuild/HEAD/msfastbuildvsix/Resources/FASTBuildPackage.ico -------------------------------------------------------------------------------- /msfastbuildvsix/Microsoft.Build.Utilities.Core.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LendyZhang/msfastbuild/HEAD/msfastbuildvsix/Microsoft.Build.Utilities.Core.dll -------------------------------------------------------------------------------- /msfastbuildvsix/System.Collections.Immutable.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LendyZhang/msfastbuild/HEAD/msfastbuildvsix/System.Collections.Immutable.dll -------------------------------------------------------------------------------- /msfastbuildvsix/System.Threading.Tasks.Dataflow.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LendyZhang/msfastbuild/HEAD/msfastbuildvsix/System.Threading.Tasks.Dataflow.dll -------------------------------------------------------------------------------- /tests/TestDynamicLibrary/dynamiclibfunctions.cpp: -------------------------------------------------------------------------------- 1 | #include "dynamiclibfunctions.h" 2 | int __cdecl DynamicLibraryFunction(int argument) 3 | { 4 | return argument - 1; 5 | } -------------------------------------------------------------------------------- /msfastbuild/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /msfastbuild/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /tests/DependentCppProject/DependentCppProject.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /tests/TestStaticLibrary/TestStaticLibrary.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /tests/TestDynamicLibrary/TestDynamicLibrary.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /tests/main.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "freefunctions.h" 3 | #include "dependentheader.h" 4 | 5 | int main(int argc, char * argv[]) 6 | { 7 | printf("Hi mom!"); 8 | TemplateAbuserClassFunction(); 9 | return 0; 10 | } 11 | 12 | #if !defined(SPACEDEFINE) 13 | #error SPACEDEFINE failed 14 | #endif 15 | #if !defined(DEPENDENT_HEADER) 16 | #error DEPENDENT_HEADER failed 17 | #endif -------------------------------------------------------------------------------- /msfastbuildvsix/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /tests/DependentCppProject/main.cpp: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | #include "../TestStaticLibrary/staticlibfunctions.h" 3 | #include "../TestDynamicLibrary/dynamiclibfunctions.h" 4 | 5 | int main(int argc, char * argv[]) 6 | { 7 | StaticLibraryFunction(1); 8 | DynamicLibraryFunction(1); 9 | printf("DependentCpp project says hello!"); 10 | return 0; 11 | } 12 | 13 | #if _DEBUG && !defined(_WIN64) 14 | #if !defined(MSFBPROPSHEET) 15 | #error Property sheet failure. 16 | #endif 17 | #endif -------------------------------------------------------------------------------- /msfastbuildvsix/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /tests/TestCppProject.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/DependentCppProject/DependentCppPropertySheet.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | _MBCS;MSFBPROPSHEET;%(PreprocessorDefinitions) 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /tests/TestStaticLibrary/staticlibfunctions.cpp: -------------------------------------------------------------------------------- 1 | //The static library is build with Visual Studio 2013 2 | 3 | int _cdecl StaticLibraryFunction(int arg1) 4 | { 5 | return arg1 * 10; 6 | } 7 | 8 | #define STRING2(x) #x 9 | #define STRING(x) STRING2(x) 10 | #pragma message("Platform toolset is " STRING(_MSC_PLATFORM_TOOLSET)) 11 | 12 | #if _DEBUG 13 | #if _MSC_PLATFORM_TOOLSET != 120 14 | #error Wrong toolset! Expected 120 15 | #endif 16 | #endif 17 | 18 | #if !_DEBUG 19 | #if _MSC_PLATFORM_TOOLSET != 140 20 | #error Wrong toolset! Expected 140 21 | #endif 22 | #endif -------------------------------------------------------------------------------- /tests/freefunctions.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | //This file doesn't use the PCH (although it's included...) 3 | 4 | int NumSquared(int num) 5 | { 6 | return num * num; 7 | } 8 | 9 | template 10 | struct TemplateAbuserClass 11 | { 12 | TemplateAbuserClass() :val(1) {} 13 | int val; 14 | 15 | TemplateAbuserClass x; 16 | TemplateAbuserClass y; 17 | }; 18 | template <> struct TemplateAbuserClass<0> 19 | { 20 | char a; 21 | }; 22 | template <> struct TemplateAbuserClass<1> 23 | { 24 | char a; 25 | }; 26 | 27 | int TemplateAbuserClassFunction() 28 | { 29 | TemplateAbuserClass<40> b; 30 | return b.val; 31 | } -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Known Shippable (Yassine Riahi and Liam Flookes) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THESOFTWARE. -------------------------------------------------------------------------------- /msfastbuildvsix/license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Known Shippable (Yassine Riahi and Liam Flookes) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /msfastbuildvsix/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("msfastbuildvsix")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("msfastbuildvsix")] 13 | [assembly: AssemblyCopyright("")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // Version information for an assembly consists of the following four values: 23 | // 24 | // Major Version 25 | // Minor Version 26 | // Build Number 27 | // Revision 28 | // 29 | // You can specify all the values or you can default the Build and Revision Numbers 30 | // by using the '*' as shown below: 31 | // [assembly: AssemblyVersion("1.0.*")] 32 | [assembly: AssemblyVersion("1.0.0.0")] 33 | [assembly: AssemblyFileVersion("1.0.0.0")] 34 | -------------------------------------------------------------------------------- /msfastbuild/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("msfastbuild")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("msfastbuild")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("6666c056-1c15-4564-84f5-7b46b5f14d18")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /runtests.bat: -------------------------------------------------------------------------------- 1 | set ShouldPause=1 2 | set FBPath="E:\fastbuild\tmp\x64-Release\Tools\FBuild\FBuildApp\FBuild.exe" 3 | set FBArgs="-dist -ide -clean" 4 | cd %~dp0\externaltests\bees\solution 5 | "%~dp0/msfastbuild/bin/Debug/msfastbuild.exe" -p bees.vcxproj -c Debug -f Win32 -a%FBArgs% -b%FBPath% - true 6 | IF DEFINED ShouldPause pause 7 | cd %~dp0\externaltests\SDL2-2.0.4\VisualC\SDL\ 8 | "%~dp0/msfastbuild/bin/Debug/msfastbuild.exe" -p SDL.vcxproj -c Debug -f Win32 -a%FBArgs% -b%FBPath% 9 | IF DEFINED ShouldPause pause 10 | "%~dp0/msfastbuild/bin/Debug/msfastbuild.exe" -p SDL.vcxproj -c Release -f x64 -a%FBArgs% -b%FBPath% 11 | IF DEFINED ShouldPause pause 12 | cd %~dp0\externaltests\lz4-r131\visual\2012\lz4\ 13 | "%~dp0/msfastbuild/bin/Debug/msfastbuild.exe" -p lz4.vcxproj -c Debug -f Win32 -a%FBArgs% -b%FBPath% 14 | IF DEFINED ShouldPause pause 15 | cd %~dp0\externaltests\notepad-plus-plus\PowerEditor\visual.net\ 16 | "%~dp0/msfastbuild/bin/Debug/msfastbuild.exe" -p notepadPlus.vs2015.vcxproj -c "Unicode Debug" -f Win32 -a%FBArgs% -b%FBPath% 17 | IF DEFINED ShouldPause pause 18 | cd %~dp0\externaltests\zlib-1.2.8\contrib\vstudio\vc11\ 19 | "%~dp0/msfastbuild/bin/Debug/msfastbuild.exe" -p zlibstat.vcxproj -c Debug -f Win32 -a%FBArgs% -b%FBPath% 20 | IF DEFINED ShouldPause pause 21 | "%~dp0/msfastbuild/bin/Debug/msfastbuild.exe" -p zlibstat.vcxproj -c Release -f x64 -a%FBArgs% -b%FBPath% 22 | IF DEFINED ShouldPause pause 23 | "%~dp0/msfastbuild/bin/Debug/msfastbuild.exe" -p zlibvc.vcxproj -c Debug -f Win32 -a%FBArgs% -b%FBPath% 24 | IF DEFINED ShouldPause pause 25 | "%~dp0/msfastbuild/bin/Debug/msfastbuild.exe" -p zlibvc.vcxproj -c Release -f x64 -a%FBArgs% -b%FBPath% 26 | IF DEFINED ShouldPause pause -------------------------------------------------------------------------------- /msfastbuild.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.757 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "msfastbuild", "msfastbuild\msfastbuild.csproj", "{6666C056-1C15-4564-84F5-7B46B5F14D18}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "msfastbuildvsix", "msfastbuildvsix\msfastbuildvsix.csproj", "{C3B9AE8D-D192-4796-94C0-3DD192F8E7AE}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {6666C056-1C15-4564-84F5-7B46B5F14D18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {6666C056-1C15-4564-84F5-7B46B5F14D18}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {6666C056-1C15-4564-84F5-7B46B5F14D18}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {6666C056-1C15-4564-84F5-7B46B5F14D18}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {C3B9AE8D-D192-4796-94C0-3DD192F8E7AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {C3B9AE8D-D192-4796-94C0-3DD192F8E7AE}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {C3B9AE8D-D192-4796-94C0-3DD192F8E7AE}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {C3B9AE8D-D192-4796-94C0-3DD192F8E7AE}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {D057C11E-CC52-44CE-A6DE-A2A2D5E7DCDE} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /msfastbuildvsix/stylesheet.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | border: 0; 5 | color: #1E1E1E; 6 | font-size: 13px; 7 | font-family: "Segoe UI", Helvetica, Arial, sans-serif; 8 | line-height: 1.45; 9 | word-wrap: break-word; 10 | } 11 | 12 | /* General & 'Reset' Stuff */ 13 | 14 | 15 | .container { 16 | width: 980px; 17 | margin: 0 auto; 18 | } 19 | 20 | section { 21 | display: block; 22 | margin: 0; 23 | } 24 | 25 | h1, h2, h3, h4, h5, h6 { 26 | margin: 0; 27 | } 28 | 29 | /* Header,
30 | header - container 31 | h1 - project name 32 | h2 - project description 33 | */ 34 | 35 | #header { 36 | color: #FFF; 37 | background: #68217a; 38 | position:relative; 39 | } 40 | #hangcloud { 41 | width: 190px; 42 | height: 160px; 43 | background: url("../images/bannerart03.png"); 44 | position: absolute; 45 | top: 0; 46 | right: -30px; 47 | } 48 | h1, h2 { 49 | font-family: "Segoe UI Light", "Segoe UI", Helvetica, Arial, sans-serif; 50 | line-height: 1; 51 | margin: 0 18px; 52 | padding: 0; 53 | } 54 | #header h1 { 55 | font-size: 3.4em; 56 | padding-top: 18px; 57 | font-weight: normal; 58 | margin-left: 15px; 59 | } 60 | 61 | #header h2 { 62 | font-size: 1.5em; 63 | margin-top: 10px; 64 | padding-bottom: 18px; 65 | font-weight: normal; 66 | } 67 | 68 | 69 | #main_content { 70 | width: 100%; 71 | display: flex; 72 | flex-direction: row; 73 | } 74 | 75 | 76 | h1, h2, h3, h4, h5, h6 { 77 | font-weight: bolder; 78 | } 79 | 80 | #main_content h1 { 81 | font-size: 1.8em; 82 | margin-top: 34px; 83 | } 84 | 85 | #main_content h1:first-child { 86 | margin-top: 30px; 87 | } 88 | 89 | #main_content h2 { 90 | font-size: 1.4em; 91 | font-weight: bold; 92 | } 93 | p, ul { 94 | margin: 11px 18px; 95 | } 96 | 97 | #main_content a { 98 | color: #06C; 99 | text-decoration: none; 100 | } 101 | ul { 102 | margin-top: 13px; 103 | margin-left: 18px; 104 | padding-left: 0; 105 | } 106 | ul li { 107 | margin-left: 18px; 108 | padding-left: 0; 109 | } 110 | #lpanel { 111 | width: 620px; 112 | float: left; 113 | } 114 | #rpanel ul { 115 | list-style-type: none; 116 | width: 300px; 117 | } 118 | #rpanel ul li { 119 | line-height: 1.8em; 120 | } 121 | #rpanel { 122 | background: #e7e7e7; 123 | width: 360px; 124 | float: right; 125 | } 126 | 127 | #rpanel div { 128 | width: 300px; 129 | } 130 | -------------------------------------------------------------------------------- /msfastbuildvsix/source.extension.vsixmanifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | msfastbuildvsix 6 | Utility to allow distributed builds and caching using FASTBuild from Visual Studio. 7 | https://github.com/LendyZhang/msfastbuild 8 | license.txt 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![msfastbuild example image](http://liam.flookes.com/msfastbuild.png "msfastbuild example") 2 | 3 | msfastbuild is a utility to make it easier to use [FASTBuild](https://github.com/fastbuild/fastbuild) with Visual Studio vcxproj and solution files. The goal is to be able to take advantage of FASTBuild's nifty caching and distribution without needing to hack out a bff file (FASTBuild's build file format) as it can be confusing at first and annoying if it's not your project or you already have everything in your project files. 4 | 5 | The bff file it generates can also be a good starting point for a custom made bff file. msfastbuild hashes the Visual Studio projects so it will only regenerate the bff file if things change and can take advantage of FASTBuild's speedy 'nothing to build' checks. 6 | 7 | It's a work in progress, but it has been used successfully with the majority of Visual Studio 2015 projects attempted. The VSIX plugin for Visual Studio 2015 adds "FASTBuild Project" and "FASTBuild solution" options to the Build menu, and it should also be usable from the commandline. 8 | 9 | ## Setup 10 | 11 | To use msfastbuild you need Visual Studio 2015 R3 installed. It relies on being able to find msbuild. 12 | 13 | You need the [FBuild.exe](http://fastbuild.org/docs/download.html) either somewhere in your path, or to specify where it is using the -b argument on the commandline, or in VSIX msfastbuild options if you are using the VSIX. 14 | 15 | By default msfastbuild passes -dist to FASTBuild. This can be overriden in the VSIX options or with the -a option on the command line. 16 | 17 | ## VSIX Usage 18 | 19 | To use msfastbuild from within Visual Studio, simply install the VSIX and either set the FBuild.exe path in the VSIX options, or have it in your path. 20 | 21 | ## Command line usage 22 | 23 | If you were building say... SDL with the following command line: 24 | 25 | `$>msbuild SDL.sln /p:Configuration=Debug;Platform=Win32` 26 | 27 | with msfastbuild you would build with: 28 | 29 | `$>msfastbuild -s ./SDL.sln -c Debug -f Win32` 30 | 31 | To select only one project in the solution and provide different FASTBuild arguments: 32 | 33 | `$>msfastbuild -s ./SDL.sln -p ./SDLMain/SDLMain.vcxproj -c Debug -f Win32 -a"-dist -ide"` 34 | 35 | ## Quirks 36 | 37 | Some of these may be addressed as time goes by: 38 | 39 | - You need Visual Studio 2015 R3 installed, even if you're building against the 2013 tools. Things requiring 2012 tools do not build correctly. They could build without a huge amount of work, it just hasn't been done. 40 | - Pre-link build events are not supported: I don't see a good way to inject it into the BFF without modifying FASTBuild. 41 | - The "Use Library Dependency Inputs" option for project dependencies is not supported. For the most part everything will still build, but /INCREMENTAL linking will not be as effective if you are changing the libraries frequently. 42 | - The AssemblerListingLocation option for compiling is not supported, remote builders complain. 43 | - The DesigntimePreprocessorDefinitions option for resource compiling is not supported. 44 | - ProfileGuidedDatabase linking option is not supported as it was parsing strangely, and I think may require checking the global solution settings. 45 | - Completely ignores MIDL. 46 | - There's a lot of weird vcxproj/solutions doing weird things I'm not handling correctly. 47 | 48 | ## Buildable projects 49 | 50 | Some of these were modified to use VS2015: 51 | 52 | - SDL2 53 | - Zlib 54 | - LZ4 55 | - Doom3 56 | - Beegame (which is mine... :)) 57 | - Handmade Quake 58 | - Gross middleware 59 | - cocos2d-x, required moving the prelink event to prebuild... which seemed fine, and adjusting some "int/\*bool\*/param" type constructs which preprocess oddly 60 | 61 | ## WIP 62 | 63 | There's a lot of room for improvement, but if there's a VS2015 project that doesn't work... let me know and I'll see if I can hack out why! Pull requests of course are very welcome! :) 64 | -------------------------------------------------------------------------------- /tests/TestMsfastbuild.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestCppProject", "TestCppProject.vcxproj", "{4B63C37C-CAE1-4442-BC2B-CFD11B30E39D}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DependentCppProject", "DependentCppProject\DependentCppProject.vcxproj", "{F441131C-E64E-4FE6-9BD9-F5A287FD0297}" 9 | ProjectSection(ProjectDependencies) = postProject 10 | {4B63C37C-CAE1-4442-BC2B-CFD11B30E39D} = {4B63C37C-CAE1-4442-BC2B-CFD11B30E39D} 11 | {981D6FCF-4490-4E09-A70B-B85541A2787C} = {981D6FCF-4490-4E09-A70B-B85541A2787C} 12 | EndProjectSection 13 | EndProject 14 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestStaticLibrary", "TestStaticLibrary\TestStaticLibrary.vcxproj", "{981D6FCF-4490-4E09-A70B-B85541A2787C}" 15 | EndProject 16 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestDynamicLibrary", "TestDynamicLibrary\TestDynamicLibrary.vcxproj", "{31C8580F-CB13-4A99-BEEA-EB2BD0BBADE6}" 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug|x64 = Debug|x64 21 | Debug|x86 = Debug|x86 22 | Release|x64 = Release|x64 23 | Release|x86 = Release|x86 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {4B63C37C-CAE1-4442-BC2B-CFD11B30E39D}.Debug|x64.ActiveCfg = Debug|x64 27 | {4B63C37C-CAE1-4442-BC2B-CFD11B30E39D}.Debug|x64.Build.0 = Debug|x64 28 | {4B63C37C-CAE1-4442-BC2B-CFD11B30E39D}.Debug|x86.ActiveCfg = Debug|Win32 29 | {4B63C37C-CAE1-4442-BC2B-CFD11B30E39D}.Debug|x86.Build.0 = Debug|Win32 30 | {4B63C37C-CAE1-4442-BC2B-CFD11B30E39D}.Release|x64.ActiveCfg = Release|x64 31 | {4B63C37C-CAE1-4442-BC2B-CFD11B30E39D}.Release|x64.Build.0 = Release|x64 32 | {4B63C37C-CAE1-4442-BC2B-CFD11B30E39D}.Release|x86.ActiveCfg = Release|Win32 33 | {4B63C37C-CAE1-4442-BC2B-CFD11B30E39D}.Release|x86.Build.0 = Release|Win32 34 | {F441131C-E64E-4FE6-9BD9-F5A287FD0297}.Debug|x64.ActiveCfg = Debug|x64 35 | {F441131C-E64E-4FE6-9BD9-F5A287FD0297}.Debug|x64.Build.0 = Debug|x64 36 | {F441131C-E64E-4FE6-9BD9-F5A287FD0297}.Debug|x86.ActiveCfg = Debug|Win32 37 | {F441131C-E64E-4FE6-9BD9-F5A287FD0297}.Debug|x86.Build.0 = Debug|Win32 38 | {F441131C-E64E-4FE6-9BD9-F5A287FD0297}.Release|x64.ActiveCfg = Release|x64 39 | {F441131C-E64E-4FE6-9BD9-F5A287FD0297}.Release|x64.Build.0 = Release|x64 40 | {F441131C-E64E-4FE6-9BD9-F5A287FD0297}.Release|x86.ActiveCfg = Release|Win32 41 | {F441131C-E64E-4FE6-9BD9-F5A287FD0297}.Release|x86.Build.0 = Release|Win32 42 | {981D6FCF-4490-4E09-A70B-B85541A2787C}.Debug|x64.ActiveCfg = Debug|x64 43 | {981D6FCF-4490-4E09-A70B-B85541A2787C}.Debug|x64.Build.0 = Debug|x64 44 | {981D6FCF-4490-4E09-A70B-B85541A2787C}.Debug|x86.ActiveCfg = Debug|Win32 45 | {981D6FCF-4490-4E09-A70B-B85541A2787C}.Debug|x86.Build.0 = Debug|Win32 46 | {981D6FCF-4490-4E09-A70B-B85541A2787C}.Release|x64.ActiveCfg = Release|x64 47 | {981D6FCF-4490-4E09-A70B-B85541A2787C}.Release|x64.Build.0 = Release|x64 48 | {981D6FCF-4490-4E09-A70B-B85541A2787C}.Release|x86.ActiveCfg = Release|Win32 49 | {981D6FCF-4490-4E09-A70B-B85541A2787C}.Release|x86.Build.0 = Release|Win32 50 | {31C8580F-CB13-4A99-BEEA-EB2BD0BBADE6}.Debug|x64.ActiveCfg = Debug|x64 51 | {31C8580F-CB13-4A99-BEEA-EB2BD0BBADE6}.Debug|x64.Build.0 = Debug|x64 52 | {31C8580F-CB13-4A99-BEEA-EB2BD0BBADE6}.Debug|x86.ActiveCfg = Debug|Win32 53 | {31C8580F-CB13-4A99-BEEA-EB2BD0BBADE6}.Debug|x86.Build.0 = Debug|Win32 54 | {31C8580F-CB13-4A99-BEEA-EB2BD0BBADE6}.Release|x64.ActiveCfg = Release|x64 55 | {31C8580F-CB13-4A99-BEEA-EB2BD0BBADE6}.Release|x64.Build.0 = Release|x64 56 | {31C8580F-CB13-4A99-BEEA-EB2BD0BBADE6}.Release|x86.ActiveCfg = Release|Win32 57 | {31C8580F-CB13-4A99-BEEA-EB2BD0BBADE6}.Release|x86.Build.0 = Release|Win32 58 | EndGlobalSection 59 | GlobalSection(SolutionProperties) = preSolution 60 | HideSolutionNode = FALSE 61 | EndGlobalSection 62 | EndGlobal 63 | -------------------------------------------------------------------------------- /msfastbuildvsix/FASTBuildPackage.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Liam Flookes and Yassine Riahi 2 | // Available under an MIT license. See license file on github for details. 3 | 4 | using System; 5 | using System.ComponentModel; 6 | using System.Diagnostics.CodeAnalysis; 7 | using System.Runtime.InteropServices; 8 | using Microsoft.VisualStudio.Shell; 9 | 10 | using EnvDTE; 11 | using EnvDTE80; 12 | 13 | namespace msfastbuildvsix 14 | { 15 | public class OptionPageGrid : DialogPage 16 | { 17 | private string FBArgs = "-dist -ide -monitor"; 18 | private string FBPath = "FBuild.exe"; 19 | private bool FBUnity = false; 20 | 21 | [Category("Options")] 22 | [DisplayName("FASTBuild arguments")] 23 | [Description("Arguments that will be passed to FASTBuild, default \"-dist -ide -monitor\"")] 24 | public string OptionFBArgs 25 | { 26 | get { return FBArgs; } 27 | set { FBArgs = value; } 28 | } 29 | 30 | [Category("Options")] 31 | [DisplayName("FBuild.exe path")] 32 | [Description("Specify the path to FBuild.exe")] 33 | public string OptionFBPath 34 | { 35 | get { return FBPath; } 36 | set { FBPath = value; } 37 | } 38 | 39 | [Category("Options")] 40 | [DisplayName("Use unity files")] 41 | [Description("Whether to merge files together to speed up compilation. May require modifying some headers.")] 42 | public bool OptionFBUnity 43 | { 44 | get { return FBUnity; } 45 | set { FBUnity = value; } 46 | } 47 | } 48 | 49 | [PackageRegistration(UseManagedResourcesOnly = true)] 50 | [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] // Info on this package for Help/About 51 | [ProvideMenuResource("Menus.ctmenu", 1)] 52 | [Guid(FASTBuildPackage.PackageGuidString)] 53 | [ProvideOptionPage(typeof(OptionPageGrid), "FASTBuild", "General", 0, 0, true)] 54 | [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "pkgdef, VS and vsixmanifest are valid VS terms")] 55 | public sealed class FASTBuildPackage : Package 56 | { 57 | /// 58 | /// FASTBuildPackage GUID string. 59 | /// 60 | public const string PackageGuidString = "b5f4430f-5f92-4bf7-8c27-ed6e0eadacdc"; 61 | 62 | public DTE2 m_dte; 63 | public OutputWindowPane m_outputPane; 64 | 65 | /// 66 | /// Initializes a new instance of the class. 67 | /// 68 | public FASTBuildPackage() 69 | { 70 | // Inside this method you can place any initialization code that does not require 71 | // any Visual Studio service because at this point the package object is created but 72 | // not sited yet inside Visual Studio environment. The place to do all the other 73 | // initialization is the Initialize method. 74 | } 75 | 76 | public string OptionFBArgs 77 | { 78 | get 79 | { 80 | OptionPageGrid page = (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid)); 81 | return page.OptionFBArgs; 82 | } 83 | } 84 | 85 | public string OptionFBPath 86 | { 87 | get 88 | { 89 | OptionPageGrid page = (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid)); 90 | return page.OptionFBPath; 91 | } 92 | } 93 | 94 | public bool OptionFBUnity 95 | { 96 | get 97 | { 98 | OptionPageGrid page = (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid)); 99 | return page.OptionFBUnity; 100 | } 101 | } 102 | 103 | #region Package Members 104 | 105 | /// 106 | /// Initialization of the package; this method is called right after the package is sited, so this is the place 107 | /// where you can put all the initialization code that rely on services provided by VisualStudio. 108 | /// 109 | protected override void Initialize() 110 | { 111 | FASTBuild.Initialize(this); 112 | base.Initialize(); 113 | 114 | m_dte = (DTE2)GetService(typeof(DTE)); 115 | OutputWindow outputWindow = m_dte.ToolWindows.OutputWindow; 116 | 117 | m_outputPane = outputWindow.OutputWindowPanes.Add("FASTBuild"); 118 | m_outputPane.OutputString("FASTBuild\r"); 119 | } 120 | 121 | #endregion 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /msfastbuild/msfastbuild.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {6666C056-1C15-4564-84F5-7B46B5F14D18} 8 | Exe 9 | Properties 10 | msfastbuild 11 | msfastbuild 12 | v4.7.2 13 | 512 14 | true 15 | 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | TRACE;DEBUG;NULL_FASTBUILD_OUTPUT 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE;NULL_FASTBUILD_OUTPUT 33 | prompt 34 | 4 35 | 36 | 37 | true 38 | 39 | 40 | msfastbuild.snk 41 | 42 | 43 | 44 | ..\packages\CommandLineParser.1.9.71\lib\net45\CommandLine.dll 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | PreserveNewest 71 | 72 | 73 | 74 | 81 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | 254 | # ========================= 255 | # Operating System Files 256 | # ========================= 257 | 258 | # OSX 259 | # ========================= 260 | 261 | .DS_Store 262 | .AppleDouble 263 | .LSOverride 264 | 265 | # Thumbnails 266 | ._* 267 | 268 | # Files that might appear in the root of a volume 269 | .DocumentRevisions-V100 270 | .fseventsd 271 | .Spotlight-V100 272 | .TemporaryItems 273 | .Trashes 274 | .VolumeIcon.icns 275 | 276 | # Directories potentially created on remote AFP share 277 | .AppleDB 278 | .AppleDesktop 279 | Network Trash Folder 280 | Temporary Items 281 | .apdisk 282 | 283 | # Windows 284 | # ========================= 285 | 286 | # Windows image file caches 287 | Thumbs.db 288 | ehthumbs.db 289 | 290 | # Folder config file 291 | Desktop.ini 292 | 293 | # Recycle Bin used on file shares 294 | $RECYCLE.BIN/ 295 | 296 | # Windows Installer files 297 | *.cab 298 | *.msi 299 | *.msm 300 | *.msp 301 | 302 | # Windows shortcuts 303 | *.lnk 304 | 305 | externaltests/* 306 | tests/**/*.fdb 307 | tests/**/*.bat 308 | tests/**/*.bff 309 | tests/**/*.txt 310 | -------------------------------------------------------------------------------- /tests/DependentCppProject/DependentCppProject.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {F441131C-E64E-4FE6-9BD9-F5A287FD0297} 23 | DependentCppProject 24 | 8.1 25 | 26 | 27 | 28 | Application 29 | true 30 | v140 31 | MultiByte 32 | 33 | 34 | Application 35 | false 36 | v140 37 | true 38 | MultiByte 39 | 40 | 41 | Application 42 | true 43 | v140 44 | MultiByte 45 | 46 | 47 | Application 48 | false 49 | v140 50 | true 51 | MultiByte 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | Level3 79 | Disabled 80 | true 81 | 82 | 83 | 84 | 85 | Level3 86 | Disabled 87 | true 88 | 89 | 90 | 91 | 92 | Level3 93 | MaxSpeed 94 | true 95 | true 96 | true 97 | 98 | 99 | true 100 | true 101 | 102 | 103 | 104 | 105 | Level3 106 | MaxSpeed 107 | true 108 | true 109 | true 110 | 111 | 112 | true 113 | true 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | {31c8580f-cb13-4a99-beea-eb2bd0bbade6} 122 | 123 | 124 | {981d6fcf-4490-4e09-a70b-b85541a2787c} 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /tests/TestStaticLibrary/TestStaticLibrary.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {981D6FCF-4490-4E09-A70B-B85541A2787C} 23 | TestStaticLibrary 24 | 8.1 25 | 26 | 27 | 28 | StaticLibrary 29 | true 30 | v120 31 | MultiByte 32 | 33 | 34 | StaticLibrary 35 | false 36 | v140 37 | true 38 | MultiByte 39 | 40 | 41 | StaticLibrary 42 | true 43 | v120 44 | MultiByte 45 | 46 | 47 | StaticLibrary 48 | false 49 | v140 50 | true 51 | MultiByte 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | Level3 75 | Disabled 76 | true 77 | _MBCS;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);%(PreprocessorDefinitions) 78 | 79 | 80 | 81 | 82 | Level3 83 | Disabled 84 | true 85 | _MBCS;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);%(PreprocessorDefinitions) 86 | 87 | 88 | 89 | 90 | Level3 91 | MaxSpeed 92 | true 93 | true 94 | true 95 | _MBCS;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);%(PreprocessorDefinitions) 96 | 97 | 98 | true 99 | true 100 | 101 | 102 | 103 | 104 | Level3 105 | MaxSpeed 106 | true 107 | true 108 | true 109 | _MBCS;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);%(PreprocessorDefinitions) 110 | 111 | 112 | true 113 | true 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /msfastbuildvsix/FASTBuildPackage.vsct: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | 26 | 33 | 34 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 53 | 54 | 61 | 68 | 69 | 76 | 77 | 84 | 85 | 92 | 93 | 94 | 95 | 96 | 97 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /msfastbuildvsix/VSPackage.resx: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | text/microsoft-resx 120 | 121 | 122 | 2.0 123 | 124 | 125 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 126 | 127 | 128 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 129 | 130 | 131 | 132 | FASTBuild Extension 133 | 134 | 135 | FASTBuild Visual Studio Extension Detailed Info 136 | 137 | 138 | Resources\FASTBuildPackage.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 139 | 140 | -------------------------------------------------------------------------------- /tests/TestDynamicLibrary/TestDynamicLibrary.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {31C8580F-CB13-4A99-BEEA-EB2BD0BBADE6} 23 | Win32Proj 24 | TestDynamicLibrary 25 | 8.1 26 | 27 | 28 | 29 | DynamicLibrary 30 | true 31 | v140 32 | Unicode 33 | 34 | 35 | DynamicLibrary 36 | false 37 | v140 38 | true 39 | Unicode 40 | 41 | 42 | DynamicLibrary 43 | true 44 | v140 45 | Unicode 46 | 47 | 48 | DynamicLibrary 49 | false 50 | v140 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | true 77 | 78 | 79 | false 80 | 81 | 82 | false 83 | 84 | 85 | 86 | 87 | 88 | Level3 89 | Disabled 90 | WIN32;_DEBUG;_WINDOWS;_USRDLL;TESTDYNAMICLIBRARY_EXPORTS;%(PreprocessorDefinitions) 91 | true 92 | 93 | 94 | Windows 95 | true 96 | 97 | 98 | 99 | 100 | 101 | 102 | Level3 103 | Disabled 104 | _DEBUG;_WINDOWS;_USRDLL;TESTDYNAMICLIBRARY_EXPORTS;%(PreprocessorDefinitions) 105 | true 106 | 107 | 108 | Windows 109 | true 110 | 111 | 112 | 113 | 114 | Level3 115 | 116 | 117 | MaxSpeed 118 | true 119 | true 120 | WIN32;NDEBUG;_WINDOWS;_USRDLL;TESTDYNAMICLIBRARY_EXPORTS;%(PreprocessorDefinitions) 121 | true 122 | 123 | 124 | Windows 125 | true 126 | true 127 | true 128 | 129 | 130 | 131 | 132 | Level3 133 | 134 | 135 | MaxSpeed 136 | true 137 | true 138 | NDEBUG;_WINDOWS;_USRDLL;TESTDYNAMICLIBRARY_EXPORTS;%(PreprocessorDefinitions) 139 | true 140 | 141 | 142 | Windows 143 | true 144 | true 145 | true 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /tests/TestCppProject.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {4B63C37C-CAE1-4442-BC2B-CFD11B30E39D} 24 | TestCppProject 25 | 10.0.16299.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v140 32 | MultiByte 33 | 34 | 35 | Application 36 | false 37 | v140 38 | true 39 | MultiByte 40 | 41 | 42 | Application 43 | true 44 | v140 45 | MultiByte 46 | 47 | 48 | Application 49 | false 50 | v140 51 | true 52 | MultiByte 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | $(SolutionDir)DependentCppProject;$(VC_IncludePath);$(WindowsSDK_IncludePath); 75 | 76 | 77 | $(SolutionDir)DependentCppProject;$(VC_IncludePath);$(WindowsSDK_IncludePath); 78 | 79 | 80 | $(SolutionDir)DependentCppProject;$(VC_IncludePath);$(WindowsSDK_IncludePath); 81 | 82 | 83 | $(SolutionDir)DependentCppProject;$(VC_IncludePath);$(WindowsSDK_IncludePath); 84 | 85 | 86 | 87 | Level3 88 | Disabled 89 | true 90 | true 91 | Use 92 | TRAILINGSPACE =1;SPACEDEFINE=" ";TWOWORD DEFINE;%(PreprocessorDefinitions) 93 | 94 | 95 | echo "Pre-Build Event" 96 | 97 | 98 | echo "Post-Build event" 99 | 100 | 101 | 102 | 103 | Level3 104 | Disabled 105 | true 106 | true 107 | 108 | 109 | 110 | 111 | Level3 112 | MaxSpeed 113 | true 114 | true 115 | true 116 | true 117 | Use 118 | TRAILINGSPACE =1;SPACEDEFINE=" ";TWOWORD DEFINE;%(PreprocessorDefinitions) 119 | 120 | 121 | true 122 | true 123 | 124 | 125 | 126 | 127 | Level3 128 | MaxSpeed 129 | true 130 | true 131 | true 132 | true 133 | 134 | 135 | true 136 | true 137 | 138 | 139 | 140 | 141 | NotUsing 142 | NotUsing 143 | 144 | 145 | 146 | Create 147 | Create 148 | 149 | 150 | NotUsing 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /msfastbuildvsix/FASTBuild.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Liam Flookes and Yassine Riahi 2 | // Available under an MIT license. See license file on github for details. 3 | 4 | using System; 5 | using System.ComponentModel.Design; 6 | using Microsoft.VisualStudio.Shell; 7 | using Microsoft.VisualStudio.VCProjectEngine; 8 | 9 | using System.Reflection; 10 | using System.IO; 11 | using EnvDTE; 12 | using EnvDTE80; 13 | 14 | namespace msfastbuildvsix 15 | { 16 | /// 17 | /// Command handler 18 | /// 19 | internal sealed class FASTBuild 20 | { 21 | /// 22 | /// Command ID. 23 | /// 24 | public const int CommandId = 0x0100; 25 | public const int SlnCommandId = 0x0101; 26 | public const int ContextCommandId = 0x0102; 27 | public const int SlnContextCommandId = 0x0103; 28 | 29 | /// 30 | /// Command menu group (command set GUID). 31 | /// 32 | public static readonly Guid CommandSet = new Guid("7c132991-dea1-4719-8c67-c20b24b6775c"); 33 | 34 | /// 35 | /// VS Package that provides this command, not null. 36 | /// 37 | private readonly Package package; 38 | 39 | /// 40 | /// Initializes a new instance of the class. 41 | /// Adds our command handlers for menu (commands must exist in the command table file) 42 | /// 43 | /// Owner package, not null. 44 | private FASTBuild(Package package) 45 | { 46 | if (package == null) 47 | { 48 | throw new ArgumentNullException("package"); 49 | } 50 | 51 | this.package = package; 52 | 53 | OleMenuCommandService commandService = this.ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService; 54 | if (commandService != null) 55 | { 56 | var menuCommandID = new CommandID(CommandSet, CommandId); 57 | var menuItem = new MenuCommand(this.MenuItemCallback, menuCommandID); 58 | commandService.AddCommand(menuItem); 59 | 60 | menuCommandID = new CommandID(CommandSet, SlnCommandId); 61 | menuItem = new MenuCommand(this.MenuItemCallback, menuCommandID); 62 | commandService.AddCommand(menuItem); 63 | 64 | menuCommandID = new CommandID(CommandSet, ContextCommandId); 65 | menuItem = new MenuCommand(this.MenuItemCallback, menuCommandID); 66 | commandService.AddCommand(menuItem); 67 | 68 | menuCommandID = new CommandID(CommandSet, SlnContextCommandId); 69 | menuItem = new MenuCommand(this.MenuItemCallback, menuCommandID); 70 | commandService.AddCommand(menuItem); 71 | } 72 | } 73 | 74 | /// 75 | /// Gets the instance of the command. 76 | /// 77 | public static FASTBuild Instance 78 | { 79 | get; 80 | private set; 81 | } 82 | 83 | /// 84 | /// Gets the service provider from the owner package. 85 | /// 86 | private IServiceProvider ServiceProvider 87 | { 88 | get 89 | { 90 | return this.package; 91 | } 92 | } 93 | 94 | /// 95 | /// Initializes the singleton instance of the command. 96 | /// 97 | /// Owner package, not null. 98 | public static void Initialize(Package package) 99 | { 100 | Instance = new FASTBuild(package); 101 | } 102 | 103 | [System.Runtime.InteropServices.DllImport("kernel32.dll")] 104 | public static extern int GetSystemDefaultLCID(); 105 | 106 | private bool IsFBuildFindable(string FBuildExePath) 107 | { 108 | string fbuild = "fbuild.exe"; 109 | 110 | if (FBuildExePath.ToLower() != fbuild) 111 | { 112 | return File.Exists(FBuildExePath); 113 | } 114 | 115 | string PathVariable = Environment.GetEnvironmentVariable("PATH"); 116 | foreach (string SearchPath in PathVariable.Split(Path.PathSeparator)) 117 | { 118 | try 119 | { 120 | string PotentialPath = Path.Combine(SearchPath, fbuild); 121 | if (File.Exists(PotentialPath)) 122 | { 123 | return true; 124 | } 125 | } 126 | catch (ArgumentException) 127 | { } 128 | } 129 | return false; 130 | } 131 | 132 | /// 133 | /// This function is the callback used to execute the command when the menu item is clicked. 134 | /// See the constructor to see how the menu item is associated with this function using 135 | /// OleMenuCommandService service and MenuCommand class. 136 | /// 137 | /// Event sender. 138 | /// Event args. 139 | private void MenuItemCallback(object sender, EventArgs e) 140 | { 141 | FASTBuildPackage fbPackage = (FASTBuildPackage)this.package; 142 | if (null == fbPackage.m_dte.Solution) 143 | return; 144 | 145 | MenuCommand eventSender = sender as MenuCommand; 146 | 147 | fbPackage.m_outputPane.Activate(); 148 | fbPackage.m_outputPane.Clear(); 149 | 150 | if (eventSender == null) 151 | { 152 | fbPackage.m_outputPane.OutputString("VSIX failed to cast sender to OleMenuCommand.\r"); 153 | return; 154 | } 155 | 156 | if (fbPackage.m_dte.Debugger.CurrentMode != dbgDebugMode.dbgDesignMode) 157 | { 158 | fbPackage.m_outputPane.OutputString("Build not launched due to active debugger.\r"); 159 | return; 160 | } 161 | 162 | if(!IsFBuildFindable(fbPackage.OptionFBPath)) 163 | { 164 | fbPackage.m_outputPane.OutputString(string.Format("Could not find fbuild at the provided path: {0}, please verify in the msfastbuild options.\r", fbPackage.OptionFBPath)); 165 | return; 166 | } 167 | 168 | fbPackage.m_dte.ExecuteCommand("File.SaveAll"); 169 | 170 | string fbCommandLine = ""; 171 | string fbWorkingDirectory = ""; 172 | 173 | Solution sln = fbPackage.m_dte.Solution; 174 | SolutionBuild sb = sln.SolutionBuild; 175 | SolutionConfiguration2 sc = sb.ActiveConfiguration as SolutionConfiguration2; 176 | VCProject proj = null; 177 | 178 | if (eventSender.CommandID.ID != SlnCommandId && eventSender.CommandID.ID != SlnContextCommandId) 179 | { 180 | if (fbPackage.m_dte.SelectedItems.Count > 0) 181 | { 182 | Project envProj = (fbPackage.m_dte.SelectedItems.Item(1).Project as EnvDTE.Project); 183 | if (envProj != null) 184 | { 185 | proj = envProj.Object as VCProject; 186 | } 187 | } 188 | 189 | if (proj == null) 190 | { 191 | string startupProject = ""; 192 | foreach (String item in (Array)sb.StartupProjects) 193 | { 194 | startupProject += item; 195 | } 196 | proj = sln.Item(startupProject).Object as VCProject; 197 | } 198 | 199 | if (proj == null) 200 | { 201 | fbPackage.m_outputPane.OutputString("No valid vcproj selected for building or set as the startup project.\r"); 202 | return; 203 | } 204 | 205 | fbPackage.m_outputPane.OutputString("Building " + Path.GetFileName(proj.ProjectFile) + " " + sc.Name + " " + sc.PlatformName + "\r"); 206 | fbCommandLine = string.Format("-p \"{0}\" -c {1} -f {2} -s \"{3}\" -a\"{4}\" -b \"{5}\"", Path.GetFileName(proj.ProjectFile), sc.Name, sc.PlatformName, sln.FileName, fbPackage.OptionFBArgs, fbPackage.OptionFBPath); 207 | fbWorkingDirectory = Path.GetDirectoryName(proj.ProjectFile); 208 | } 209 | else 210 | { 211 | fbCommandLine = string.Format("-s \"{0}\" -c {1} -f {2} -a\"{3}\" -b \"{4}\"", sln.FileName, sc.Name, sc.PlatformName, fbPackage.OptionFBArgs, fbPackage.OptionFBPath); 212 | fbWorkingDirectory = Path.GetDirectoryName(sln.FileName); 213 | } 214 | 215 | if(fbPackage.OptionFBUnity) 216 | { 217 | fbCommandLine += " -u true"; 218 | } 219 | 220 | string msfastbuildPath = Assembly.GetAssembly(typeof(msfastbuild.msfastbuild)).Location; 221 | try 222 | { 223 | fbPackage.m_outputPane.OutputString("Launching msfastbuild with command line: " + fbCommandLine + "\r"); 224 | 225 | System.Diagnostics.Process FBProcess = new System.Diagnostics.Process(); 226 | FBProcess.StartInfo.FileName = msfastbuildPath; 227 | FBProcess.StartInfo.Arguments = fbCommandLine; 228 | FBProcess.StartInfo.WorkingDirectory = fbWorkingDirectory; 229 | FBProcess.StartInfo.RedirectStandardOutput = true; 230 | FBProcess.StartInfo.UseShellExecute = false; 231 | FBProcess.StartInfo.CreateNoWindow = true; 232 | var SystemEncoding = System.Globalization.CultureInfo.GetCultureInfo(GetSystemDefaultLCID()).TextInfo.OEMCodePage; 233 | FBProcess.StartInfo.StandardOutputEncoding = System.Text.Encoding.GetEncoding(SystemEncoding); 234 | 235 | System.Diagnostics.DataReceivedEventHandler OutputEventHandler = (Sender, Args) => { 236 | if (Args.Data != null) 237 | fbPackage.m_outputPane.OutputString(Args.Data + "\r"); 238 | }; 239 | 240 | FBProcess.OutputDataReceived += OutputEventHandler; 241 | FBProcess.Start(); 242 | FBProcess.BeginOutputReadLine(); 243 | //FBProcess.WaitForExit(); 244 | } 245 | catch (Exception ex) 246 | { 247 | fbPackage.m_outputPane.OutputString("VSIX exception launching msfastbuild. Could be a broken VSIX? Exception: " + ex.Message + "\r"); 248 | } 249 | } 250 | } 251 | } 252 | -------------------------------------------------------------------------------- /msfastbuildvsix/msfastbuildvsix.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15.0 6 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 7 | 8 | 9 | true 10 | 11 | 12 | 13 | 14 | 14.0 15 | 16 | 17 | 18 | true 19 | 20 | 21 | Key.snk 22 | 23 | 24 | 25 | Debug 26 | AnyCPU 27 | 2.0 28 | {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 29 | {C3B9AE8D-D192-4796-94C0-3DD192F8E7AE} 30 | Library 31 | Properties 32 | msfastbuildvsix 33 | msfastbuildvsix 34 | v4.7.2 35 | true 36 | true 37 | true 38 | true 39 | true 40 | false 41 | 42 | 43 | true 44 | full 45 | false 46 | bin\Debug\ 47 | DEBUG;TRACE 48 | prompt 49 | 4 50 | 51 | 52 | pdbonly 53 | true 54 | bin\Release\ 55 | TRACE 56 | prompt 57 | 4 58 | 59 | 60 | 61 | 62 | Component 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | Designer 72 | 73 | 74 | 75 | 76 | Always 77 | true 78 | 79 | 80 | Always 81 | true 82 | 83 | 84 | Menus.ctmenu 85 | Designer 86 | 87 | 88 | Always 89 | true 90 | 91 | 92 | Always 93 | true 94 | 95 | 96 | Always 97 | true 98 | 99 | 100 | Always 101 | true 102 | 103 | 104 | Always 105 | true 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | False 114 | 115 | 116 | False 117 | 118 | 119 | False 120 | 121 | 122 | False 123 | 124 | 125 | 126 | 127 | False 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | True 140 | 141 | 142 | True 143 | 144 | 145 | True 146 | 147 | 148 | True 149 | 150 | 151 | True 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | True 162 | 163 | 164 | False 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | true 176 | VSPackage 177 | 178 | 179 | 180 | 181 | {6666c056-1c15-4564-84f5-7b46b5f14d18} 182 | msfastbuild 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 210 | -------------------------------------------------------------------------------- /msfastbuild/msfastbuild.cs: -------------------------------------------------------------------------------- 1 | // msfastbuild.cs - Generates and executes a bff file for fastbuild from a .sln or .vcxproj. 2 | // Copyright 2016 Liam Flookes and Yassine Riahi 3 | // Available under an MIT license. See license file on github for details. 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using CommandLine; 8 | using CommandLine.Text; 9 | using System.IO; 10 | using System.Reflection; 11 | using System.Text; 12 | 13 | using Microsoft.Build.Evaluation; 14 | using Microsoft.Build.Construction; 15 | using Microsoft.Build.Utilities; 16 | 17 | namespace msfastbuild 18 | { 19 | public class Options 20 | { 21 | [Option('p', "vcproject", DefaultValue = "", 22 | HelpText = "Path of .vcxproj file to build, or project name if a solution is provided.")] 23 | public string Project { get; set; } 24 | 25 | [Option('s', "sln", DefaultValue = "", 26 | HelpText = "Path of .sln file which contains the projects.")] 27 | public string Solution { get; set; } 28 | 29 | [Option('c', "config", DefaultValue = "Debug", 30 | HelpText = "Configuration to build.")] 31 | public string Config { get; set; } 32 | 33 | [Option('f', "platform", DefaultValue = "Win32", 34 | HelpText = "Platform to build.")] 35 | public string Platform { get; set; } 36 | 37 | [Option('a', "fbargs", DefaultValue = "-dist", 38 | HelpText = "Arguments that pass through to FASTBuild.")] 39 | public string FBArgs { get; set; } 40 | 41 | [Option('g', "generateonly", DefaultValue = false, 42 | HelpText = "Generate bff file only, without calling FASTBuild.")] 43 | public bool GenerateOnly { get; set; } 44 | 45 | [Option('r', "regen", DefaultValue = false, 46 | HelpText = "Regenerate bff file even when the project hasn't changed.")] 47 | public bool AlwaysRegenerate { get; set; } 48 | 49 | [Option('b', "fbpath", DefaultValue = @"FBuild.exe", 50 | HelpText = "Path to FASTBuild executable.")] 51 | public string FBPath { get; set; } 52 | 53 | [Option('u', "unity", DefaultValue = false, 54 | HelpText = "Whether to combine files into a unity step. May substantially improve compilation time, but not all projects are suitable.")] 55 | public bool UseUnity { get; set; } 56 | 57 | [HelpOption] 58 | public string GetUsage() 59 | { 60 | return HelpText.AutoBuild(this,(HelpText current) => HelpText.DefaultParsingErrorsHandler(this, current)); 61 | } 62 | } 63 | 64 | public class msfastbuild 65 | { 66 | static public string PlatformToolsetVersion = "140"; 67 | static public string VCBasePath = ""; 68 | static public string VCExePath = ""; 69 | static public string BFFOutputFilePath = "fbuild.bff"; 70 | static public Options CommandLineOptions = new Options(); 71 | static public string WindowsSDKTarget = "10.0.10240.0"; 72 | static public MSFBProject CurrentProject; 73 | static public Assembly CPPTasksAssembly; 74 | static public string PreBuildBatchFile = ""; 75 | static public string PostBuildBatchFile = ""; 76 | static public string SolutionDir = ""; 77 | static public bool HasCompileActions = true; 78 | 79 | public enum BuildType 80 | { 81 | Application, 82 | StaticLib, 83 | DynamicLib 84 | } 85 | 86 | static public BuildType BuildOutput = BuildType.Application; 87 | 88 | public class MSFBProject 89 | { 90 | public Project Proj; 91 | public List Dependents = new List(); 92 | public string AdditionalLinkInputs = ""; 93 | } 94 | 95 | static void Main(string[] args) 96 | { 97 | Parser parser = new Parser(); 98 | if (!parser.ParseArguments(args, CommandLineOptions)) 99 | { 100 | Console.WriteLine(CommandLineOptions.GetUsage()); 101 | return; 102 | } 103 | 104 | if (string.IsNullOrEmpty(CommandLineOptions.Solution) && string.IsNullOrEmpty(CommandLineOptions.Project)) 105 | { 106 | Console.WriteLine("No solution or project provided!"); 107 | Console.WriteLine(CommandLineOptions.GetUsage()); 108 | return; 109 | } 110 | 111 | List ProjectsToBuild = new List(); 112 | if (!string.IsNullOrEmpty(CommandLineOptions.Solution) && File.Exists(CommandLineOptions.Solution)) 113 | { 114 | try 115 | { 116 | if (string.IsNullOrEmpty(CommandLineOptions.Project)) 117 | { 118 | List SolutionProjects = SolutionFile.Parse(Path.GetFullPath(CommandLineOptions.Solution)).ProjectsInOrder.Where(el => el.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat).ToList(); 119 | SolutionProjects.Sort((x, y) => //Very dubious sort. 120 | { 121 | if (x.Dependencies.Contains(y.ProjectGuid)) return 1; 122 | if (y.Dependencies.Contains(x.ProjectGuid)) return -1; 123 | return 0; 124 | }); 125 | ProjectsToBuild = SolutionProjects.ConvertAll(el => el.AbsolutePath); 126 | } 127 | else 128 | { 129 | ProjectsToBuild.Add(Path.GetFullPath(CommandLineOptions.Project)); 130 | } 131 | 132 | SolutionDir = Path.GetDirectoryName(Path.GetFullPath(CommandLineOptions.Solution)); 133 | SolutionDir = SolutionDir.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); 134 | if(SolutionDir.Last() != Path.AltDirectorySeparatorChar) 135 | SolutionDir += Path.AltDirectorySeparatorChar; 136 | } 137 | catch (Exception e) 138 | { 139 | Console.WriteLine("Failed to parse solution file " + CommandLineOptions.Solution + "!"); 140 | Console.WriteLine("Exception: " + e.Message); 141 | return; 142 | } 143 | } 144 | else if (!string.IsNullOrEmpty(CommandLineOptions.Project)) 145 | { 146 | ProjectsToBuild.Add(Path.GetFullPath(CommandLineOptions.Project)); 147 | } 148 | 149 | List EvaluatedProjects = new List(); 150 | 151 | for (int i=0; i < ProjectsToBuild.Count; ++i) 152 | { 153 | EvaluateProjectReferences(ProjectsToBuild[i], EvaluatedProjects, null); 154 | } 155 | 156 | int ProjectsBuilt = 0; 157 | foreach(MSFBProject project in EvaluatedProjects) 158 | { 159 | CurrentProject = project; 160 | 161 | string VCTargetsPath = CurrentProject.Proj.GetPropertyValue("VCTargetsPathEffective"); 162 | if (string.IsNullOrEmpty(VCTargetsPath)) 163 | { 164 | VCTargetsPath = CurrentProject.Proj.GetPropertyValue("VCTargetsPath"); 165 | } 166 | if (string.IsNullOrEmpty(VCTargetsPath)) 167 | { 168 | Console.WriteLine("Failed to evaluate VCTargetsPath variable on " + Path.GetFileName(CurrentProject.Proj.FullPath) + "!"); 169 | continue; 170 | } 171 | 172 | bool useBuiltinDll = true; 173 | string BuildDllName = "Microsoft.Build.CPPTasks.Common.dll"; 174 | string BuildDllPath = VCTargetsPath + BuildDllName; 175 | if (File.Exists(BuildDllPath)) 176 | { 177 | CPPTasksAssembly = Assembly.LoadFrom(BuildDllPath); 178 | if (CPPTasksAssembly.GetType("Microsoft.Build.CPPTasks.CL") != null && 179 | CPPTasksAssembly.GetType("Microsoft.Build.CPPTasks.RC") != null && 180 | CPPTasksAssembly.GetType("Microsoft.Build.CPPTasks.Link") != null && 181 | CPPTasksAssembly.GetType("Microsoft.Build.CPPTasks.LIB") != null) 182 | { 183 | useBuiltinDll = false; 184 | } 185 | } 186 | if (useBuiltinDll) 187 | { 188 | CPPTasksAssembly = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + BuildDllName); 189 | } 190 | 191 | BFFOutputFilePath = Path.GetDirectoryName(CurrentProject.Proj.FullPath) + "\\" + Path.GetFileName(CurrentProject.Proj.FullPath) + "_" + CommandLineOptions.Config.Replace(" ", "") + "_" + CommandLineOptions.Platform.Replace(" ", "") + ".bff"; 192 | GenerateBffFromVcxproj(CommandLineOptions.Config, CommandLineOptions.Platform); 193 | 194 | if (!CommandLineOptions.GenerateOnly) 195 | { 196 | if (HasCompileActions && !ExecuteBffFile(CurrentProject.Proj.FullPath, CommandLineOptions.Platform)) 197 | break; 198 | else 199 | ProjectsBuilt++; 200 | } 201 | } 202 | 203 | Console.WriteLine(ProjectsBuilt + "/" + EvaluatedProjects.Count + " built."); 204 | } 205 | 206 | static public void EvaluateProjectReferences(string ProjectPath, List evaluatedProjects, MSFBProject dependent) 207 | { 208 | if (!string.IsNullOrEmpty(ProjectPath) && File.Exists(ProjectPath)) 209 | { 210 | try 211 | { 212 | MSFBProject newProj = evaluatedProjects.Find(elem => elem.Proj.FullPath == Path.GetFullPath(ProjectPath)); 213 | if (newProj != null) 214 | { 215 | //Console.WriteLine("Found exisiting project " + Path.GetFileNameWithoutExtension(ProjectPath)); 216 | if (dependent != null) 217 | newProj.Dependents.Add(dependent); 218 | } 219 | else 220 | { 221 | ProjectCollection projColl = new ProjectCollection(); 222 | if (!string.IsNullOrEmpty(SolutionDir)) 223 | projColl.SetGlobalProperty("SolutionDir", SolutionDir); 224 | newProj = new MSFBProject(); 225 | Project proj = projColl.LoadProject(ProjectPath); 226 | 227 | if (proj != null) 228 | { 229 | proj.SetGlobalProperty("Configuration", CommandLineOptions.Config); 230 | proj.SetGlobalProperty("Platform", CommandLineOptions.Platform); 231 | if (!string.IsNullOrEmpty(SolutionDir)) 232 | proj.SetGlobalProperty("SolutionDir", SolutionDir); 233 | proj.ReevaluateIfNecessary(); 234 | 235 | newProj.Proj = proj; 236 | if (dependent != null) 237 | { 238 | newProj.Dependents.Add(dependent); 239 | } 240 | var ProjectReferences = proj.Items.Where(elem => elem.ItemType == "ProjectReference"); 241 | foreach (var ProjRef in ProjectReferences) 242 | { 243 | if (ProjRef.GetMetadataValue("ReferenceOutputAssembly") == "true" || ProjRef.GetMetadataValue("LinkLibraryDependencies") == "true") 244 | { 245 | //Console.WriteLine(string.Format("{0} referenced by {1}.", Path.GetFileNameWithoutExtension(ProjRef.EvaluatedInclude), Path.GetFileNameWithoutExtension(proj.FullPath))); 246 | EvaluateProjectReferences(Path.GetDirectoryName(proj.FullPath) + Path.DirectorySeparatorChar + ProjRef.EvaluatedInclude, evaluatedProjects, newProj); 247 | } 248 | } 249 | //Console.WriteLine("Adding " + Path.GetFileNameWithoutExtension(proj.FullPath)); 250 | evaluatedProjects.Add(newProj); 251 | } 252 | } 253 | } 254 | catch (Exception e) 255 | { 256 | Console.WriteLine("Failed to parse project file " + ProjectPath + "!"); 257 | Console.WriteLine("Exception: " + e.Message); 258 | return; 259 | } 260 | } 261 | } 262 | 263 | static public bool HasFileChanged(string InputFile, string Platform, string Config, out string MD5hash) 264 | { 265 | using (var md5 = System.Security.Cryptography.MD5.Create()) 266 | { 267 | using (var stream = File.OpenRead(InputFile)) 268 | { 269 | MD5hash = ";" + InputFile + "_" + Platform + "_" + Config + "_" + BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLower(); 270 | } 271 | } 272 | 273 | if (!File.Exists(BFFOutputFilePath)) 274 | return true; 275 | 276 | string FirstLine = File.ReadAllLines(BFFOutputFilePath).First(); //bit wasteful to read the whole file... 277 | if (FirstLine == MD5hash) 278 | return false; 279 | else 280 | return true; 281 | } 282 | 283 | static public bool ExecuteBffFile(string ProjectPath, string Platform) 284 | { 285 | string projectDir = Path.GetDirectoryName(ProjectPath) + "\\"; 286 | 287 | string BatchFileText = "@echo off\n" 288 | + "%comspec% /c \"\"" + VCBasePath + "Auxiliary\\Build\\vcvarsall.bat\" " 289 | + (Platform == "Win32" ? "x86" : "x64") + " " + WindowsSDKTarget 290 | + " && \"" + CommandLineOptions.FBPath +"\" %*\""; 291 | 292 | #if NULL_FASTBUILD_OUTPUT 293 | BatchFileText += " > nul"; 294 | #endif 295 | 296 | File.WriteAllText(projectDir + "fb.bat", BatchFileText); 297 | 298 | Console.WriteLine("Building " + Path.GetFileNameWithoutExtension(ProjectPath)); 299 | 300 | try 301 | { 302 | System.Diagnostics.Process FBProcess = new System.Diagnostics.Process(); 303 | FBProcess.StartInfo.FileName = projectDir + "fb.bat"; 304 | FBProcess.StartInfo.Arguments = "-config \"" + BFFOutputFilePath + "\" " + CommandLineOptions.FBArgs; 305 | FBProcess.StartInfo.RedirectStandardOutput = true; 306 | FBProcess.StartInfo.UseShellExecute = false; 307 | FBProcess.StartInfo.WorkingDirectory = projectDir; 308 | FBProcess.StartInfo.StandardOutputEncoding = Console.OutputEncoding; 309 | 310 | FBProcess.Start(); 311 | while (!FBProcess.StandardOutput.EndOfStream) 312 | { 313 | Console.Write(FBProcess.StandardOutput.ReadLine() + "\n"); 314 | } 315 | FBProcess.WaitForExit(); 316 | return FBProcess.ExitCode == 0; 317 | } 318 | catch (Exception e) 319 | { 320 | Console.WriteLine("Failed to launch FASTBuild!"); 321 | Console.WriteLine("Exception: " + e.Message); 322 | return false; 323 | } 324 | } 325 | 326 | public class ObjectListNode 327 | { 328 | string Compiler; 329 | string CompilerOutputPath; 330 | string CompilerOptions; 331 | string CompilerOutputExtension; 332 | string PrecompiledHeaderString; 333 | 334 | List CompilerInputFiles; 335 | 336 | public ObjectListNode(string InputFile, string InCompiler, string InCompilerOutputPath, string InCompilerOptions, string InPrecompiledHeaderString, string InCompilerOutputExtension = "") 337 | { 338 | CompilerInputFiles = new List(); 339 | CompilerInputFiles.Add(InputFile); 340 | Compiler = InCompiler; 341 | CompilerOutputPath = InCompilerOutputPath; 342 | CompilerOptions = InCompilerOptions; 343 | CompilerOutputExtension = InCompilerOutputExtension; 344 | PrecompiledHeaderString = InPrecompiledHeaderString; 345 | } 346 | 347 | public bool AddIfMatches(string InputFile, string InCompiler, string InCompilerOutputPath, string InCompilerOptions, string InPrecompiledHeaderString) 348 | { 349 | if(Compiler == InCompiler && CompilerOutputPath == InCompilerOutputPath && CompilerOptions == InCompilerOptions && PrecompiledHeaderString == InPrecompiledHeaderString) 350 | { 351 | CompilerInputFiles.Add(InputFile); 352 | return true; 353 | } 354 | return false; 355 | } 356 | 357 | public string ToString(int ActionNumber) 358 | { 359 | bool UsedUnity = false; 360 | string ResultString = ""; 361 | if(CommandLineOptions.UseUnity && Compiler != "rc" && CompilerInputFiles.Count > 1) 362 | { 363 | StringBuilder UnityListString = new StringBuilder(string.Format("Unity('unity_{0}')\n{{\n", ActionNumber)); 364 | UnityListString.AppendFormat("\t.UnityInputFiles = {{ {0} }}\n", string.Join(",", CompilerInputFiles.ConvertAll(el => string.Format("'{0}'", el)).ToArray())); 365 | UnityListString.AppendFormat("\t.UnityOutputPath = \"{0}\"\n", CompilerOutputPath); 366 | UnityListString.AppendFormat("\t.UnityNumFiles = {0}\n", 1 + CompilerInputFiles.Count/10); 367 | UnityListString.Append("}\n\n"); 368 | UsedUnity = true; 369 | ResultString = UnityListString.ToString(); 370 | } 371 | 372 | StringBuilder ObjectListString = new StringBuilder(string.Format("ObjectList('action_{0}')\n{{\n", ActionNumber)); 373 | ObjectListString.AppendFormat("\t.Compiler = '{0}'\n", Compiler); 374 | ObjectListString.AppendFormat("\t.CompilerOutputPath = \"{0}\"\n", CompilerOutputPath); 375 | if(UsedUnity) 376 | { 377 | ObjectListString.AppendFormat("\t.CompilerInputUnity = {{ {0} }}\n", string.Format("'unity_{0}'", ActionNumber)); 378 | } 379 | else 380 | { 381 | ObjectListString.AppendFormat("\t.CompilerInputFiles = {{ {0} }}\n", string.Join(",", CompilerInputFiles.ConvertAll(el => string.Format("'{0}'", el)).ToArray())); 382 | } 383 | ObjectListString.AppendFormat("\t.CompilerOptions = '{0}'\n", CompilerOptions); 384 | if (!string.IsNullOrEmpty(CompilerOutputExtension)) 385 | { 386 | ObjectListString.AppendFormat("\t.CompilerOutputExtension = '{0}'\n", CompilerOutputExtension); 387 | } 388 | if (!string.IsNullOrEmpty(PrecompiledHeaderString)) 389 | { 390 | ObjectListString.Append(PrecompiledHeaderString); 391 | } 392 | if (!string.IsNullOrEmpty(PreBuildBatchFile)) 393 | { 394 | ObjectListString.Append("\t.PreBuildDependencies = 'prebuild'\n"); 395 | } 396 | ObjectListString.Append("}\n\n"); 397 | ResultString += ObjectListString.ToString(); 398 | return ResultString; 399 | } 400 | } 401 | 402 | static private void AddExtraDlls(StringBuilder outputString, string rootDir, string pattern) 403 | { 404 | string[] dllFiles = Directory.GetFiles(rootDir, pattern); 405 | foreach (string dllFile in dllFiles) 406 | { 407 | outputString.AppendFormat("\t\t'$Root$/{0}'\n", Path.GetFileName(dllFile)); 408 | } 409 | } 410 | 411 | static private void GenerateBffFromVcxproj(string Config, string Platform) 412 | { 413 | Project ActiveProject = CurrentProject.Proj; 414 | string MD5hash = "wafflepalooza"; 415 | PreBuildBatchFile = ""; 416 | PostBuildBatchFile = ""; 417 | bool FileChanged = HasFileChanged(ActiveProject.FullPath, Platform, Config, out MD5hash); 418 | 419 | string configType = ActiveProject.GetProperty("ConfigurationType").EvaluatedValue; 420 | switch(configType) 421 | { 422 | case "DynamicLibrary": BuildOutput = BuildType.DynamicLib; break; 423 | case "StaticLibrary": BuildOutput = BuildType.StaticLib; break; 424 | default: 425 | case "Application": BuildOutput = BuildType.Application; break; 426 | } 427 | 428 | PlatformToolsetVersion = ActiveProject.GetProperty("PlatformToolsetVersion").EvaluatedValue; 429 | 430 | string OutDir = ActiveProject.GetProperty("OutDir").EvaluatedValue; 431 | string IntDir = ActiveProject.GetProperty("IntDir").EvaluatedValue; 432 | 433 | StringBuilder OutputString = new StringBuilder(MD5hash + "\n\n"); 434 | 435 | OutputString.AppendFormat(".VSBasePath = '{0}'\n", ActiveProject.GetProperty("VSInstallDir").EvaluatedValue); 436 | VCBasePath = ActiveProject.GetProperty("VCInstallDir").EvaluatedValue; 437 | OutputString.AppendFormat(".VCBasePath = '{0}'\n", VCBasePath); 438 | 439 | if (Platform == "Win32" || Platform == "x86") 440 | { 441 | VCExePath = ActiveProject.GetProperty("VC_ExecutablePath_x86_x86").EvaluatedValue; 442 | } 443 | else 444 | { 445 | VCExePath = ActiveProject.GetProperty("VC_ExecutablePath_x64_x64").EvaluatedValue; 446 | } 447 | OutputString.AppendFormat(".VCExePath = '{0}'\n", VCExePath ); 448 | 449 | WindowsSDKTarget = ActiveProject.GetProperty("WindowsTargetPlatformVersion") != null ? ActiveProject.GetProperty("WindowsTargetPlatformVersion").EvaluatedValue : "8.1"; 450 | 451 | string winSdkDir = ActiveProject.GetProperty("WindowsSdkDir").EvaluatedValue; 452 | OutputString.AppendFormat(".WindowsSDKBasePath = '{0}'\n\n", winSdkDir); 453 | 454 | OutputString.Append("Settings\n{\n\t.Environment = \n\t{\n"); 455 | OutputString.AppendFormat("\t\t\"INCLUDE={0}\",\n", ActiveProject.GetProperty("IncludePath").EvaluatedValue); 456 | OutputString.AppendFormat("\t\t\"LIB={0}\",\n", ActiveProject.GetProperty("LibraryPath").EvaluatedValue); 457 | OutputString.AppendFormat("\t\t\"LIBPATH={0}\",\n", ActiveProject.GetProperty("ReferencePath").EvaluatedValue); 458 | OutputString.AppendFormat("\t\t\"PATH={0}\"\n", ActiveProject.GetProperty("Path").EvaluatedValue); 459 | OutputString.AppendFormat("\t\t\"TMP={0}\"\n", ActiveProject.GetProperty("Temp").EvaluatedValue); 460 | OutputString.AppendFormat("\t\t\"TEMP={0}\"\n", ActiveProject.GetProperty("Temp").EvaluatedValue); 461 | OutputString.AppendFormat("\t\t\"SystemRoot={0}\"\n", ActiveProject.GetProperty("SystemRoot").EvaluatedValue); 462 | OutputString.Append("\t}\n}\n\n"); 463 | 464 | StringBuilder CompilerString = new StringBuilder("Compiler('msvc')\n{\n"); 465 | 466 | string CompilerRoot = VCExePath; 467 | CompilerString.Append("\t.Root = '$VCExePath$'\n"); 468 | CompilerString.Append("\t.Executable = '$Root$/cl.exe'\n"); 469 | CompilerString.Append("\t.ExtraFiles =\n\t{\n"); 470 | CompilerString.Append("\t\t'$Root$/c1.dll'\n"); 471 | CompilerString.Append("\t\t'$Root$/c1xx.dll'\n"); 472 | CompilerString.Append("\t\t'$Root$/c2.dll'\n"); 473 | 474 | if(File.Exists(CompilerRoot + "1033/clui.dll")) //Check English first... 475 | { 476 | CompilerString.Append("\t\t'$Root$/1033/clui.dll'\n"); 477 | } 478 | else 479 | { 480 | var numericDirectories = Directory.GetDirectories(CompilerRoot).Where(d => Path.GetFileName(d).All(char.IsDigit)); 481 | var cluiDirectories = numericDirectories.Where(d => Directory.GetFiles(d, "clui.dll").Any()); 482 | if(cluiDirectories.Any()) 483 | { 484 | CompilerString.AppendFormat("\t\t'$Root$/{0}/clui.dll'\n", Path.GetFileName(cluiDirectories.First())); 485 | } 486 | } 487 | 488 | CompilerString.Append("\t\t'$Root$/mspdbsrv.exe'\n"); 489 | //CompilerString.Append("\t\t'$Root$/mspdbcore.dll'\n"); 490 | 491 | //CompilerString.AppendFormat("\t\t'$Root$/mspft{0}.dll'\n", PlatformToolsetVersion); 492 | //CompilerString.AppendFormat("\t\t'$Root$/msobj{0}.dll'\n", PlatformToolsetVersion); 493 | //CompilerString.AppendFormat("\t\t'$Root$/mspdb{0}.dll'\n", PlatformToolsetVersion); 494 | //CompilerString.AppendFormat("\t\t'$VSBasePath$/VC/redist/{0}/Microsoft.VC{1}.CRT/msvcp{1}.dll'\n", Platform == "Win32" ? "x86" : "x64", PlatformToolsetVersion); 495 | //CompilerString.AppendFormat("\t\t'$VSBasePath$/VC/redist/{0}/Microsoft.VC{1}.CRT/vccorlib{1}.dll'\n", Platform == "Win32" ? "x86" : "x64", PlatformToolsetVersion); 496 | 497 | AddExtraDlls(CompilerString, CompilerRoot, "msobj*.dll"); 498 | AddExtraDlls(CompilerString, CompilerRoot, "mspdb*.dll"); 499 | AddExtraDlls(CompilerString, CompilerRoot, "mspft*.dll"); 500 | AddExtraDlls(CompilerString, CompilerRoot, "msvcp*.dll"); 501 | AddExtraDlls(CompilerString, CompilerRoot, "tbbmalloc.dll"); 502 | AddExtraDlls(CompilerString, CompilerRoot, "vcmeta.dll"); 503 | AddExtraDlls(CompilerString, CompilerRoot, "vcruntime*.dll"); 504 | 505 | CompilerString.Append("\t}\n"); //End extra files 506 | CompilerString.Append("}\n\n"); //End compiler 507 | 508 | string rcPath = "\\bin\\" + WindowsSDKTarget + "\\x64\\rc.exe"; 509 | if (!File.Exists(winSdkDir + rcPath)) 510 | { 511 | rcPath = "\\bin\\x64\\rc.exe"; 512 | } 513 | 514 | CompilerString.Append("Compiler('rc')\n{\n"); 515 | CompilerString.Append("\t.Executable = '$WindowsSDKBasePath$" + rcPath + "'\n"); 516 | CompilerString.Append("\t.CompilerFamily = 'custom'\n"); 517 | CompilerString.Append("}\n\n"); //End rc compiler 518 | 519 | OutputString.Append(CompilerString); 520 | 521 | if (ActiveProject.GetItems("PreBuildEvent").Any()) 522 | { 523 | var buildEvent = ActiveProject.GetItems("PreBuildEvent").First(); 524 | if (buildEvent.Metadata.Any()) 525 | { 526 | var mdPi = buildEvent.Metadata.First(); 527 | if(!string.IsNullOrEmpty(mdPi.EvaluatedValue)) 528 | { 529 | string BatchText = "call \"" + VCBasePath + "Auxiliary\\Build\\vcvarsall.bat\" " 530 | + (Platform == "Win32" ? "x86" : "x64") + " " + WindowsSDKTarget + "\n"; 531 | PreBuildBatchFile = Path.Combine(ActiveProject.DirectoryPath, Path.GetFileNameWithoutExtension(ActiveProject.FullPath) + "_prebuild.bat"); 532 | File.WriteAllText(PreBuildBatchFile, BatchText + mdPi.EvaluatedValue); 533 | OutputString.Append("Exec('prebuild') \n{\n"); 534 | OutputString.AppendFormat("\t.ExecExecutable = '{0}' \n", PreBuildBatchFile); 535 | OutputString.AppendFormat("\t.ExecInput = '{0}' \n", PreBuildBatchFile); 536 | OutputString.AppendFormat("\t.ExecOutput = '{0}' \n", PreBuildBatchFile + ".txt"); 537 | OutputString.Append("\t.ExecUseStdOutAsOutput = true \n"); 538 | OutputString.Append("}\n\n"); 539 | } 540 | } 541 | } 542 | 543 | string CompilerOptions = ""; 544 | 545 | List ObjectLists = new List(); 546 | var CompileItems = ActiveProject.GetItems("ClCompile"); 547 | string PrecompiledHeaderString = ""; 548 | 549 | foreach (var Item in CompileItems) 550 | { 551 | if (Item.DirectMetadata.Any()) 552 | { 553 | if (Item.DirectMetadata.Where(dmd => dmd.Name == "ExcludedFromBuild" && dmd.EvaluatedValue == "true").Any()) 554 | continue; 555 | if (Item.DirectMetadata.Where(dmd => dmd.Name == "PrecompiledHeader" && dmd.EvaluatedValue == "Create").Any()) 556 | { 557 | ToolTask CLtask = (ToolTask)Activator.CreateInstance(CPPTasksAssembly.GetType("Microsoft.Build.CPPTasks.CL")); 558 | CLtask.GetType().GetProperty("Sources").SetValue(CLtask, new TaskItem[] { new TaskItem() }); 559 | string pchCompilerOptions = GenerateTaskCommandLine(CLtask, new string[] { "PrecompiledHeaderOutputFile", "ObjectFileName", "AssemblerListingLocation" }, Item.Metadata) + " /FS"; 560 | PrecompiledHeaderString = "\t.PCHOptions = '" + string.Format("\"%1\" /Fp\"%2\" /Fo\"%3\" {0} '\n", pchCompilerOptions); 561 | PrecompiledHeaderString += "\t.PCHInputFile = '" + Item.EvaluatedInclude + "'\n"; 562 | PrecompiledHeaderString += "\t.PCHOutputFile = '" + Item.GetMetadataValue("PrecompiledHeaderOutputFile") + "'\n"; 563 | break; //Assumes only one pch... 564 | } 565 | } 566 | } 567 | 568 | foreach (var Item in CompileItems) 569 | { 570 | bool ExcludePrecompiledHeader = false; 571 | if (Item.DirectMetadata.Any()) 572 | { 573 | if (Item.DirectMetadata.Where(dmd => dmd.Name == "ExcludedFromBuild" && dmd.EvaluatedValue == "true").Any()) 574 | continue; 575 | if (Item.DirectMetadata.Where(dmd => dmd.Name == "PrecompiledHeader" && dmd.EvaluatedValue == "Create").Any()) 576 | continue; 577 | if (Item.DirectMetadata.Where(dmd => dmd.Name == "PrecompiledHeader" && dmd.EvaluatedValue == "NotUsing").Any()) 578 | ExcludePrecompiledHeader = true; 579 | } 580 | 581 | ToolTask Task = (ToolTask) Activator.CreateInstance(CPPTasksAssembly.GetType("Microsoft.Build.CPPTasks.CL")); 582 | Task.GetType().GetProperty("Sources").SetValue(Task, new TaskItem[] { new TaskItem() }); //CPPTasks throws an exception otherwise... 583 | string TempCompilerOptions = GenerateTaskCommandLine(Task, new string[] { "ObjectFileName", "AssemblerListingLocation" }, Item.Metadata) + " /FS"; 584 | if (Path.GetExtension(Item.EvaluatedInclude) == ".c") 585 | TempCompilerOptions += " /TC"; 586 | else 587 | TempCompilerOptions += " /TP"; 588 | CompilerOptions = TempCompilerOptions; 589 | string FormattedCompilerOptions = string.Format("\"%1\" /Fo\"%2\" {0}", TempCompilerOptions); 590 | var MatchingNodes = ObjectLists.Where(el => el.AddIfMatches(Item.EvaluatedInclude, "msvc", IntDir, FormattedCompilerOptions, ExcludePrecompiledHeader ? "" : PrecompiledHeaderString)); 591 | if(!MatchingNodes.Any()) 592 | { 593 | ObjectLists.Add(new ObjectListNode(Item.EvaluatedInclude, "msvc", IntDir, FormattedCompilerOptions, ExcludePrecompiledHeader ? "" : PrecompiledHeaderString)); 594 | } 595 | } 596 | 597 | PrecompiledHeaderString = ""; 598 | 599 | var ResourceCompileItems = ActiveProject.GetItems("ResourceCompile"); 600 | foreach (var Item in ResourceCompileItems) 601 | { 602 | if (Item.DirectMetadata.Any()) 603 | { 604 | if (Item.DirectMetadata.Where(dmd => dmd.Name == "ExcludedFromBuild" && dmd.EvaluatedValue == "true").Any()) 605 | continue; 606 | } 607 | 608 | ToolTask Task = (ToolTask)Activator.CreateInstance(CPPTasksAssembly.GetType("Microsoft.Build.CPPTasks.RC")); 609 | string ResourceCompilerOptions = GenerateTaskCommandLine(Task, new string[] { "ResourceOutputFileName", "DesigntimePreprocessorDefinitions" }, Item.Metadata); 610 | 611 | string formattedCompilerOptions = string.Format("{0} /fo\"%2\" \"%1\"", ResourceCompilerOptions); 612 | var MatchingNodes = ObjectLists.Where(el => el.AddIfMatches(Item.EvaluatedInclude, "rc", IntDir, formattedCompilerOptions, PrecompiledHeaderString)); 613 | if (!MatchingNodes.Any()) 614 | { 615 | ObjectLists.Add(new ObjectListNode(Item.EvaluatedInclude, "rc", IntDir, formattedCompilerOptions, PrecompiledHeaderString, ".res")); 616 | } 617 | } 618 | 619 | int ActionNumber = 0; 620 | foreach (ObjectListNode ObjList in ObjectLists) 621 | { 622 | OutputString.Append(ObjList.ToString(ActionNumber)); 623 | ActionNumber++; 624 | } 625 | 626 | if (ActionNumber > 0) 627 | { 628 | HasCompileActions = true; 629 | } 630 | else 631 | { 632 | HasCompileActions = false; 633 | Console.WriteLine("Project has no actions to compile."); 634 | } 635 | 636 | string CompileActions = string.Join(",", Enumerable.Range(0, ActionNumber).ToList().ConvertAll(x => string.Format("'action_{0}'", x)).ToArray()); 637 | 638 | if (BuildOutput == BuildType.Application || BuildOutput == BuildType.DynamicLib) 639 | { 640 | OutputString.AppendFormat("{0}('output')\n{{", BuildOutput == BuildType.Application ? "Executable" : "DLL"); 641 | OutputString.Append("\t.Linker = '$VCExePath$\\link.exe'\n"); 642 | 643 | var LinkDefinitions = ActiveProject.ItemDefinitions["Link"]; 644 | string OutputFile = LinkDefinitions.GetMetadataValue("OutputFile").Replace('\\', '/'); 645 | 646 | if(HasCompileActions) 647 | { 648 | string DependencyOutputPath = LinkDefinitions.GetMetadataValue("ImportLibrary"); 649 | if (Path.IsPathRooted(DependencyOutputPath)) 650 | DependencyOutputPath = DependencyOutputPath.Replace('\\', '/'); 651 | else 652 | DependencyOutputPath = Path.Combine(ActiveProject.DirectoryPath, DependencyOutputPath).Replace('\\', '/'); 653 | 654 | foreach (var deps in CurrentProject.Dependents) 655 | { 656 | deps.AdditionalLinkInputs += " \"" + DependencyOutputPath + "\" "; 657 | } 658 | } 659 | 660 | ToolTask Task = (ToolTask)Activator.CreateInstance(CPPTasksAssembly.GetType("Microsoft.Build.CPPTasks.Link")); 661 | string LinkerOptions = GenerateTaskCommandLine(Task, new string[] { "OutputFile", "ProfileGuidedDatabase" }, LinkDefinitions.Metadata); 662 | 663 | if (!string.IsNullOrEmpty(CurrentProject.AdditionalLinkInputs)) 664 | { 665 | LinkerOptions += CurrentProject.AdditionalLinkInputs; 666 | } 667 | OutputString.AppendFormat("\t.LinkerOptions = '\"%1\" /OUT:\"%2\" {0}'\n", LinkerOptions.Replace("'","^'")); 668 | OutputString.AppendFormat("\t.LinkerOutput = '{0}'\n", OutputFile); 669 | 670 | OutputString.Append("\t.Libraries = { "); 671 | OutputString.Append(CompileActions); 672 | OutputString.Append(" }\n"); 673 | 674 | OutputString.Append("}\n\n"); 675 | } 676 | else if(BuildOutput == BuildType.StaticLib) 677 | { 678 | OutputString.Append("Library('output')\n{"); 679 | OutputString.Append("\t.Compiler = 'msvc'\n"); 680 | OutputString.Append(string.Format("\t.CompilerOptions = '\"%1\" /Fo\"%2\" /c {0}'\n", CompilerOptions)); 681 | OutputString.Append(string.Format("\t.CompilerOutputPath = \"{0}\"\n", IntDir)); 682 | OutputString.Append("\t.Librarian = '$VCExePath$\\lib.exe'\n"); 683 | 684 | var LibDefinitions = ActiveProject.ItemDefinitions["Lib"]; 685 | string OutputFile = LibDefinitions.GetMetadataValue("OutputFile").Replace('\\','/'); 686 | 687 | if(HasCompileActions) 688 | { 689 | string DependencyOutputPath = ""; 690 | if (Path.IsPathRooted(OutputFile)) 691 | DependencyOutputPath = Path.GetFullPath(OutputFile).Replace('\\', '/'); 692 | else 693 | DependencyOutputPath = Path.Combine(ActiveProject.DirectoryPath, OutputFile).Replace('\\', '/'); 694 | 695 | foreach (var deps in CurrentProject.Dependents) 696 | { 697 | deps.AdditionalLinkInputs += " \"" + DependencyOutputPath + "\" "; 698 | } 699 | } 700 | 701 | ToolTask task = (ToolTask)Activator.CreateInstance(CPPTasksAssembly.GetType("Microsoft.Build.CPPTasks.LIB")); 702 | string linkerOptions = GenerateTaskCommandLine(task, new string[] { "OutputFile" }, LibDefinitions.Metadata); 703 | if(!string.IsNullOrEmpty(CurrentProject.AdditionalLinkInputs)) 704 | { 705 | linkerOptions += CurrentProject.AdditionalLinkInputs; 706 | } 707 | OutputString.AppendFormat("\t.LibrarianOptions = '\"%1\" /OUT:\"%2\" {0}'\n", linkerOptions); 708 | OutputString.AppendFormat("\t.LibrarianOutput = '{0}'\n", OutputFile); 709 | 710 | OutputString.Append("\t.LibrarianAdditionalInputs = { "); 711 | OutputString.Append(CompileActions); 712 | OutputString.Append(" }\n"); 713 | 714 | OutputString.Append("}\n\n"); 715 | } 716 | 717 | if (ActiveProject.GetItems("PostBuildEvent").Any()) 718 | { 719 | ProjectItem BuildEvent = ActiveProject.GetItems("PostBuildEvent").First(); 720 | if (BuildEvent.Metadata.Any()) 721 | { 722 | ProjectMetadata MetaData = BuildEvent.Metadata.First(); 723 | if(!string.IsNullOrEmpty(MetaData.EvaluatedValue)) 724 | { 725 | string BatchText = "call \"" + VCBasePath + "Auxiliary\\Build\\vcvarsall.bat\" " 726 | + (Platform == "Win32" ? "x86" : "x64") + " " + WindowsSDKTarget + "\n"; 727 | PostBuildBatchFile = Path.Combine(ActiveProject.DirectoryPath, Path.GetFileNameWithoutExtension(ActiveProject.FullPath) + "_postbuild.bat"); 728 | File.WriteAllText(PostBuildBatchFile, BatchText + MetaData.EvaluatedValue); 729 | OutputString.Append("Exec('postbuild') \n{\n"); 730 | OutputString.AppendFormat("\t.ExecExecutable = '{0}' \n", PostBuildBatchFile); 731 | OutputString.AppendFormat("\t.ExecInput = '{0}' \n", PostBuildBatchFile); 732 | OutputString.AppendFormat("\t.ExecOutput = '{0}' \n", PostBuildBatchFile + ".txt"); 733 | OutputString.Append("\t.PreBuildDependencies = 'output' \n"); 734 | OutputString.Append("\t.ExecUseStdOutAsOutput = true \n"); 735 | OutputString.Append("}\n\n"); 736 | } 737 | } 738 | } 739 | 740 | OutputString.AppendFormat("Alias ('all')\n{{\n\t.Targets = {{ '{0}' }}\n}}", string.IsNullOrEmpty(PostBuildBatchFile) ? "output" : "postbuild"); 741 | 742 | if(FileChanged || CommandLineOptions.AlwaysRegenerate) 743 | { 744 | File.WriteAllText(BFFOutputFilePath, OutputString.ToString()); 745 | } 746 | } 747 | 748 | public static string GenerateTaskCommandLine( 749 | ToolTask Task, 750 | string[] PropertiesToSkip, 751 | IEnumerable MetaDataList) 752 | { 753 | foreach (ProjectMetadata MetaData in MetaDataList) 754 | { 755 | if (PropertiesToSkip.Contains(MetaData.Name)) 756 | continue; 757 | 758 | var MatchingProps = Task.GetType().GetProperties().Where(prop => prop.Name == MetaData.Name); 759 | if (MatchingProps.Any() && !string.IsNullOrEmpty(MetaData.EvaluatedValue)) 760 | { 761 | string EvaluatedValue = MetaData.EvaluatedValue.Trim(); 762 | if(MetaData.Name == "AdditionalIncludeDirectories") 763 | { 764 | EvaluatedValue = EvaluatedValue.Replace("\\\\", "\\"); 765 | EvaluatedValue = EvaluatedValue.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); 766 | } 767 | 768 | PropertyInfo propInfo = MatchingProps.First(); //Dubious 769 | if (propInfo.PropertyType.IsArray && propInfo.PropertyType.GetElementType() == typeof(string)) 770 | { 771 | propInfo.SetValue(Task, Convert.ChangeType(EvaluatedValue.Split(';'), propInfo.PropertyType)); 772 | } 773 | else 774 | { 775 | propInfo.SetValue(Task, Convert.ChangeType(EvaluatedValue, propInfo.PropertyType)); 776 | } 777 | } 778 | } 779 | 780 | var GenCmdLineMethod = Task.GetType().GetRuntimeMethods().Where(meth => meth.Name == "GenerateCommandLine").First(); //Dubious 781 | return GenCmdLineMethod.Invoke(Task, new object[] { Type.Missing, Type.Missing }) as string; 782 | } 783 | } 784 | 785 | } 786 | --------------------------------------------------------------------------------