diff options
Diffstat (limited to 'devtools')
| -rw-r--r-- | devtools/create_project/create_project.cpp | 191 | ||||
| -rw-r--r-- | devtools/create_project/create_project.h | 10 | ||||
| -rw-r--r-- | devtools/create_project/msbuild.cpp | 43 | ||||
| -rw-r--r-- | devtools/create_project/msvc.cpp | 10 | ||||
| -rw-r--r-- | devtools/create_project/msvc.h | 7 | ||||
| -rw-r--r-- | devtools/create_project/visualstudio.cpp | 26 | 
6 files changed, 210 insertions, 77 deletions
| diff --git a/devtools/create_project/create_project.cpp b/devtools/create_project/create_project.cpp index 0a77a84602..3ee5fc4f97 100644 --- a/devtools/create_project/create_project.cpp +++ b/devtools/create_project/create_project.cpp @@ -109,7 +109,7 @@ enum ProjectType {  int main(int argc, char *argv[]) {  #ifndef USE_WIN32_API  	// Initialize random number generator for UUID creation -	std::srand((uint)std::time(0)); +	std::srand((unsigned int)std::time(0));  #endif  	if (argc < 2) { @@ -264,7 +264,7 @@ int main(int argc, char *argv[]) {  				setup.filePrefix.erase(setup.filePrefix.size() - 1);  		} else if (!std::strcmp(argv[i], "--output-dir")) {  			if (i + 1 >= argc) { -				std::cerr << "ERROR: Missing \"path\" parameter for \"--output-dirx\"!\n"; +				std::cerr << "ERROR: Missing \"path\" parameter for \"--output-dir\"!\n";  				return -1;  			} @@ -279,12 +279,23 @@ int main(int argc, char *argv[]) {  			setup.createInstaller = true;  		} else if (!std::strcmp(argv[i], "--tools")) {  			setup.devTools = true; +		} else if (!std::strcmp(argv[i], "--tests")) { +			setup.tests = true;  		} else {  			std::cerr << "ERROR: Unknown parameter \"" << argv[i] << "\"\n";  			return -1;  		}  	} +	// When building tests, disable some features +	if (setup.tests) { +		setFeatureBuildState("mt32emu", setup.features, false); +		setFeatureBuildState("eventrecorder", setup.features, false); + +		for (EngineDescList::iterator j = setup.engines.begin(); j != setup.engines.end(); ++j) +			j->enable = false; +	} +  	// Print status  	cout << "Enabled engines:\n\n";  	for (EngineDescList::const_iterator i = setup.engines.begin(); i != setup.engines.end(); ++i) { @@ -321,6 +332,12 @@ int main(int argc, char *argv[]) {  		}  	} +	// Check if tools and tests are enabled simultaneously +	if (setup.devTools && setup.tests) { +		std::cerr << "ERROR: The tools and tests projects cannot be created simultaneously\n"; +		return -1; +	} +  	// Setup defines and libraries  	setup.defines = getEngineDefines(setup.engines);  	setup.libraries = getFeatureLibraries(setup.features); @@ -358,8 +375,8 @@ int main(int argc, char *argv[]) {  		return -1;  	case kProjectCodeBlocks: -		if (setup.devTools) { -			std::cerr << "ERROR: Building tools is not supported for the CodeBlocks project type!\n"; +		if (setup.devTools || setup.tests) { +			std::cerr << "ERROR: Building tools or tests is not supported for the CodeBlocks project type!\n";  			return -1;  		} @@ -531,8 +548,8 @@ int main(int argc, char *argv[]) {  		break;  	case kProjectXcode: -		if (setup.devTools) { -			std::cerr << "ERROR: Building tools is not supported for the XCode project type!\n"; +		if (setup.devTools || setup.tests) { +			std::cerr << "ERROR: Building tools or tests is not supported for the XCode project type!\n";  			return -1;  		} @@ -573,6 +590,11 @@ int main(int argc, char *argv[]) {  		setup.projectDescription += "Tools";  	} +	if (setup.tests) { +		setup.projectName += "-tests"; +		setup.projectDescription += "Tests"; +	} +  	provider->createProject(setup);  	delete provider; @@ -623,6 +645,9 @@ void displayHelp(const char *exe) {  	        " --tools                  Create project files for the devtools\n"  	        "                          (ignores --build-events and --installer, as well as engine settings)\n"  	        "                          (default: false)\n" +	        " --tests                  Create project files for the tests\n" +	        "                          (ignores --build-events and --installer, as well as engine settings)\n" +	        "                          (default: false)\n"  	        "\n"  	        "Engines settings:\n"  	        " --list-engines           list all available engines and their default state\n" @@ -1130,69 +1155,66 @@ ProjectProvider::ProjectProvider(StringList &global_warnings, std::map<std::stri  	: _version(version), _globalWarnings(global_warnings), _projectWarnings(project_warnings) {  } -void ProjectProvider::createProject(const BuildSetup &setup) { +void ProjectProvider::createProject(BuildSetup &setup) { +	std::string targetFolder; +  	if (setup.devTools) {  		_uuidMap = createToolsUUIDMap(); +		targetFolder = "/devtools/"; +	} else if (!setup.tests) { +		_uuidMap = createUUIDMap(setup); +		targetFolder = "/engines/"; +	} -		// We also need to add the UUID of the main project file. -		const std::string svmUUID = _uuidMap[setup.projectName] = createUUID(); - -		createWorkspace(setup); - -		StringList in, ex; - -		// Create tools project files -		for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) { -			if (i->first == setup.projectName) -				continue; - -			in.clear(); ex.clear(); -			const std::string moduleDir = setup.srcDir + "/devtools/" + i->first; - -			createModuleList(moduleDir, setup.defines, in, ex); -			createProjectFile(i->first, i->second, setup, moduleDir, in, ex); -		} - -		// Create other misc. build files -		createOtherBuildFiles(setup); +	// We also need to add the UUID of the main project file. +	const std::string svmUUID = _uuidMap[setup.projectName] = createUUID(); -	} else { -		_uuidMap = createUUIDMap(setup); +	createWorkspace(setup); -		// We also need to add the UUID of the main project file. -		const std::string svmUUID = _uuidMap[setup.projectName] = createUUID(); +	StringList in, ex; -		// Create Solution/Workspace file -		createWorkspace(setup); +	// Create project files +	for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) { +		if (i->first == setup.projectName) +			continue; -		StringList in, ex; +		in.clear(); ex.clear(); +		const std::string moduleDir = setup.srcDir + targetFolder + i->first; -		// Create engine project files -		for (UUIDMap::const_iterator i = _uuidMap.begin(); i != _uuidMap.end(); ++i) { -			if (i->first == setup.projectName) -				continue; +		createModuleList(moduleDir, setup.defines, setup.testDirs, in, ex); +		createProjectFile(i->first, i->second, setup, moduleDir, in, ex); +	} -			in.clear(); ex.clear(); -			const std::string moduleDir = setup.srcDir + "/engines/" + i->first; +	if (setup.tests) { +		// Create the main project file. +		in.clear(); ex.clear(); -			createModuleList(moduleDir, setup.defines, in, ex); -			createProjectFile(i->first, i->second, setup, moduleDir, in, ex); -		} +		createModuleList(setup.srcDir + "/backends", setup.defines, setup.testDirs, in, ex); +		createModuleList(setup.srcDir + "/backends/platform/sdl", setup.defines, setup.testDirs, in, ex); +		createModuleList(setup.srcDir + "/base", setup.defines, setup.testDirs, in, ex); +		createModuleList(setup.srcDir + "/common", setup.defines, setup.testDirs, in, ex); +		createModuleList(setup.srcDir + "/engines", setup.defines, setup.testDirs, in, ex); +		createModuleList(setup.srcDir + "/graphics", setup.defines, setup.testDirs, in, ex); +		createModuleList(setup.srcDir + "/gui", setup.defines, setup.testDirs, in, ex); +		createModuleList(setup.srcDir + "/audio", setup.defines, setup.testDirs, in, ex); +		createModuleList(setup.srcDir + "/test", setup.defines, setup.testDirs, in, ex); +		createProjectFile(setup.projectName, svmUUID, setup, setup.srcDir, in, ex); +	} else if (!setup.devTools) {  		// Last but not least create the main project file.  		in.clear(); ex.clear();  		// File list for the Project file -		createModuleList(setup.srcDir + "/backends", setup.defines, in, ex); -		createModuleList(setup.srcDir + "/backends/platform/sdl", setup.defines, in, ex); -		createModuleList(setup.srcDir + "/base", setup.defines, in, ex); -		createModuleList(setup.srcDir + "/common", setup.defines, in, ex); -		createModuleList(setup.srcDir + "/engines", setup.defines, in, ex); -		createModuleList(setup.srcDir + "/graphics", setup.defines, in, ex); -		createModuleList(setup.srcDir + "/gui", setup.defines, in, ex); -		createModuleList(setup.srcDir + "/audio", setup.defines, in, ex); -		createModuleList(setup.srcDir + "/audio/softsynth/mt32", setup.defines, in, ex); -		createModuleList(setup.srcDir + "/video", setup.defines, in, ex); +		createModuleList(setup.srcDir + "/backends", setup.defines, setup.testDirs, in, ex); +		createModuleList(setup.srcDir + "/backends/platform/sdl", setup.defines, setup.testDirs, in, ex); +		createModuleList(setup.srcDir + "/base", setup.defines, setup.testDirs, in, ex); +		createModuleList(setup.srcDir + "/common", setup.defines, setup.testDirs, in, ex); +		createModuleList(setup.srcDir + "/engines", setup.defines, setup.testDirs, in, ex); +		createModuleList(setup.srcDir + "/graphics", setup.defines, setup.testDirs, in, ex); +		createModuleList(setup.srcDir + "/gui", setup.defines, setup.testDirs, in, ex); +		createModuleList(setup.srcDir + "/audio", setup.defines, setup.testDirs, in, ex); +		createModuleList(setup.srcDir + "/audio/softsynth/mt32", setup.defines, setup.testDirs, in, ex); +		createModuleList(setup.srcDir + "/video", setup.defines, setup.testDirs, in, ex);  		// Resource files  		in.push_back(setup.srcDir + "/icons/" + setup.projectName + ".ico"); @@ -1211,10 +1233,10 @@ void ProjectProvider::createProject(const BuildSetup &setup) {  		// Create the main project file.  		createProjectFile(setup.projectName, svmUUID, setup, setup.srcDir, in, ex); - -		// Create other misc. build files -		createOtherBuildFiles(setup);  	} + +	// Create other misc. build files +	createOtherBuildFiles(setup);  }  ProjectProvider::UUIDMap ProjectProvider::createUUIDMap(const BuildSetup &setup) const { @@ -1322,7 +1344,7 @@ void ProjectProvider::addFilesToProject(const std::string &dir, std::ofstream &p  	delete files;  } -void ProjectProvider::createModuleList(const std::string &moduleDir, const StringList &defines, StringList &includeList, StringList &excludeList) const { +void ProjectProvider::createModuleList(const std::string &moduleDir, const StringList &defines, StringList &testDirs, StringList &includeList, StringList &excludeList) const {  	const std::string moduleMkFile = moduleDir + "/module.mk";  	std::ifstream moduleMk(moduleMkFile.c_str());  	if (!moduleMk) @@ -1453,6 +1475,59 @@ void ProjectProvider::createModuleList(const std::string &moduleDir, const Strin  					++i;  				}  			} +		} else if (*i == "TESTS") { +			if (tokens.size() < 3) +				error("Malformed TESTS definition in " + moduleMkFile); +			++i; + +			if (*i != ":=" && *i != "+=" && *i != "=") +				error("Malformed TESTS definition in " + moduleMkFile); +			++i; + +			while (i != tokens.end()) { +				// Read input +				std::string folder = unifyPath(*i); + +				// Get include folder +				const std::string source_dir = "$(srcdir)/"; +				const std::string selector = getLastPathComponent(folder); +				const std::string module = getLastPathComponent(moduleDir); + +				folder.replace(folder.find(source_dir), source_dir.length(), ""); +				folder.replace(folder.find(selector), selector.length(), ""); +				folder.replace(folder.find(module), module.length(), moduleDir); + +				// Scan all files in the include folder +				FileList files = listDirectory(folder); + +				if (files.empty()) +					continue; + +				// Add to list of test folders +				testDirs.push_back(folder); + +				for (FileList::const_iterator f = files.begin(); f != files.end(); ++f) { +					if (f->isDirectory) +						continue; + +					std::string filename = folder + f->name; + +					if (shouldInclude.top()) { +						// In case we should include a file, we need to make +						// sure it is not in the exclude list already. If it +						// is we just drop it from the exclude list. +						excludeList.remove(filename); + +						includeList.push_back(filename); +					} else if (std::find(includeList.begin(), includeList.end(), filename) == includeList.end()) { +						// We only add the file to the exclude list in case it +						// has not yet been added to the include list. +						excludeList.push_back(filename); +					} +				} + +				++i; +			}  		} else if (*i == "ifdef") {  			if (tokens.size() < 2)  				error("Malformed ifdef in " + moduleMkFile); diff --git a/devtools/create_project/create_project.h b/devtools/create_project/create_project.h index de77793ee7..d0f2db364c 100644 --- a/devtools/create_project/create_project.h +++ b/devtools/create_project/create_project.h @@ -221,13 +221,16 @@ struct BuildSetup {  	StringList defines;   ///< List of all defines for the build.  	StringList libraries; ///< List of all external libraries required for the build. +	StringList testDirs;  ///< List of all folders containing tests  	bool devTools;         ///< Generate project files for the tools +	bool tests;             ///< Generate project files for the tests  	bool runBuildEvents;   ///< Run build events as part of the build (generate revision number and copy engine/theme data & needed files to the build folder  	bool createInstaller;  ///< Create NSIS installer after the build  	BuildSetup() {  		devTools        = false; +		tests           = false;  		runBuildEvents  = false;  		createInstaller = false;  	} @@ -339,7 +342,7 @@ public:  	 *  	 * @param setup Description of the desired build setup.  	 */ -	void createProject(const BuildSetup &setup); +	void createProject(BuildSetup &setup);  	/**  	 * Returns the last path component. @@ -430,10 +433,11 @@ protected:  	 *  	 * @param moduleDir Path to the module.  	 * @param defines List of set defines. +	 * @param testDirs List of folders containing tests.  	 * @param includeList Reference to a list, where included files should be added.  	 * @param excludeList Reference to a list, where excluded files should be added.  	 */ -	void createModuleList(const std::string &moduleDir, const StringList &defines, StringList &includeList, StringList &excludeList) const; +	void createModuleList(const std::string &moduleDir, const StringList &defines, StringList &testDirs, StringList &includeList, StringList &excludeList) const;  	/**  	 * Creates an UUID for every enabled engine of the @@ -448,7 +452,7 @@ protected:  	 * Creates an UUID for every enabled tool of the  	 * passed build description.  	 * -	 * @return A map, which includes UUIDs for all enabled engines. +	 * @return A map, which includes UUIDs for all enabled tools.  	 */  	UUIDMap createToolsUUIDMap() const; diff --git a/devtools/create_project/msbuild.cpp b/devtools/create_project/msbuild.cpp index 6af9323fcd..23bf1bc28a 100644 --- a/devtools/create_project/msbuild.cpp +++ b/devtools/create_project/msbuild.cpp @@ -69,7 +69,7 @@ inline void outputConfiguration(std::ostream &project, const std::string &config  inline void outputConfigurationType(const BuildSetup &setup, std::ostream &project, const std::string &name, const std::string &config, int version) {  	project << "\t<PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='" << config << "'\" Label=\"Configuration\">\n" -	           "\t\t<ConfigurationType>" << ((name == setup.projectName || setup.devTools) ? "Application" : "StaticLibrary") << "</ConfigurationType>\n" +	           "\t\t<ConfigurationType>" << ((name == setup.projectName || setup.devTools || setup.tests) ? "Application" : "StaticLibrary") << "</ConfigurationType>\n"  	           "\t\t<PlatformToolset>v" << version << "0</PlatformToolset>\n"  	           "\t</PropertyGroup>\n";  } @@ -159,10 +159,26 @@ void MSBuildProvider::createProjectFile(const std::string &name, const std::stri  	if (name == setup.projectName)  		writeReferences(setup, project); +	// Output auto-generated test runner +	if (setup.tests) { +		project << "\t<ItemGroup>\n"; +		project << "\t\t<ClCompile Include=\"test_runner.cpp\" />\n"; +		project << "\t</ItemGroup>\n"; +	} +  	project << "\t<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n"  	           "\t<ImportGroup Label=\"ExtensionTargets\">\n" -	           "\t</ImportGroup>\n" -	           "</Project>\n"; +	           "\t</ImportGroup>\n"; + +	if (setup.tests) { +		// We override the normal target to ignore the exit code (this allows us to have a clean output and not message about the command exit code) +		project << "\t\t<Target Name=\"PostBuildEvent\">\n" +		        << "\t\t\t<Message Text=\"Description: Run tests\" />\n" +				<< "\t\t\t<Exec Command=\"$(TargetPath)\"  IgnoreExitCode=\"true\" />\n" +		        << "\t\t</Target>\n"; +	} + +	project << "</Project>\n";  	// Output filter file if necessary  	createFiltersFile(setup, name); @@ -248,7 +264,7 @@ void MSBuildProvider::outputProjectSettings(std::ofstream &project, const std::s  	bool disableEditAndContinue = find(_disableEditAndContinue.begin(), _disableEditAndContinue.end(), name) != _disableEditAndContinue.end();  	// Nothing to add here, move along! -	if (!setup.devTools && name != setup.projectName && !enableLanguageExtensions && !disableEditAndContinue && warningsIterator == _projectWarnings.end()) +	if ((!setup.devTools || !setup.tests) && name != setup.projectName && !enableLanguageExtensions && !disableEditAndContinue && warningsIterator == _projectWarnings.end())  		return;  	std::string warnings = ""; @@ -260,7 +276,7 @@ void MSBuildProvider::outputProjectSettings(std::ofstream &project, const std::s  	           "\t\t<ClCompile>\n";  	// Language Extensions -	if (setup.devTools || name == setup.projectName || enableLanguageExtensions) +	if (setup.devTools || setup.tests || name == setup.projectName || enableLanguageExtensions)  		project << "\t\t\t<DisableLanguageExtensions>false</DisableLanguageExtensions>\n";  	// Edit and Continue @@ -274,18 +290,18 @@ void MSBuildProvider::outputProjectSettings(std::ofstream &project, const std::s  	project << "\t\t</ClCompile>\n";  	// Link configuration for main project -	if (name == setup.projectName || setup.devTools) { +	if (name == setup.projectName || setup.devTools || setup.tests) {  		std::string libraries;  		for (StringList::const_iterator i = setup.libraries.begin(); i != setup.libraries.end(); ++i)  			libraries += *i + ".lib;";  		project << "\t\t<Link>\n" -		           "\t\t\t<OutputFile>$(OutDir)" << (setup.devTools ? name : setup.projectName) << ".exe</OutputFile>\n" +		           "\t\t\t<OutputFile>$(OutDir)" << ((setup.devTools || setup.tests) ? name : setup.projectName) << ".exe</OutputFile>\n"  		           "\t\t\t<AdditionalDependencies>" << libraries << "%(AdditionalDependencies)</AdditionalDependencies>\n"  		           "\t\t</Link>\n"; -		if (!setup.devTools && setup.runBuildEvents) { +		if (!setup.devTools && !setup.tests && setup.runBuildEvents) {  			project << "\t\t<PreBuildEvent>\n"  			           "\t\t\t<Message>Generate revision</Message>\n"  			           "\t\t\t<Command>" << getPreBuildEvent() << "</Command>\n" @@ -296,6 +312,11 @@ void MSBuildProvider::outputProjectSettings(std::ofstream &project, const std::s  					   "\t\t\t<Message>Copy data files to the build folder</Message>\n"  					   "\t\t\t<Command>" << getPostBuildEvent(isWin32, setup.createInstaller) << "</Command>\n"  					   "\t\t</PostBuildEvent>\n"; +		} else if (setup.tests) { +			project << "\t\t<PreBuildEvent>\n" +			           "\t\t\t<Message>Generate runner.cpp</Message>\n" +			           "\t\t\t<Command>" << getTestPreBuildEvent(setup) << "</Command>\n" +			           "\t\t</PreBuildEvent>\n";  		}  	} @@ -330,9 +351,9 @@ void MSBuildProvider::outputGlobalPropFile(const BuildSetup &setup, std::ofstrea  	              "\t\t<ClCompile>\n"  	              "\t\t\t<DisableLanguageExtensions>true</DisableLanguageExtensions>\n"  	              "\t\t\t<DisableSpecificWarnings>" << warnings << ";%(DisableSpecificWarnings)</DisableSpecificWarnings>\n" -	              "\t\t\t<AdditionalIncludeDirectories>$(" << LIBS_DEFINE << ")\\include;" << prefix << ";" << prefix << "\\engines;$(TargetDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n" +	              "\t\t\t<AdditionalIncludeDirectories>$(" << LIBS_DEFINE << ")\\include;" << prefix << ";" << prefix << "\\engines;" << (setup.tests ? prefix + "\\test\\cxxtest;" : "") << "$(TargetDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n"  	              "\t\t\t<PreprocessorDefinitions>" << definesList << "%(PreprocessorDefinitions)</PreprocessorDefinitions>\n" -	              "\t\t\t<ExceptionHandling>" << (setup.devTools ? "Sync" : "") << "</ExceptionHandling>\n"; +	              "\t\t\t<ExceptionHandling>" << ((setup.devTools || setup.tests) ? "Sync" : "") << "</ExceptionHandling>\n";  #if NEEDS_RTTI  	properties << "\t\t\t<RuntimeTypeInfo>true</RuntimeTypeInfo>\n"; @@ -348,7 +369,7 @@ void MSBuildProvider::outputGlobalPropFile(const BuildSetup &setup, std::ofstrea  	              "\t\t\t<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>\n"  	              "\t\t\t<SubSystem>Console</SubSystem>\n"; -	if (!setup.devTools) +	if (!setup.devTools && !setup.tests)  		properties << "\t\t\t<EntryPointSymbol>WinMainCRTStartup</EntryPointSymbol>\n";  	properties << "\t\t</Link>\n" diff --git a/devtools/create_project/msvc.cpp b/devtools/create_project/msvc.cpp index b8d2401af9..2fedadcba5 100644 --- a/devtools/create_project/msvc.cpp +++ b/devtools/create_project/msvc.cpp @@ -161,6 +161,16 @@ std::string MSVCProvider::getPreBuildEvent() const {  	return cmdLine;  } +std::string MSVCProvider::getTestPreBuildEvent(const BuildSetup &setup) const { +	// Build list of folders containing tests +	std::string target = ""; + +	for (StringList::const_iterator it = setup.testDirs.begin(); it != setup.testDirs.end(); ++it) +		target += " $(SolutionDir)" + *it + "*.h"; + +	return ""$(SolutionDir)../../test/cxxtest/cxxtestgen.py" --runner=ParenPrinter --no-std --no-eh -o $(SolutionDir)test_runner.cpp" + target; +} +  std::string MSVCProvider::getPostBuildEvent(bool isWin32, bool createInstaller) const {  	std::string cmdLine = ""; diff --git a/devtools/create_project/msvc.h b/devtools/create_project/msvc.h index 5a854b596a..b9b93fe109 100644 --- a/devtools/create_project/msvc.h +++ b/devtools/create_project/msvc.h @@ -88,6 +88,13 @@ protected:  	std::string getPreBuildEvent() const;  	/** +	* Get the command line for the test generator +	* +	* @param setup Description of the desired build setup. +	*/ +	std::string getTestPreBuildEvent(const BuildSetup &setup) const; + +	/**  	 * Get the command line for copying data files to the build directory.  	 *  	 * @param	isWin32		   	Bitness of property file. diff --git a/devtools/create_project/visualstudio.cpp b/devtools/create_project/visualstudio.cpp index de2df96d78..23225d3435 100644 --- a/devtools/create_project/visualstudio.cpp +++ b/devtools/create_project/visualstudio.cpp @@ -83,7 +83,7 @@ void VisualStudioProvider::createProjectFile(const std::string &name, const std:  	// Check for project-specific warnings:  	std::map< std::string, std::list<std::string> >::iterator warningsIterator = _projectWarnings.find(name); -	if (setup.devTools || name == setup.projectName) { +	if (setup.devTools || setup.tests || name == setup.projectName) {  		std::string libraries;  		for (StringList::const_iterator i = setup.libraries.begin(); i != setup.libraries.end(); ++i) @@ -140,6 +140,11 @@ void VisualStudioProvider::createProjectFile(const std::string &name, const std:  	else  		addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix); +	// Output auto-generated test runner +	if (setup.tests) { +		project << "\t\t<File RelativePath=\"test_runner.cpp\" />\n"; +	} +  	project << "\t</Files>\n"  	           "</VisualStudioProject>\n";  } @@ -161,7 +166,7 @@ void VisualStudioProvider::outputConfiguration(const BuildSetup &setup, std::ost  }  void VisualStudioProvider::outputBuildEvents(std::ostream &project, const BuildSetup &setup, const bool isWin32) { -	if (!setup.devTools && setup.runBuildEvents) { +	if (!setup.devTools && !setup.tests && setup.runBuildEvents) {  		project << "\t\t\t<Tool\tName=\"VCPreBuildEventTool\"\n"  		           "\t\t\t\tCommandLine=\"" << getPreBuildEvent() << "\"\n"  		           "\t\t\t/>\n" @@ -169,6 +174,17 @@ void VisualStudioProvider::outputBuildEvents(std::ostream &project, const BuildS  		           "\t\t\t\tCommandLine=\"" << getPostBuildEvent(isWin32, setup.createInstaller) << "\"\n"  		           "\t\t\t/>\n";  	} + +	// Generate runner file before build for tests +	if (setup.tests) { +		project << "\t\t\t<Tool\tName=\"VCPreBuildEventTool\"\n" +			"\t\t\t\tCommandLine=\"" << getTestPreBuildEvent(setup) << "\"\n" +			"\t\t\t/>\n"; + +		project << "\t\t\t<Tool\tName=\"VCPostBuildEventTool\"\n" +			"\t\t\t\tCommandLine=\"$(TargetPath)\" IgnoreExitCode=\"true\"\n" +			"\t\t\t/>\n"; +	}  }  void VisualStudioProvider::writeReferences(const BuildSetup &setup, std::ofstream &output) { @@ -212,9 +228,9 @@ void VisualStudioProvider::outputGlobalPropFile(const BuildSetup &setup, std::of  	              "\t\tName=\"VCCLCompilerTool\"\n"  	              "\t\tDisableLanguageExtensions=\"" << (setup.devTools ? "false" : "true") << "\"\n"  	              "\t\tDisableSpecificWarnings=\"" << warnings << "\"\n" -	              "\t\tAdditionalIncludeDirectories=\"" << prefix << ";" << prefix << "\\engines;$(" << LIBS_DEFINE << ")\\include;$(TargetDir)\"\n" +	              "\t\tAdditionalIncludeDirectories=\"" << prefix << ";" << prefix << "\\engines;$(" << LIBS_DEFINE << ")\\include;" << (setup.tests ? prefix + "\\test\\cxxtest;" : "") << "$(TargetDir)\"\n"  	              "\t\tPreprocessorDefinitions=\"" << definesList << "\"\n" -	              "\t\tExceptionHandling=\"" << (setup.devTools ? "1" : "0") << "\"\n"; +	              "\t\tExceptionHandling=\"" << ((setup.devTools || setup.tests) ? "1" : "0") << "\"\n";  #if NEEDS_RTTI  	properties << "\t\tRuntimeTypeInfo=\"true\"\n"; @@ -235,7 +251,7 @@ void VisualStudioProvider::outputGlobalPropFile(const BuildSetup &setup, std::of  	              "\t\tIgnoreDefaultLibraryNames=\"\"\n"  	              "\t\tSubSystem=\"1\"\n"; -	if (!setup.devTools) +	if (!setup.devTools && !setup.tests)  		properties << "\t\tEntryPointSymbol=\"WinMainCRTStartup\"\n";  	properties << "\t\tAdditionalLibraryDirectories=\"$(" << LIBS_DEFINE << ")\\lib\\" << ((bits == 32) ? "x86" : "x64") << "\"\n" | 
