diff options
| -rw-r--r-- | .gitmodules | 6 | ||||
| -rw-r--r-- | Jenkinsfile | 25 | ||||
| -rw-r--r-- | bootstrap.bat | 20 | ||||
| -rwxr-xr-x | bootstrap.sh | 2 | ||||
| -rwxr-xr-x | clbootstrap.sh | 48 | ||||
| -rwxr-xr-x | clrun.sh | 31 | ||||
| -rw-r--r-- | ctor.cc | 22 | ||||
| m--------- | getopt-for-windows | 0 | ||||
| m--------- | json | 0 | ||||
| -rw-r--r-- | src/bootstrap.cc | 2 | ||||
| -rw-r--r-- | src/configure.cc | 108 | ||||
| -rw-r--r-- | src/ctor.h | 13 | ||||
| -rw-r--r-- | src/deps.cc | 74 | ||||
| -rw-r--r-- | src/execute.cc | 227 | ||||
| -rw-r--r-- | src/libctor.cc | 3 | ||||
| -rw-r--r-- | src/rebuild.cc | 15 | ||||
| -rw-r--r-- | src/task.cc | 9 | ||||
| -rw-r--r-- | src/task_ar.cc | 3 | ||||
| -rw-r--r-- | src/task_cc.cc | 2 | ||||
| -rw-r--r-- | src/task_ld.cc | 23 | ||||
| -rw-r--r-- | src/task_so.cc | 3 | ||||
| -rw-r--r-- | src/tools.cc | 409 | ||||
| -rw-r--r-- | src/util.cc | 51 | ||||
| -rw-r--r-- | test/ctor.cc | 54 | ||||
| -rw-r--r-- | test/deps_test.cc | 42 | ||||
| -rw-r--r-- | test/execute_test.cc | 8 | ||||
| -rw-r--r-- | test/source_type_test.cc | 8 | ||||
| -rwxr-xr-x | test/suite/test.sh | 2 | ||||
| -rw-r--r-- | test/tasks_test.cc | 76 | ||||
| -rw-r--r-- | test/testprog.cc | 38 | ||||
| -rw-r--r-- | test/tmpfile.h | 31 | ||||
| -rw-r--r-- | test/tools_test.cc | 315 | 
32 files changed, 1383 insertions, 287 deletions
diff --git a/.gitmodules b/.gitmodules index c765825..383739b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,9 @@  [submodule "test/uunit"]  	path = test/uunit  	url = git://git.drumgizmo.org/uunit.git +[submodule "getopt-for-windows"] +	path = getopt-for-windows +	url = https://github.com/Chunde/getopt-for-windows.git +[submodule "json"] +	path = json +	url = https://github.com/nlohmann/json.git diff --git a/Jenkinsfile b/Jenkinsfile index 290f412..3812aca 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -44,5 +44,30 @@ pipeline {  			}  		}  		//////////////////////////////////////////////////// +		stage('Windows msvc') { +			agent { label 'win10 && msvc' } +			environment +			{ +				VSDEVCMD="C:\\Program Files (x86)\\Microsoft Visual Studio\\2022\\BuildTools\\Common7\\Tools\\VsDevCmd.bat" +			} +			steps { +				echo 'Cleaning workspace ...' +				bat 'git clean -d -x -f' +				dir ('build/test') { +					writeFile file:'dummy', text:'' +				} +				bat '"%VSDEVCMD%" && bootstrap.bat && snot.exe' +				echo 'Testing (msvc) ...' +				bat 'snot.exe check' +			} +			post { +				always { +					xunit(thresholds: [ skipped(failureThreshold: '0'), +					                    failed(failureThreshold: '0') ], +					      tools: [ CppUnit(pattern: 'build/test/*.xml') ]) +				} +			} +		} +		////////////////////////////////////////////////////  	}  } diff --git a/bootstrap.bat b/bootstrap.bat new file mode 100644 index 0000000..2493eb6 --- /dev/null +++ b/bootstrap.bat @@ -0,0 +1,20 @@ +set CXX=cl.exe +set CC=cl.exe +set AR=lib.exe +set LD=link.exe + +%CXX% /nologo /MT /std:c++20 /D_X86_ /EHsc /Isrc /Fo:build\ ctor.cc src\bootstrap.cc /link /out:snot.exe +@if %errorlevel% neq 0 exit /b %errorlevel% + +snot.exe +@if %errorlevel% neq 0 exit /b %errorlevel% + +%CXX% /nologo /std:c++20 /D_X86_ /EHsc /Isrc /Fo:build\ ctor.cc /c +@if %errorlevel% neq 0 exit /b %errorlevel% +%CXX% /nologo /std:c++20 /D_X86_ /EHsc /Isrc /Fo:build\test\ test\ctor.cc /c +@if %errorlevel% neq 0 exit /b %errorlevel% +%LD% /nologo build\libctor.lib build\ctor.obj build\test\ctor.obj /subsystem:console /out:snot.exe +@if %errorlevel% neq 0 exit /b %errorlevel% + +snot.exe configure --ctor-includedir=src --ctor-libdir=build +@if %errorlevel% neq 0 exit /b %errorlevel% diff --git a/bootstrap.sh b/bootstrap.sh index 9e8cdca..052d8b7 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -6,7 +6,7 @@ set -e  CXX=$(which $CXX)  echo "Bootstrapping..." -$CXX -std=c++20 -Wall -O3 -Isrc -pthread src/bootstrap.cc ctor.cc test/ctor.cc -o ctor +$CXX -std=c++20 -Wall -O3 -Isrc -pthread src/bootstrap.cc ctor.cc -o ctor  ./ctor  $CXX -std=c++20 -Wall -O3 -Isrc -pthread ctor.cc test/ctor.cc -L$BUILDDIR -lctor -o ctor  ./ctor configure --ctor-includedir=src --ctor-libdir=$BUILDDIR --build-dir=$BUILDDIR diff --git a/clbootstrap.sh b/clbootstrap.sh new file mode 100755 index 0000000..47664d1 --- /dev/null +++ b/clbootstrap.sh @@ -0,0 +1,48 @@ +#!/bin/bash +set -e +set -x +export WINEDEBUG=-all + +export BASE='C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133' +export ONECORELIB="$BASE\lib\onecore\x86" +export WINEPATH="$BASE\bin\Hostx86\x86" +export INCLUDE="$BASE\include" +export UCRT="C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt" +export UCRTLIB="C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\ucrt\x86" +export UM="C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um" +export UMLIB="C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x86" +export SHARED="C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\shared" +echo Bootstrapping... + +export CL="/I\"$BASE\include\" /I\"$UCRT\" /I\"$UM\" /I\"$SHARED\" /link /LIBPATH:\"$UMLIB\" /LIBPATH:\"$ONECORELIB\" /LIBPATH:\"$UCRTLIB\"" +export LINK="/LIBPATH:\"$UMLIB\" /LIBPATH:\"$ONECORELIB\" /LIBPATH:\"$UCRTLIB\"" +export LIB="/LIBPATH:\"$UMLIB\" /LIBPATH:\"$ONECORELIB\" /LIBPATH:\"$UCRTLIB\"" + +# https://docs.microsoft.com/en-us/cpp/build/reference/cl-environment-variables?view=msvc-170 + +# set INCLUDE="$BASE\include";$UCRT;$UM;$SHARED +# set LIB= +# set LIBPATH=$UMLIB;$ONECORELIB;$UCRTLIB + +rm -Rf ctor.exe build/ configuration.cc +mkdir build +export CXX="cl.exe" +export CC="cl.exe" +export AR="lib.exe" +export LD="link.exe" + +wine cl /nologo /std:c++20 /D_X86_ /EHsc /Isrc /Fo:build/ ctor.cc src/bootstrap.cc /link /out:ctor.exe +#sleep 1 +wine ctor.exe +#sleep 1 +wine cl /nologo /std:c++20 /D_X86_ /EHsc /Isrc /Fo:build/ ctor.cc build/libctor.lib /link /subsystem:console /out:ctor.exe +#sleep 1 +wine ctor.exe configure --ctor-includedir=src --ctor-libdir=build +#sleep 1 + +#exit 0 + +wine ctor.exe -a test/ctor.cc +#sleep 1 +wine ctor.exe -v check +#sleep 1 diff --git a/clrun.sh b/clrun.sh new file mode 100755 index 0000000..d2e57f3 --- /dev/null +++ b/clrun.sh @@ -0,0 +1,31 @@ +#!/bin/bash +set -e +set -x +export WINEDEBUG=-all + +rm -f ~/.wine/drive_c/number + +export BASE='C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133' +export ONECORELIB="$BASE\lib\onecore\x86" +export WINEPATH="$BASE\bin\Hostx86\x86" +export INCLUDE="$BASE\include" +export UCRT="C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt" +export UCRTLIB="C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\ucrt\x86" +export UM="C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um" +export UMLIB="C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x86" +export SHARED="C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\shared" + +export CL="/I\"$BASE\include\" /I\"$UCRT\" /I\"$UM\" /I\"$SHARED\" /link /LIBPATH:\"$UMLIB\" /LIBPATH:\"$ONECORELIB\" /LIBPATH:\"$UCRTLIB\"" +export LINK="/LIBPATH:\"$UMLIB\" /LIBPATH:\"$ONECORELIB\" /LIBPATH:\"$UCRTLIB\"" +export LIB="/LIBPATH:\"$UMLIB\" /LIBPATH:\"$ONECORELIB\" /LIBPATH:\"$UCRTLIB\"" + +export CXX="cl.exe" +export CC="cl.exe" +export AR="lib.exe" +export LD="link.exe" + + +#wine ctor.exe + +$* + @@ -30,8 +30,23 @@ ctor::build_configurations ctorConfigs(const ctor::settings& settings)  				"src/tools.cc",  				"src/util.cc",  				"src/unittest.cc", +				{ctor::toolchain::msvc, "getopt-for-windows/getopt.c"},  			},  			.flags = { +				.cflags = { +					"-O3", +//					"-g", +//					"-Wall", +//					"-Wconversion", +//					"-Wextra", +					//"-Werror", +					"-Isrc", +					{ctor::toolchain::msvc, ctor::c_opt::custom, "/Igetopt-for-windows"}, +					{ctor::toolchain::msvc, ctor::c_opt::custom, "/D_X86_"}, +					{ctor::toolchain::msvc, ctor::c_opt::custom, "/EHsc"}, +					{ctor::toolchain::msvc, ctor::c_opt::custom, "/external:W0"}, +					{ctor::toolchain::msvc, ctor::c_opt::custom, "/D_CRT_SECURE_NO_WARNINGS"}, +				},  				.cxxflags = {  					"-std=c++20",  					"-O3", @@ -43,6 +58,13 @@ ctor::build_configurations ctorConfigs(const ctor::settings& settings)  					"-Wconversion",  //					"-Wnrvo",  					"-Isrc", +					"-Ijson/include", +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/Igetopt-for-windows"}, +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/D_X86_"}, +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/EHsc"}, +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/external:W0"}, +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/D_CRT_SECURE_NO_WARNINGS"}, +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/Dstrdup=_strdup"},  				},  			},  		} diff --git a/getopt-for-windows b/getopt-for-windows new file mode 160000 +Subproject 76fe2df86f84771775fd2f1a641a09adbce28df diff --git a/json b/json new file mode 160000 +Subproject 6be4e8560023098fdb6d2047e6e6e5bc5dd5287 diff --git a/src/bootstrap.cc b/src/bootstrap.cc index aa50561..9d895ba 100644 --- a/src/bootstrap.cc +++ b/src/bootstrap.cc @@ -41,7 +41,7 @@ bool ctor::configuration::has(const std::string& key) const  	return false;  } -const std::string& ctor::configuration::get(const std::string& key, const std::string& default_value) const +std::string ctor::configuration::get(const std::string& key, const std::string& default_value) const  {  	auto cxx_env = std::getenv("CXX");  	if(key == ctor::cfg::build_cxx && cxx_env) diff --git a/src/configure.cc b/src/configure.cc index 995e340..d2c1053 100644 --- a/src/configure.cc +++ b/src/configure.cc @@ -8,6 +8,8 @@  #include <fstream>  #include <optional>  #include <span> +#include <vector> +#include <deque>  #include <getoptpp/getoptpp.hpp> @@ -25,17 +27,49 @@ const std::filesystem::path configHeaderFile("config.h");  std::map<std::string, std::string> external_includedir;  std::map<std::string, std::string> external_libdir; +#if !defined(_WIN32)  const ctor::configuration& __attribute__((weak)) ctor::get_configuration() +#else +const ctor::configuration& default_get_configuration() +#endif  {  	static ctor::configuration cfg;  	static bool initialised{false};  	if(!initialised)  	{ -		cfg.build_toolchain = getToolChain(cfg.get(ctor::cfg::build_cxx, "/usr/bin/g++")); +		std::string cxx_prog{"g++"}; +		auto cxx_env = getenv("CXX"); +		if(cxx_env) +		{ +			cxx_prog = cxx_env; +		} + +		cfg.build_toolchain = getToolChain(cfg.get(ctor::cfg::build_cxx, cxx_prog));  		initialised = true;  	}  	return cfg;  } +#if defined(_WIN32) +// Hack to make ctor::get_configuration "weak" linked +// See: +//   https://stackoverflow.com/questions/2290587/gcc-style-weak-linking-in-visual-studio +// and +//   https://stackoverflow.com/questions/11849853/how-to-list-functions-present-in-object-file +#pragma comment(linker, "/alternatename:?get_configuration@ctor@@YAABUconfiguration@1@XZ=?default_get_configuration@@YAABUconfiguration@ctor@@XZ") + +/* + +?get_configuration@ctor@@YAABUconfiguration@1@XZ +??__Fcfg@?1??get_configuration@ctor@@YAABUconfiguration@1@XZ@YAXXZ + += + +?default_get_configuration@@YAABUconfiguration@ctor@@XZ +??__Fcfg@?1??default_get_configuration@@YAABUconfiguration@ctor@@XZ@YAXXZ + +*/ +//#pragma comment(linker, "/alternatename:??__Fcfg@?1??get_configuration@ctor@@YAABUconfiguration@1@XZ@YAXXZ=??__Fcfg@?1??default_get_configuration@@YAABUconfiguration@ctor@@XZ@YAXXZ") +#endif  namespace ctor {  std::optional<std::string> includedir; @@ -69,7 +103,7 @@ bool ctor::configuration::has(const std::string& key) const  	return tools.find(key) != tools.end();  } -const std::string& ctor::configuration::get(const std::string& key, const std::string& default_value) const +std::string ctor::configuration::get(const std::string& key, const std::string& default_value) const  {  	if(key == ctor::cfg::ctor_includedir && ctor::includedir)  	{ @@ -91,11 +125,47 @@ const std::string& ctor::configuration::get(const std::string& key, const std::s  		return ctor::conf_values[key];  	} -	if(has(key)) +	if(tools.find(key) != tools.end())  	{  		return tools.at(key);  	} +	if(key == ctor::cfg::build_cxx) +	{ +		auto e = std::getenv("CXX"); +		if(e) +		{ +			return e; +		} +	} + +	if(key == ctor::cfg::build_cc) +	{ +		auto e = std::getenv("CC"); +		if(e) +		{ +			return e; +		} +	} + +	if(key == ctor::cfg::build_ld) +	{ +		auto e = std::getenv("LD"); +		if(e) +		{ +			return e; +		} +	} + +	if(key == ctor::cfg::build_ar) +	{ +		auto e = std::getenv("AR"); +		if(e) +		{ +			return e; +		} +	} +  	return default_value;  } @@ -136,6 +206,9 @@ std::ostream& operator<<(std::ostream& stream, const ctor::toolchain& toolchain)  	case ctor::toolchain::gcc:  		stream << "ctor::toolchain::gcc";  		break; +	case ctor::toolchain::msvc: +		stream << "ctor::toolchain::msvc"; +		break;  	case ctor::toolchain::clang:  		stream << "ctor::toolchain::clang";  		break; @@ -358,13 +431,12 @@ int regenerateCache(ctor::settings& settings,  	opt.add("help", no_argument, 'h',  	        "Print this help text.", -	        [&]() { +	        [&]() -> int {  		        std::cout << "Configure how to build with " << name << "\n";  		        std::cout << "Usage: " << name << " configure [options]\n\n";  		        std::cout << "Options:\n";  		        opt.help();  		        exit(0); -		        return 0;  	        });  	opt.process(static_cast<int>(vargs.size()), vargs.data()); @@ -651,6 +723,7 @@ int regenerateCache(ctor::settings& settings,  	{  		ctor::conf_values[ctor::cfg::builddir] = builddir;  	} +  	ctor::conf_values[ctor::cfg::host_cxx] = host_cxx;  	ctor::conf_values[ctor::cfg::build_cxx] = build_cxx; @@ -863,6 +936,31 @@ int configure(const ctor::settings& global_settings, int argc, char* argv[])  		env["PATH"] = path_env;  	} +	// Env vars for msvc +	auto cl_env = getenv("CL"); +	if(cl_env) +	{ +		env["CL"] = cl_env; +	} + +	auto lib_env = getenv("LIB"); +	if(lib_env) +	{ +		env["LIB"] = lib_env; +	} + +	auto link_env = getenv("LINK"); +	if(link_env) +	{ +		env["LINK"] = link_env; +	} + +	auto include_env = getenv("INCLUDE"); +	if(include_env) +	{ +		env["INCLUDE"] = include_env; +	} +  	auto ret = regenerateCache(settings, args_span[0], args, env);  	if(ret != 0)  	{ @@ -59,6 +59,7 @@ enum class toolchain  	none,  	gcc,  	clang, +	msvc,  };  struct source @@ -90,6 +91,9 @@ enum class cxx_opt  	output,                          //  -o  	debug,                           //  -g  	warn_all,                        //  -Wall +	warn_conversion,                 //  -Wconversion +	warn_shadow,                     //  -Wshadow +	warn_extra,                      //  -Wextra  	warnings_as_errors,              //  -Werror  	generate_dep_tree,               //  -MMD  	no_link,                         //  -c @@ -108,6 +112,9 @@ enum class c_opt  	output,                          //  -o  	debug,                           //  -g  	warn_all,                        //  -Wall +	warn_conversion,                 //  -Wconversion +	warn_shadow,                     //  -Wshadow +	warn_extra,                      //  -Wextra  	warnings_as_errors,              //  -Werror  	generate_dep_tree,               //  -MMD  	no_link,                         //  -c @@ -261,12 +268,12 @@ namespace cfg  constexpr auto builddir = "builddir";  constexpr auto host_cc = "host-cc"; -constexpr auto host_cxx = "host-cpp"; +constexpr auto host_cxx = "host-cxx";  constexpr auto host_ar = "host-ar";  constexpr auto host_ld = "host-ld";  constexpr auto build_cc = "build-cc"; -constexpr auto build_cxx = "build-cpp"; +constexpr auto build_cxx = "build-cxx";  constexpr auto build_ar = "build-ar";  constexpr auto build_ld = "build-ld"; @@ -277,7 +284,7 @@ constexpr auto ctor_libdir = "ctor-libdir";  struct configuration  {  	bool has(const std::string& key) const; -	const std::string& get(const std::string& key, const std::string& default_value = {}) const; +	std::string get(const std::string& key, const std::string& default_value = {}) const;  	ctor::toolchain host_toolchain{ctor::toolchain::none};  	ctor::arch host_arch{ctor::arch::unknown}; diff --git a/src/deps.cc b/src/deps.cc index 9400b35..599be8c 100644 --- a/src/deps.cc +++ b/src/deps.cc @@ -5,6 +5,8 @@  #include "util.h" +#include <nlohmann/json.hpp> +  #include <fstream>  namespace { @@ -94,6 +96,74 @@ std::vector<std::string> readDepsMake(const std::string& dep_file)  	return output;  } + +// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1689r5.html +// https://devblogs.microsoft.com/cppblog/introducing-source-dependency-reporting-with-msvc-in-visual-studio-2019-version-16-7/ +/* Format examples: +{ +    "Version": "1.1", +    "Data": { +        "Source": "z:\\home\\deva\\docs\\c\\ctor\\src\\libctor.cc", +        "ProvidedModule": "", +        "Includes": [ +            "c:\\program files (x86)\\microsoft visual studio\\2019\\buildtools\\vc\\tools\\msvc\\14.29.30133\\include\\vector", +            "c:\\program files (x86)\\microsoft visual studio\\2019\\buildtools\\vc\\tools\\msvc\\14.29.30133\\include\\yvals_core.h", +            "c:\\program files (x86)\\microsoft visual studio\\2019\\buildtools\\vc\\tools\\msvc\\14.29.30133\\include\\vcruntime.h", +. +. +. +            "z:\\home\\deva\\docs\\c\\ctor\\src\\unittest.h" +        ], +        "ImportedModules": [], +        "ImportedHeaderUnits": [] +    } +} +*/ +/* +{ +    "Version": "1.2", +    "Data": { +        "Source": "c:\\jenkins\\workspace\\ctor-linux64\\src\\build.cc", +        "ProvidedModule": "", +        "Includes": [ +            "c:\\jenkins\\workspace\\ctor-linux64\\src\\build.h", +            "c:\\program files (x86)\\microsoft visual studio\\2022\\buildtools\\vc\\tools\\msvc\\14.42.34433\\include\\string", +            "c:\\program files (x86)\\microsoft visual studio\\2022\\buildtools\\vc\\tools\\msvc\\14.42.34433\\include\\yvals_core.h", +. +. +. +            "c:\\program files (x86)\\microsoft visual studio\\2022\\buildtools\\vc\\tools\\msvc\\14.42.34433\\include\\iostream" +        ], +        "ImportedModules": [], +        "ImportedHeaderUnits": [] +    } +} +*/ + +std::vector<std::string> readDepsJson(const std::string& dep_file) +{ +	std::ifstream stream(dep_file); +	auto json = nlohmann::json::parse(stream); +	for(const auto& [key, value] : json.items()) +	{ +		if(key == "Data" && value.is_object()) +		{ +			for(const auto& [inner_key, inner_value] : value.items()) +			{ +				if(inner_key == "Includes" && inner_value.is_array()) +				{ +					std::vector<std::string> deps; +					for(const auto& dep : inner_value) +					{ +						deps.emplace_back(dep); +					} +					return deps; +				} +			} +		} +	} +	return {}; +}  }  std::vector<std::string> readDeps(const std::string& dep_file, @@ -110,6 +180,10 @@ std::vector<std::string> readDeps(const std::string& dep_file,  	case ctor::toolchain::none:  		return {}; +	// json based: +	case ctor::toolchain::msvc: +		return readDepsJson(dep_file); +  	// makefile .d file based:  	case ctor::toolchain::gcc:  	case ctor::toolchain::clang: diff --git a/src/execute.cc b/src/execute.cc index cbae899..58e0051 100644 --- a/src/execute.cc +++ b/src/execute.cc @@ -5,12 +5,22 @@  #include "ctor.h" -#include <unistd.h> -#include <cstring> -#include <sys/types.h> -#include <sys/wait.h> -#include <spawn.h> +#if !defined(_WIN32) +	#include <unistd.h> +	#include <sys/types.h> +	#include <sys/wait.h> +	#include <spawn.h> +#else +	#define WINDOWS_LEAN_AND_MEAN +	#include <windows.h> +	#undef max +#endif +  #include <iostream> +#include <cstring> +#include <vector> +#include <deque> +#include <filesystem>  /*  https://blog.famzah.net/2009/11/20/a-much-faster-popen-and-system-implementation-for-linux/ @@ -30,7 +40,11 @@ public:  	{  		for(const auto& arg : args)  		{ +#if !defined(_WIN32)  			push_back(strdup(arg.data())); +#else +			push_back(_strdup(arg.data())); +#endif  		}  		push_back(nullptr);  	} @@ -44,6 +58,7 @@ public:  	}  }; +#if !defined(_WIN32)  int parent_waitpid(pid_t pid)  {  	int status{}; @@ -55,9 +70,44 @@ int parent_waitpid(pid_t pid)  	return WEXITSTATUS(status);  } +#endif //_WIN32  } // namespace :: +#if !defined(_WIN32)  extern char **environ; // see 'man environ' +#endif + +#if defined(_WIN32) +//Returns the last Win32 error, in string format. Returns an empty string if there is no error. +std::string GetLastErrorAsString() +{ +	//Get the error message ID, if any. +	DWORD errorMessageID = ::GetLastError(); +	if(errorMessageID == 0) +	{ +		return std::string(); //No error message has been recorded +	} + +	LPSTR messageBuffer = nullptr; + +	//Ask Win32 to give us the string version of that message ID. +	//The parameters we pass in, tell Win32 to create the buffer that holds the message for us +	// (because we don't yet know how long the message string will be). +	size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | +	                             FORMAT_MESSAGE_FROM_SYSTEM | +	                             FORMAT_MESSAGE_IGNORE_INSERTS, +	                             NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), +	                             (LPSTR)&messageBuffer, 0, NULL); + +	//Copy the error message into a std::string. +	std::string message(messageBuffer, size); + +	//Free the Win32's string's buffer. +	LocalFree(messageBuffer); + +	return message; +} +#endif // _WIN32  int execute(const ctor::settings& settings,              const std::string& command, @@ -92,6 +142,8 @@ int execute(const ctor::settings& settings,  		std::cout << cmd << std::endl;  	} +#if !defined(_WIN32) +  #if 1  	auto pid = vfork();  	if(pid == 0) @@ -133,5 +185,170 @@ int execute(const ctor::settings& settings,  	return system(cmd.data());  #endif +#else // _WIN32 +	std::map<std::string, std::string> new_env; +	{ +		auto env_strings = GetEnvironmentStrings(); +		const char* ptr = env_strings; +		std::string key; +		std::string value; +		bool key_state{true}; +		while(true) +		{ +			if(key_state) // searching for key +			{ +				if(*ptr == '\0') +				{ +					break; +				} + +				if(*ptr != '=') +				{ +					key += *ptr; +				} +				else +				{ +					key_state = false; +				} +			} +			else +			{ +				if(*ptr != '\0') +				{ +					value += *ptr; +				} +				else +				{ +					new_env.insert({key, value}); +					key = {}; +					value = {}; +					key_state = true; +				} +			} +		++ptr; +		} +		FreeEnvironmentStrings(env_strings); +	} + +	// add new env vars (if any) +	for(const auto& [key, value] : env) +	{ +		//if(key == "CL" || key == "LINK" || key == "LIB") +		{ +			new_env[key] = value; +		} +	} + +	std::string env_str; +	for(const auto& [k,v] : new_env) +	{ +		env_str += k + "=" + v; +		env_str += '\0'; +	} +	env_str += '\0'; + +//	std::cout <<"#### Length of new env: " << env_str.size() << "\n"; + +	STARTUPINFO si{}; +//	si.hStdInput = GetStdHandle(((DWORD)-10)/*STD_INPUT_HANDLE*/); +//	si.hStdOutput = GetStdHandle(((DWORD)-11)/*STD_OUTPUT_HANDLE*/); +//	si.hStdError = GetStdHandle(((DWORD)-12)/*STD_ERROR_HANDLE*/); +//	si.dwFlags = /*STARTF_USESTDHANDLES*/0x00000100; + +	PROCESS_INFORMATION pi{}; + +	si.cb = sizeof(si); + +	// TODO: Use SetDllDirectory(...) to set DLL search directory + +	if(terminate) +	{ +		char tmpdir[MAX_PATH+1]; +		int cnt{0}; + +		// The returned string ends with a backslash +		if(GetTempPathA(sizeof(tmpdir), tmpdir) == 0) +		{ +			std::cerr << "Could not read TMP folder\n"; +			return GetLastError(); +		} + +		char source[MAX_PATH]; +		HMODULE module = GetModuleHandle(0); +		GetModuleFileNameA(module, source, MAX_PATH); + +		while(true) +		{ +			if(cnt > 10) // If we need to try more than 10 times something is wrong +			{ +				return 1; +			} + +			std::filesystem::path tmp_file = settings.builddir; +			tmp_file /= "tmp"; +			std::string target = tmp_file.string() + "-" + std::to_string(cnt); +			std::cout << "move " << source << " => " << target <<std::endl; +			if(MoveFileA(source, target.data())) +			{ +				break; // success +			} + +			auto err = GetLastError(); +			if(err == ERROR_ALREADY_EXISTS) +			{ +				if(DeleteFileA(target.data())) +				{ +					continue; // Try again +				} + +				err = GetLastError(); +				if(err != ERROR_ACCESS_DENIED) +				{ +					std::cerr << "Could not delete file\n"; +					return err; +				} + +				cnt++; +				continue; // Increment and try again +			} +			else +			{ +				std::cerr << "Could not move file\n"; +				return err; +			} +		} +	} + +	if(!CreateProcess(nullptr,           // lpApplicationName +	                  (char*)cmd.data(), // lpCommandLine +	                  nullptr,           // lpProcessAttributes +	                  nullptr,           // lpThreadAttributes +	                  TRUE,              // bInheritHandles +	                  INHERIT_PARENT_AFFINITY | +	                  //DETACHED_PROCESS | +	                  ///*DEBUG_PROCESS*/ 0x00000001 | +	                  ///*CREATE_NO_WINDOW*/ 0x08000000 | +	                  ///*CREATE_BREAKAWAY_FROM_JOB*/ 0x01000000 | +	                  /*CREATE_NEW_PROCESS_GROUP*/ 0x00000200 | +	                  0,                 // dwCreationFlags +	                  env_str.data(),    // lpEnvironment +	                  nullptr,           // lpCurrentDirectory +	                  &si,               // lpStartupInfo +	                  &pi))              // lpProcessInformation +	{ +		std::cout << "Could not execute " << command << ": " << +			GetLastErrorAsString() << "\n"; +		return 1;//_exit(1); // execve only returns if an error occurred +	} + +	// Now 'pi.hProcess' contains the process HANDLE, which you can use to +	// wait for it like this: +	const DWORD infinite = 0xFFFFFFFF; +	WaitForSingleObject(pi.hProcess, infinite); +	DWORD exitCode{0}; +	GetExitCodeProcess(pi.hProcess, &exitCode); +	return exitCode; +#endif // _WIN32 +  	return 1;  } diff --git a/src/libctor.cc b/src/libctor.cc index b1fbaea..aaf17c9 100644 --- a/src/libctor.cc +++ b/src/libctor.cc @@ -159,7 +159,7 @@ int main(int argc, char* argv[])  	opt.add("help", no_argument, 'h',  	        "Print this help text.", -	        [&]() { +	        [&]() -> int {  		        std::cout << "Usage: " << args[0] << " [options] [target] ...\n";  		        std::cout <<  R"_( where target can be either: @@ -174,7 +174,6 @@ Options:  )_";  		        opt.help();  		        exit(0); -		        return 0;  	        });  	opt.process(argc, argv); diff --git a/src/rebuild.cc b/src/rebuild.cc index 4ca1809..865a45b 100644 --- a/src/rebuild.cc +++ b/src/rebuild.cc @@ -38,7 +38,10 @@ int reg(ctor::build_configurations (*cb)(const ctor::settings&),  	{  		auto pwd = std::filesystem::current_path();  		auto rel = std::filesystem::relative(loc, pwd); -		configFiles[numConfigFiles].file = strdup(rel.string().data()); // NOTE: This intentionally leaks memory +		auto str = rel.string(); +		auto file = new char[str.size() + 1]; +		strncpy(file, str.data(), str.size() + 1); +		configFiles[numConfigFiles].file = file; // NOTE: This intentionally leaks memory  	}  	else  	{ @@ -71,7 +74,7 @@ int reg(const char* location)  int unreg(const char* location)  { -	std::size_t found{0}; +	int found{0};  	for(std::size_t i = 0; i < numConfigFiles;)  	{  		if(std::string(location) == configFiles[i].file) @@ -169,6 +172,8 @@ bool recompileCheck(const ctor::settings& global_settings, int argc, char* argv[  	config.flags.cxxflags.emplace_back(ctor::cxx_opt::optimization, "3");  	config.flags.cxxflags.emplace_back(ctor::cxx_opt::cpp_std, "c++20"); +	config.flags.cxxflags.push_back({ctor::toolchain::msvc, ctor::cxx_opt::custom, "/EHsc"}); +  	const auto& c = ctor::get_configuration();  	if(c.has(ctor::cfg::ctor_includedir))  	{ @@ -180,10 +185,14 @@ bool recompileCheck(const ctor::settings& global_settings, int argc, char* argv[  		config.flags.ldflags.emplace_back(ctor::ld_opt::library_path,  		                                  c.get(ctor::cfg::ctor_libdir));  	} -	config.flags.ldflags.emplace_back(ctor::ld_opt::link, "ctor"); +	config.flags.ldflags.emplace_back(ctor::toolchain::msvc, ctor::ld_opt::link, "libctor.lib"); +	config.flags.ldflags.emplace_back(ctor::toolchain::gcc, ctor::ld_opt::link, "ctor"); +	config.flags.ldflags.emplace_back(ctor::toolchain::clang, ctor::ld_opt::link, "ctor");  	config.flags.ldflags.emplace_back(ctor::ld_opt::strip);  	config.flags.ldflags.emplace_back(ctor::ld_opt::threads); +	config.flags.ldflags.push_back({ctor::toolchain::msvc, ctor::ld_opt::custom, "/subsystem:console"}); +  	ctor::settings settings{global_settings};  	settings.verbose = -1; // Make check completely silent. diff --git a/src/task.cc b/src/task.cc index cd03fce..ef7731b 100644 --- a/src/task.cc +++ b/src/task.cc @@ -48,10 +48,11 @@ bool Task::operator==(const std::string& depStr)  	std::filesystem::path generated_output = sourceDir;  	generated_output /= target();  	return -		name() == depStr || -		target() == depStr || -		generated_output  == depStr || -		targetFile().string() == depStr +		(!derived() && name() == depStr) || // compare to name +		(!derived() && config.target == depStr) || // compare to stated target (ex. foo.a) +		target() == depStr || // compare to derived (derived to foo.lib on msvc) +		generated_output  == depStr || // not sure what this is for?! +		targetFile().string() == depStr // compare to target output file  		;  } diff --git a/src/task_ar.cc b/src/task_ar.cc index 09403bb..25ab7c0 100644 --- a/src/task_ar.cc +++ b/src/task_ar.cc @@ -93,6 +93,8 @@ int TaskAR::runInner()  	append(args, ar_option(toolchain, ctor::ar_opt::add_index));  	append(args, ar_option(toolchain, ctor::ar_opt::create));  	append(args, ar_option(toolchain, ctor::ar_opt::output, targetFile().string())); +	append(args, to_strings(toolchain, {ctor::toolchain::msvc, ctor::ar_opt::custom, "/nologo"})); +  	for(const auto& task : getDependsTasks())  	{  		args.push_back(task->targetFile().string()); @@ -189,7 +191,6 @@ std::string TaskAR::flagsString() const  			flagsStr += str;  		}  	} -	flagsStr += "\n";  	for(const auto& dep : config.depends)  	{ diff --git a/src/task_cc.cc b/src/task_cc.cc index 9de2657..2e15555 100644 --- a/src/task_cc.cc +++ b/src/task_cc.cc @@ -278,12 +278,14 @@ std::vector<std::string> TaskCC::flags() const  		{  			append(flags, to_strings(toolchain, flag));  		} +		append(flags, to_strings(toolchain, {ctor::toolchain::msvc, ctor::c_opt::custom, "/nologo"}));  		return flags;  	case ctor::language::cpp:  		for(const auto& flag : config.flags.cxxflags)  		{  			append(flags, to_strings(toolchain, flag));  		} +		append(flags, to_strings(toolchain, {ctor::toolchain::msvc, ctor::cxx_opt::custom, "/nologo"}));  		return flags;  	default:  		std::cerr << "Unknown CC target type\n"; diff --git a/src/task_ld.cc b/src/task_ld.cc index 31ee8c0..9dcbb3a 100644 --- a/src/task_ld.cc +++ b/src/task_ld.cc @@ -115,6 +115,7 @@ int TaskLD::runInner()  	}  	append(args, ld_option(toolchain, ctor::ld_opt::output, targetFile().string())); +	append(args, to_strings(toolchain, {ctor::toolchain::msvc, ctor::ld_opt::custom, "/nologo"}));  	{ // Write flags to file.  		std::ofstream flagsStream(flagsFile); @@ -127,8 +128,27 @@ int TaskLD::runInner()  		std::cout << output << std::flush;  	} -	auto tool = compiler(); +	std::string tool;  	const auto& c = ctor::get_configuration(); + +	if(toolchain == ctor::toolchain::gcc || +	   toolchain == ctor::toolchain::clang) +	{ +		tool = compiler(); +	} +	else // msvc +	{ +		switch(outputSystem()) +		{ +		case ctor::output_system::host: +			tool = c.get(ctor::cfg::host_ld, "/usr/bin/ld"); +			break; +		case ctor::output_system::build: +			tool = c.get(ctor::cfg::build_ld, "/usr/bin/ld"); +			break; +		} +	} +  	return execute(settings, tool, args, c.env, is_self);  } @@ -197,7 +217,6 @@ std::string TaskLD::flagsString() const  			flagsStr += str;  		}  	} -	flagsStr += "\n";  	for(const auto& dep : config.depends)  	{ diff --git a/src/task_so.cc b/src/task_so.cc index eecd7aa..f61fa17 100644 --- a/src/task_so.cc +++ b/src/task_so.cc @@ -93,6 +93,8 @@ int TaskSO::runInner()  	append(args, ld_option(toolchain, ctor::ld_opt::output, targetFile().string())); +	append(args, to_strings(toolchain, {ctor::toolchain::msvc, ctor::ld_opt::custom, "/nologo"})); +  	for(const auto& task : getDependsTasks())  	{  		args.push_back(task->targetFile().string()); @@ -184,7 +186,6 @@ std::string TaskSO::flagsString() const  			flagsStr += str;  		}  	} -	flagsStr += "\n";  	for(const auto& dep : config.depends)  	{ diff --git a/src/tools.cc b/src/tools.cc index eb98265..7f16a0e 100644 --- a/src/tools.cc +++ b/src/tools.cc @@ -6,6 +6,7 @@  #include <filesystem>  #include <iostream>  #include <sstream> +#include <algorithm>  #include <cassert>  #include <cstdio> @@ -20,6 +21,9 @@ std::ostream& operator<<(std::ostream& stream, const ctor::c_opt& opt)  	case ctor::c_opt::output: stream << "ctor::c_opt::output"; break;  	case ctor::c_opt::debug: stream << "ctor::c_opt::debug"; break;  	case ctor::c_opt::warn_all: stream << "ctor::c_opt::warn_all"; break; +	case ctor::c_opt::warn_conversion: stream << "ctor::c_opt::warn_conversion"; break; +	case ctor::c_opt::warn_shadow: stream << "ctor::c_opt::warn_shadow"; break; +	case ctor::c_opt::warn_extra: stream << "ctor::c_opt::warn_extra"; break;  	case ctor::c_opt::warnings_as_errors: stream << "ctor::c_opt::warnings_as_errors"; break;  	case ctor::c_opt::generate_dep_tree: stream << "ctor::c_opt::generate_dep_tree"; break;  	case ctor::c_opt::no_link: stream << "ctor::c_opt::no_link"; break; @@ -43,6 +47,9 @@ std::ostream& operator<<(std::ostream& stream, const ctor::cxx_opt& opt)  	case ctor::cxx_opt::output: stream << "ctor::cxx_opt::output"; break;  	case ctor::cxx_opt::debug: stream << "ctor::cxx_opt::debug"; break;  	case ctor::cxx_opt::warn_all: stream << "ctor::cxx_opt::warn_all"; break; +	case ctor::cxx_opt::warn_conversion: stream << "ctor::cxx_opt::warn_conversion"; break; +	case ctor::cxx_opt::warn_shadow: stream << "ctor::cxx_opt::warn_shadow"; break; +	case ctor::cxx_opt::warn_extra: stream << "ctor::cxx_opt::warn_extra"; break;  	case ctor::cxx_opt::warnings_as_errors: stream << "ctor::cxx_opt::warnings_as_errors"; break;  	case ctor::cxx_opt::generate_dep_tree: stream << "ctor::cxx_opt::generate_dep_tree"; break;  	case ctor::cxx_opt::no_link: stream << "ctor::cxx_opt::no_link"; break; @@ -111,18 +118,27 @@ ctor::toolchain getToolChain(const std::string& compiler)  	std::filesystem::path cc(compiler);  	auto cc_cmd = cc.stem().string(); +	std::cout << "getToolChain: [" << cc_cmd << "] => "; +  	// Note: "g++" is a substring of "clang++" so "clang++" must be tested first.  	if(cc_cmd.find("clang++") != std::string::npos ||  	   cc_cmd.find("clang") != std::string::npos)  	{ +		std::cout << "clang" << std::endl;  		return ctor::toolchain::clang;  	}  	else if(cc_cmd.find("g++") != std::string::npos ||  	        cc_cmd.find("gcc") != std::string::npos ||  	        cc_cmd.find("mingw") != std::string::npos)  	{ +		std::cout << "gcc" << std::endl;  		return ctor::toolchain::gcc;  	} +	else if(to_lower(cc_cmd).find("cl") != std::string::npos) +	{ +		std::cout << "msvc" << std::endl; +		return ctor::toolchain::msvc; +	}  	std::cerr << "Unsupported output system.\n";  	return ctor::toolchain::gcc; @@ -148,12 +164,262 @@ ctor::toolchain getToolChain(ctor::output_system system)  		return getToolChain(cfg.get(ctor::cfg::build_cxx, "g++"));  	}  } +namespace msvc { +std::string get_arch([[maybe_unused]] ctor::output_system system) +{ +	std::string arch; +	// TODO +	return arch; +} + +ctor::arch get_arch([[maybe_unused]] const std::string& str) +{ +	return ctor::arch::windows; +} + +ctor::c_flag c_option(const std::string& flag) +{ +	if(flag.starts_with("/I")) +	{ +		std::string path = flag.substr(2); +		path.erase(0, path.find_first_not_of(' ')); +		return { ctor::c_opt::include_path, path }; +	} + +	return { ctor::c_opt::custom, flag }; +} + +ctor::cxx_flag cxx_option(const std::string& flag) +{ +	if(flag.starts_with("/I")) +	{ +		std::string path = flag.substr(2); +		path.erase(0, path.find_first_not_of(' ')); +		return { ctor::cxx_opt::include_path, path }; +	} + +	return { ctor::cxx_opt::custom, flag }; +} + +ctor::ld_flag ld_option(const std::string& flag) +{ +	if(flag.starts_with("/L")) +	{ +		std::string path = flag.substr(2); +		path.erase(0, path.find_first_not_of(' ')); +		return { ctor::ld_opt::library_path, path }; +	} + +	return { ctor::ld_opt::custom, flag }; +} + +ctor::ar_flag ar_option(const std::string& flag) +{ +	return { ctor::ar_opt::custom, flag }; +} + +std::vector<std::string> cxx_option(ctor::cxx_opt opt, const std::string& arg, +                                    const std::string& arg2) +{ +	switch(opt) +	{ +	case ctor::cxx_opt::output: +		return {"/Fo\"" + arg + "\""}; +	case ctor::cxx_opt::debug: +		return {"/DEBUG"}; +	case ctor::cxx_opt::warn_all: +		return {"/W4"}; +	case ctor::cxx_opt::warn_conversion: +		return {"/W4"}; // TODO: This is incorrect +	case ctor::cxx_opt::warn_shadow: +		return {"/W4"}; // TODO: This is incorrect +	case ctor::cxx_opt::warn_extra: +		return {"/W4"}; // TODO: This is incorrect +	case ctor::cxx_opt::warnings_as_errors: +		return {"/WX"}; +	case ctor::cxx_opt::generate_dep_tree: +		return {"/sourceDependencies", arg}; +	case ctor::cxx_opt::no_link: +		return {"/c"}; +	case ctor::cxx_opt::include_path: +		return {"/I" + arg}; +	case ctor::cxx_opt::cpp_std: +		return {"/std:" + arg}; +	case ctor::cxx_opt::optimization: +		{ +			int o{0}; +			try +			{ +				o = std::stoi(arg); +				o = std::clamp(o, 0, 2); +			} +			catch(...) +			{ +				// bad number? +			} +			return {"/O" + std::to_string(o)}; +		} +	case ctor::cxx_opt::position_independent_code: +		return {}; // TODO? +	case ctor::cxx_opt::position_independent_executable: +		return {}; // TODO? +	case ctor::cxx_opt::define: +		if(!arg2.empty()) +		{ +			return {"/D" + arg + "=" + esc(arg2)}; +		} +		else +		{ +			return {"/D" + arg}; +		} +	case ctor::cxx_opt::custom: +		return {arg}; +	} + +	std::cerr << "Unsupported compiler option.\n"; +	return {}; +} + +std::vector<std::string> c_option(ctor::c_opt opt, const std::string& arg, +                                  const std::string& arg2) +{ +	switch(opt) +	{ +	case ctor::c_opt::output: +		return {"/Fo\"" + arg + "\""}; +	case ctor::c_opt::debug: +		return {"/DEBUG"}; +	case ctor::c_opt::warn_all: +		return {"/W4"}; +	case ctor::c_opt::warn_conversion: +		return {"/W4"}; // TODO: This is incorrect +	case ctor::c_opt::warn_shadow: +		return {"/W4"}; // TODO: This is incorrect +	case ctor::c_opt::warn_extra: +		return {"/W4"}; // TODO: This is incorrect +	case ctor::c_opt::warnings_as_errors: +		return {"/WX"}; +	case ctor::c_opt::generate_dep_tree: +		return {"/sourceDependencies", arg}; +	case ctor::c_opt::no_link: +		return {"/c"}; +	case ctor::c_opt::include_path: +		return {"/I" + arg}; +	case ctor::c_opt::c_std: +		return {"/std:" + arg}; +	case ctor::c_opt::optimization: +		{ +			int o{0}; +			try +			{ +				o = std::stoi(arg); +				o = std::clamp(o, 0, 2); +			} +			catch(...) +			{ +				// bad number? +			} +			return {"/O" + std::to_string(o)}; +		} +	case ctor::c_opt::position_independent_code: +		return {}; // TODO? +	case ctor::c_opt::position_independent_executable: +		return {}; // TODO? +	case ctor::c_opt::define: +		if(!arg2.empty()) +		{ +			return {"/D" + arg + "=" + esc(arg2)}; +		} +		else +		{ +			return {"/D" + arg}; +		} +	case ctor::c_opt::custom: +		return {arg}; +	} + +	std::cerr << "Unsupported compiler option.\n"; +	return {}; +} + +std::vector<std::string> ld_option(ctor::ld_opt opt, const std::string& arg, +                                   [[maybe_unused]]const std::string& arg2) +{ +	switch(opt) +	{ +	case ctor::ld_opt::output: +		return {"/out:" + arg + ""}; +	case ctor::ld_opt::strip: +		return {}; // TODO? +	case ctor::ld_opt::warn_all: +		return {"/Wall"}; +	case ctor::ld_opt::warnings_as_errors: +		return {"/WX"}; +	case ctor::ld_opt::library_path: +		return {"/LIBPATH:\""+arg+"\""}; +	case ctor::ld_opt::link: +		return {arg}; // TODO? +	case ctor::ld_opt::cpp_std: +		return {"/std:" + arg}; +	case ctor::ld_opt::build_shared: +		return {}; // TODO? +	case ctor::ld_opt::threads: +		return {}; // TODO? +	case ctor::ld_opt::position_independent_code: +		return {}; // TODO? +	case ctor::ld_opt::position_independent_executable: +		return {}; // TODO? +	case ctor::ld_opt::custom: +		return {arg}; +	} + +	std::cerr << "Unsupported compiler option.\n"; +	return {}; +} + +std::vector<std::string> ar_option(ctor::ar_opt opt, const std::string& arg, +                                   [[maybe_unused]]const std::string& arg2) +{ +	switch(opt) +	{ +	case ctor::ar_opt::replace: +		return {}; +	case ctor::ar_opt::add_index: +		return {}; +	case ctor::ar_opt::create: +		return {}; +	case ctor::ar_opt::output: +		return {"/out:" + arg}; +	case ctor::ar_opt::custom: +		return {arg}; +	} + +	std::cerr << "Unsupported compiler option.\n"; +	return {}; +} + +std::vector<std::string> asm_option(ctor::asm_opt opt, const std::string& arg, +                                    [[maybe_unused]]const std::string& arg2) +{ +	switch(opt) +	{ +	case ctor::asm_opt::custom: +		return {arg}; +	} + +	std::cerr << "Unsupported compiler option.\n"; +	return {}; +} +} // msvc:: +  namespace gcc { -std::string get_arch(ctor::output_system system) +std::string get_arch([[maybe_unused]] ctor::output_system system)  { +	std::string arch; +	// TODO popen on windows +#if !defined(_WIN32)  	std::string cmd; -  	const auto& c = ctor::get_configuration();  	switch(system)  	{ @@ -174,7 +440,6 @@ std::string get_arch(ctor::output_system system)  		return {};//ctor::arch::unknown;  	} -	std::string arch;  	while(!feof(pipe))  	{  		constexpr auto buffer_size{1024}; @@ -200,6 +465,7 @@ std::string get_arch(ctor::output_system system)  	// Remove 'Target: ' prefix  	constexpr auto prefix_length{8};  	arch = arch.substr(prefix_length); +#endif // _WIN32  	return arch;  } @@ -247,6 +513,48 @@ ctor::c_flag c_option(const std::string& flag)  		return { ctor::c_opt::include_path, path };  	} +	if(flag.starts_with("-std=")) +	{ +		std::string std = flag.substr(5); +		return { ctor::c_opt::c_std, std }; +	} + +	if(flag.starts_with("-O")) +	{ +		std::string opt = flag.substr(2, 1); +		return { ctor::c_opt::optimization, opt }; +	} + +	if(flag.starts_with("-Wall")) +	{ +		return { ctor::c_opt::warn_all }; +	} + +	if(flag.starts_with("-Wconversion")) +	{ +		return { ctor::c_opt::warn_conversion}; +	} + +	if(flag.starts_with("-Wshadow")) +	{ +		return { ctor::c_opt::warn_shadow}; +	} + +	if(flag.starts_with("-Wextra")) +	{ +		return { ctor::c_opt::warn_extra}; +	} + +	if(flag.starts_with("-Werror")) +	{ +		return { ctor::c_opt::warnings_as_errors }; +	} + +	if(flag.starts_with("-g")) +	{ +		return { ctor::c_opt::debug }; +	} +  	if(flag.starts_with("-D"))  	{  		std::string def = flag.substr(2); @@ -272,6 +580,48 @@ ctor::cxx_flag cxx_option(const std::string& flag)  		return { ctor::cxx_opt::include_path, path };  	} +	if(flag.starts_with("-std=")) +	{ +		std::string std = flag.substr(5); +		return { ctor::cxx_opt::cpp_std, std }; +	} + +	if(flag.starts_with("-O")) +	{ +		std::string opt = flag.substr(2, 1); +		return { ctor::cxx_opt::optimization, opt }; +	} + +	if(flag.starts_with("-Wall")) +	{ +		return { ctor::cxx_opt::warn_all }; +	} + +	if(flag.starts_with("-Werror")) +	{ +		return { ctor::cxx_opt::warnings_as_errors }; +	} + +	if(flag.starts_with("-Wconversion")) +	{ +		return { ctor::cxx_opt::warn_conversion}; +	} + +	if(flag.starts_with("-Wshadow")) +	{ +		return { ctor::cxx_opt::warn_shadow}; +	} + +	if(flag.starts_with("-Wextra")) +	{ +		return { ctor::cxx_opt::warn_extra}; +	} + +	if(flag.starts_with("-g")) +	{ +		return { ctor::cxx_opt::debug }; +	} +  	if(flag.starts_with("-D"))  	{  		std::string def = flag.substr(2); @@ -298,6 +648,11 @@ ctor::ld_flag ld_option(const std::string& flag)  		return { ctor::ld_opt::library_path, path };  	} +	if(flag.starts_with("-pthread")) +	{ +		return { ctor::ld_opt::threads }; +	} +  	return { ctor::ld_opt::custom, flag };  } @@ -317,6 +672,12 @@ std::vector<std::string> cxx_option(ctor::cxx_opt opt, const std::string& arg,  		return {"-g"};  	case ctor::cxx_opt::warn_all:  		return {"-Wall"}; +	case ctor::cxx_opt::warn_conversion: +		return {"-Wconversion"}; +	case ctor::cxx_opt::warn_shadow: +		return {"-Wshadow"}; +	case ctor::cxx_opt::warn_extra: +		return {"-Wextra"};  	case ctor::cxx_opt::warnings_as_errors:  		return {"-Werror"};  	case ctor::cxx_opt::generate_dep_tree: @@ -358,6 +719,12 @@ std::vector<std::string> c_option(ctor::c_opt opt, const std::string& arg,  		return {"-g"};  	case ctor::c_opt::warn_all:  		return {"-Wall"}; +	case ctor::c_opt::warn_conversion: +		return {"-Wconversion"}; +	case ctor::c_opt::warn_shadow: +		return {"-Wshadow"}; +	case ctor::c_opt::warn_extra: +		return {"-Wextra"};  	case ctor::c_opt::warnings_as_errors:  		return {"-Werror"};  	case ctor::c_opt::generate_dep_tree: @@ -466,6 +833,8 @@ std::string get_arch(ctor::output_system system)  	case ctor::toolchain::clang:  	case ctor::toolchain::gcc:  		return gcc::get_arch(system); +	case ctor::toolchain::msvc: +		return msvc::get_arch(system);  	case ctor::toolchain::any:  	case ctor::toolchain::none:  		break; @@ -481,6 +850,8 @@ ctor::arch get_arch(ctor::output_system system, const std::string& str)  	case ctor::toolchain::clang:  	case ctor::toolchain::gcc:  		return gcc::get_arch(str); +	case ctor::toolchain::msvc: +		return msvc::get_arch(str);  	case ctor::toolchain::any:  	case ctor::toolchain::none:  		break; @@ -498,6 +869,8 @@ std::vector<std::string> c_option(ctor::toolchain toolchain,  	case ctor::toolchain::gcc:  	case ctor::toolchain::clang:  		return gcc::c_option(opt, arg, arg2); +	case ctor::toolchain::msvc: +		return msvc::c_option(opt, arg, arg2);  	case ctor::toolchain::any:  		{  			std::ostringstream ss; @@ -531,6 +904,8 @@ std::vector<std::string> cxx_option(ctor::toolchain toolchain,  	case ctor::toolchain::gcc:  	case ctor::toolchain::clang:  		return gcc::cxx_option(opt, arg, arg2); +	case ctor::toolchain::msvc: +		return msvc::cxx_option(opt, arg, arg2);  	case ctor::toolchain::any:  		{  			std::ostringstream ss; @@ -564,6 +939,8 @@ std::vector<std::string> ld_option(ctor::toolchain toolchain,  	case ctor::toolchain::gcc:  	case ctor::toolchain::clang:  		return gcc::ld_option(opt, arg, arg2); +	case ctor::toolchain::msvc: +		return msvc::ld_option(opt, arg, arg2);  	case ctor::toolchain::any:  		{  			std::ostringstream ss; @@ -597,6 +974,8 @@ std::vector<std::string> ar_option(ctor::toolchain toolchain,  	case ctor::toolchain::gcc:  	case ctor::toolchain::clang:  		return gcc::ar_option(opt, arg, arg2); +	case ctor::toolchain::msvc: +		return msvc::ar_option(opt, arg, arg2);  	case ctor::toolchain::any:  		{  			std::ostringstream ss; @@ -630,6 +1009,8 @@ std::vector<std::string> asm_option(ctor::toolchain toolchain,  	case ctor::toolchain::gcc:  	case ctor::toolchain::clang:  		return gcc::asm_option(opt, arg, arg2); +	case ctor::toolchain::msvc: +		return msvc::asm_option(opt, arg, arg2);  	case ctor::toolchain::any:  		{  			std::ostringstream ss; @@ -661,6 +1042,8 @@ ctor::c_flag c_option(const std::string& flag, ctor::toolchain toolchain)  	case ctor::toolchain::gcc:  	case ctor::toolchain::clang:  		return gcc::c_option(flag); +	case ctor::toolchain::msvc: +		return msvc::c_option(flag);  	case ctor::toolchain::any:  	case ctor::toolchain::none:  		break; @@ -676,6 +1059,8 @@ ctor::cxx_flag cxx_option(const std::string& flag, ctor::toolchain toolchain)  	case ctor::toolchain::gcc:  	case ctor::toolchain::clang:  		return gcc::cxx_option(flag); +	case ctor::toolchain::msvc: +		return msvc::cxx_option(flag);  	case ctor::toolchain::any:  	case ctor::toolchain::none:  		break; @@ -691,6 +1076,8 @@ ctor::ld_flag ld_option(const std::string& flag, ctor::toolchain toolchain)  	case ctor::toolchain::gcc:  	case ctor::toolchain::clang:  		return gcc::ld_option(flag); +	case ctor::toolchain::msvc: +		return msvc::ld_option(flag);  	case ctor::toolchain::any:  	case ctor::toolchain::none:  		break; @@ -706,6 +1093,8 @@ ctor::ar_flag ar_option(const std::string& flag, ctor::toolchain toolchain)  	case ctor::toolchain::gcc:  	case ctor::toolchain::clang:  		return gcc::ar_option(flag); +	case ctor::toolchain::msvc: +		return msvc::ar_option(flag);  	case ctor::toolchain::any:  	case ctor::toolchain::none:  		break; @@ -720,6 +1109,7 @@ ctor::asm_flag asm_option(const std::string& flag, ctor::toolchain toolchain)  	{  	case ctor::toolchain::gcc:  	case ctor::toolchain::clang: +	case ctor::toolchain::msvc:  	case ctor::toolchain::any:  	case ctor::toolchain::none:  		break; @@ -803,10 +1193,11 @@ ctor::toolchain guess_toolchain(const std::string& opt)  		return ctor::toolchain::gcc;  	} -	//if(opt[0] == '/') -	//{ -	//	return ctor::toolchain::msvc; -	//} +	if(opt[0] == '/') +	{ +		return ctor::toolchain::msvc; +	} +  	return ctor::toolchain::any;  }  } @@ -877,8 +1268,8 @@ ctor::target_type target_type_from_extension(ctor::toolchain toolchain,  		}  	} -	if(toolchain == ctor::toolchain::any// || -	   //toolchain == ctor::toolchain::msvc || +	if(toolchain == ctor::toolchain::any || +	   toolchain == ctor::toolchain::msvc// ||  	   //toolchain == ctor::toolchain::mingw ||  		)  	{ diff --git a/src/util.cc b/src/util.cc index dbd4c3c..f13a4a4 100644 --- a/src/util.cc +++ b/src/util.cc @@ -7,10 +7,17 @@  #include <fstream>  #include <algorithm> +namespace { +char to_lower_c(char ch) +{ +	return static_cast<char>(::tolower(ch)); +} +} +  std::string to_lower(const std::string& str)  {  	std::string out{str}; -	std::transform(out.begin(), out.end(), out.begin(), ::tolower); +	std::transform(out.begin(), out.end(), out.begin(), to_lower_c);  	return out;  } @@ -19,13 +26,18 @@ std::string readFile(const std::string& fileName)  	std::ifstream ifs(fileName.c_str(),  	                  std::ios::in | std::ios::binary | std::ios::ate); -	std::ifstream::pos_type fileSize = ifs.tellg(); +	auto tell = ifs.tellg(); +	if(tell < 0) +	{ +		return {}; +	} +	auto fileSize = static_cast<std::size_t>(tell);  	ifs.seekg(0, std::ios::beg); -	std::vector<char> bytes(static_cast<std::size_t>(fileSize)); -	ifs.read(bytes.data(), fileSize); +	std::vector<char> bytes(fileSize); +	ifs.read(bytes.data(), static_cast<long>(bytes.size())); -	return {bytes.data(), static_cast<std::size_t>(fileSize)}; +	return { bytes.data(), bytes.size() };  }  ctor::language languageFromExtension(const std::filesystem::path& file) @@ -169,15 +181,36 @@ std::string locate(const std::string& prog,  		}  	} +	if(std::filesystem::exists(program + ".exe")) +	{ +		if(check_executable(program + ".exe")) +		{ +			return program + ".exe"; +		} +	} +  	for(const auto& path_str : paths)  	{  		std::filesystem::path path(path_str); -		auto prog_path = path / program; -		if(std::filesystem::exists(prog_path))  		{ -			if(check_executable(prog_path)) +			auto prog_path = path / program; +			if(std::filesystem::exists(prog_path)) +			{ +				if(check_executable(prog_path)) +				{ +					return prog_path.string(); +				} +			} +		} + +		{ +			auto prog_path = path / (program + ".exe"); +			if(std::filesystem::exists(prog_path))  			{ -				return prog_path.string(); +				if(check_executable(prog_path)) +				{ +					return prog_path.string(); +				}  			}  		}  	} diff --git a/test/ctor.cc b/test/ctor.cc index 1951a30..6d97649 100644 --- a/test/ctor.cc +++ b/test/ctor.cc @@ -24,11 +24,15 @@ ctor::build_configurations ctorTestConfigs(const ctor::settings& settings)  				.cxxflags = {  					"-std=c++20", "-O3", "-Wall", "-Werror",  					"-I../src", "-Iuunit", +					"-Ijson/include",  					"-DOUTPUT=\"deps\"", +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/EHsc"}, +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/D_CRT_SECURE_NO_WARNINGS"},  				},  			},  		},  		{ +			.name = "testprog",  			.type = ctor::target_type::unit_test,  			.system = ctor::output_system::build,  			.target = "testprog", @@ -37,7 +41,9 @@ ctor::build_configurations ctorTestConfigs(const ctor::settings& settings)  			},  			.flags = {  				.cxxflags = { -					"-std=c++20", "-O3", "-Wall", "-Werror", +					"-std=c++20", "-O3", "-Wall",// "-Werror", +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/EHsc"}, +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/D_CRT_SECURE_NO_WARNINGS"},  				},  			},  		}, @@ -54,9 +60,11 @@ ctor::build_configurations ctorTestConfigs(const ctor::settings& settings)  			.depends = { "testprog", },  			.flags = {  				.cxxflags = { -					"-std=c++20", "-O3", "-Wall", "-Werror", +					"-std=c++20", "-O3", "-Wall",// "-Werror",  					"-I../src", "-Iuunit",  					"-DOUTPUT=\"execute\"", +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/EHsc"}, +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/D_CRT_SECURE_NO_WARNINGS"},  				},  				.ldflags = { "-pthread" },  			}, @@ -69,12 +77,14 @@ ctor::build_configurations ctorTestConfigs(const ctor::settings& settings)  				"tasks_test.cc",  				"testmain.cc",  			}, -			.depends = { "libctor_nomain.a" }, +			.depends = { "libctor_nomain.lib" },  			.flags = {  				.cxxflags = { -					"-std=c++20", "-O3", "-Wall", "-Werror", +					"-std=c++20", "-O3", "-Wall",// "-Werror",  					"-I../src", "-Iuunit",  					"-DOUTPUT=\"tasks\"", +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/EHsc"}, +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/D_CRT_SECURE_NO_WARNINGS"},  				},  				.ldflags = { "-pthread" },  			}, @@ -87,12 +97,14 @@ ctor::build_configurations ctorTestConfigs(const ctor::settings& settings)  				"source_type_test.cc",  				"testmain.cc",  			}, -			.depends = { "libctor_nomain.a" }, +			.depends = { "libctor_nomain.lib" },  			.flags = {  				.cxxflags = { -					"-std=c++20", "-O3", "-Wall", "-Werror", +					"-std=c++20", "-O3", "-Wall",// "-Werror",  					"-I../src", "-Iuunit",  					"-DOUTPUT=\"source_type\"", +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/EHsc"}, +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/D_CRT_SECURE_NO_WARNINGS"},  				},  				.ldflags = { "-pthread" },  			}, @@ -110,16 +122,18 @@ ctor::build_configurations ctorTestConfigs(const ctor::settings& settings)  			//.depends = { "libctor_nomain.a" },  			.flags = {  				.cxxflags = { -					"-std=c++20", "-O3", "-Wall", "-Werror", +					"-std=c++20", "-O3", "-Wall",// "-Werror",  					"-I../src", "-Iuunit",  					"-DOUTPUT=\"tools\"", +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/EHsc"}, +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/D_CRT_SECURE_NO_WARNINGS"},  				},  			},  		},  		{  			.type = ctor::target_type::unit_test_library,  			.system = ctor::output_system::build, -			.target = "libctor_nomain.a", +			.target = "libctor_nomain.lib",  			.sources = {  				"../src/build.cc",  				"../src/configure.cc", @@ -136,11 +150,33 @@ ctor::build_configurations ctorTestConfigs(const ctor::settings& settings)  				"../src/tools.cc",  				"../src/util.cc",  				"../src/externals_manual.cc", +				{ctor::toolchain::msvc, "../getopt-for-windows/getopt.c"},  			},  			.flags = { +				.cflags = { +					"-O3", +//					"-g", +//					"-Wall", +//					"-Wconversion", +//					"-Wextra", +					//"-Werror", +					"-I../src", +					{ctor::toolchain::msvc, ctor::c_opt::custom, "/I../getopt-for-windows"}, +					{ctor::toolchain::msvc, ctor::c_opt::custom, "/D_X86_"}, +					{ctor::toolchain::msvc, ctor::c_opt::custom, "/EHsc"}, +					{ctor::toolchain::msvc, ctor::c_opt::custom, "/external:W0"}, +					{ctor::toolchain::msvc, ctor::c_opt::custom, "/D_CRT_SECURE_NO_WARNINGS"}, +				},  				.cxxflags = { -					"-std=c++20", "-O3", "-Wall", "-Werror", +					"-std=c++20", "-O3", "-Wall",// "-Werror",  					"-I../src", +					"-Ijson/include", +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/Igetopt-for-windows"}, +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/D_X86_"}, +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/EHsc"}, +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/external:W0"}, +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/D_CRT_SECURE_NO_WARNINGS"}, +					{ctor::toolchain::msvc, ctor::cxx_opt::custom, "/Dstrdup=_strdup"},  				},  				.ldflags = { "-pthread" },  			}, diff --git a/test/deps_test.cc b/test/deps_test.cc index 762b0e5..fdaa691 100644 --- a/test/deps_test.cc +++ b/test/deps_test.cc @@ -42,43 +42,43 @@ public:  		{  			auto res = readDeps(trivial.string(), ctor::toolchain::gcc); -			uASSERT_EQUAL(1u, res.size()); -			uASSERT_EQUAL("x.cc"s, res[0]); +			assert_equal(1u, res.size(), __FILE__, __LINE__); +			assert_equal("x.cc"s, res[0], __FILE__, __LINE__);  		}  		{  			auto res = readDeps(no_newline.string(), ctor::toolchain::gcc); -			uASSERT_EQUAL(1u, res.size()); -			uASSERT_EQUAL("x.cc"s, res[0]); +			assert_equal(1u, res.size(), __FILE__, __LINE__); +			assert_equal("x.cc"s, res[0], __FILE__, __LINE__);  		}  		{  			auto res = readDeps(no_deps.string(), ctor::toolchain::gcc); -			uASSERT_EQUAL(0u, res.size()); +			assert_equal(0u, res.size(), __FILE__, __LINE__);  		}  		{  			auto res = readDeps(spaces.string(), ctor::toolchain::gcc); -			uASSERT_EQUAL(2u, res.size()); -			uASSERT_EQUAL("x y.cc"s, res[0]); -			uASSERT_EQUAL("x y.h"s, res[1]); +			assert_equal(2u, res.size(), __FILE__, __LINE__); +			assert_equal("x y.cc"s, res[0], __FILE__, __LINE__); +			assert_equal("x y.h"s, res[1], __FILE__, __LINE__);  		}  		{  			auto res = readDeps(multiline.string(), ctor::toolchain::gcc); -			uASSERT_EQUAL(12u, res.size()); -			uASSERT_EQUAL("src/configure.cc"s, res[0]); -			uASSERT_EQUAL("src/configure.h"s, res[1]); -			uASSERT_EQUAL("src/getoptpp/getoptpp.hpp"s, res[2]); -			uASSERT_EQUAL("src/execute.h"s, res[3]); -			uASSERT_EQUAL("src/ctor.h"s, res[4]); -			uASSERT_EQUAL("src/tasks.h"s, res[5]); -			uASSERT_EQUAL("src/task.h"s, res[6]); -			uASSERT_EQUAL("src/rebuild.h"s, res[7]); -			uASSERT_EQUAL("src/externals.h"s, res[8]); -			uASSERT_EQUAL("src/externals_manual.h"s, res[9]); -			uASSERT_EQUAL("src/tools.h"s, res[10]); -			uASSERT_EQUAL("src/util.h"s, res[11]); +			assert_equal(12u, res.size(), __FILE__, __LINE__); +			assert_equal("src/configure.cc"s, res[0], __FILE__, __LINE__); +			assert_equal("src/configure.h"s, res[1], __FILE__, __LINE__); +			assert_equal("src/getoptpp/getoptpp.hpp"s, res[2], __FILE__, __LINE__); +			assert_equal("src/execute.h"s, res[3], __FILE__, __LINE__); +			assert_equal("src/ctor.h"s, res[4], __FILE__, __LINE__); +			assert_equal("src/tasks.h"s, res[5], __FILE__, __LINE__); +			assert_equal("src/task.h"s, res[6], __FILE__, __LINE__); +			assert_equal("src/rebuild.h"s, res[7], __FILE__, __LINE__); +			assert_equal("src/externals.h"s, res[8], __FILE__, __LINE__); +			assert_equal("src/externals_manual.h"s, res[9], __FILE__, __LINE__); +			assert_equal("src/tools.h"s, res[10], __FILE__, __LINE__); +			assert_equal("src/util.h"s, res[11], __FILE__, __LINE__);  		}  		{ diff --git a/test/execute_test.cc b/test/execute_test.cc index 4c686bf..027ef3b 100644 --- a/test/execute_test.cc +++ b/test/execute_test.cc @@ -30,11 +30,11 @@ public:  		uASSERT(!cmd.empty());  		auto value = execute(s, cmd, {"retval", "0"}, {}, false); -		uASSERT_EQUAL(0, value); +		assert_equal(0, value, __FILE__, __LINE__);  		value = execute(s, cmd, {"retval", "1"}, {}, false); -		uASSERT_EQUAL(1, value); +		assert_equal(1, value, __FILE__, __LINE__);  		value = execute(s, "no-such-binary", {}, {}, false); -		uASSERT_EQUAL(1, value); +		assert_equal(1, value, __FILE__, __LINE__);  	}  	void env() @@ -59,7 +59,7 @@ public:  		env["LANG"] = "foo";  		auto value = execute(s, cmd, {"envdump", tmp.get()}, env, false); -		uASSERT_EQUAL(0, value); +		assert_equal(0, value, __FILE__, __LINE__);  		std::vector<std::string> vars;  		{ diff --git a/test/source_type_test.cc b/test/source_type_test.cc index 288f1e5..ced8e3a 100644 --- a/test/source_type_test.cc +++ b/test/source_type_test.cc @@ -53,22 +53,22 @@ public:  	{  		{ // c++  			TestableTaskCC task("hello.cc"); -			uASSERT_EQUAL(ctor::language::cpp, task.language()); +			assert_equal(ctor::language::cpp, task.language(), __FILE__, __LINE__);  		}  		{ // c  			TestableTaskCC task("hello.c"); -			uASSERT_EQUAL(ctor::language::c, task.language()); +			assert_equal(ctor::language::c, task.language(), __FILE__, __LINE__);  		}  		{ // asm  			TestableTaskCC task("hello.s"); -			uASSERT_EQUAL(ctor::language::assembler, task.language()); +			assert_equal(ctor::language::assembler, task.language(), __FILE__, __LINE__);  		}  		{ // custom/explicit language  			TestableTaskCC task( {"hello.foo", ctor::language::assembler} ); -			uASSERT_EQUAL(ctor::language::assembler, task.language()); +			assert_equal(ctor::language::assembler, task.language(), __FILE__, __LINE__);  		}  		// Note: Failure state will result in exit(1) so cannot be tested diff --git a/test/suite/test.sh b/test/suite/test.sh index c112351..23740a9 100755 --- a/test/suite/test.sh +++ b/test/suite/test.sh @@ -1,4 +1,6 @@  #!/bin/bash +#set -x +  : ${CXX:=g++}  : ${CTORDIR:=../../build}  : ${BUILDDIR:=build} diff --git a/test/tasks_test.cc b/test/tasks_test.cc index 3de6982..c6909c0 100644 --- a/test/tasks_test.cc +++ b/test/tasks_test.cc @@ -93,17 +93,17 @@ public:  		using namespace std::string_literals;  		ctor::settings settings{};  		const auto& targets = getTargets(settings); -		uASSERT_EQUAL(4u, targets.size()); +		assert_equal(4u, targets.size(), __FILE__, __LINE__); -		uASSERT_EQUAL("target1"s, targets[0].config.target); -		uASSERT_EQUAL("target2"s, targets[1].config.target); -		uASSERT_EQUAL("target3"s, targets[2].config.target); -		uASSERT_EQUAL("target4"s, targets[3].config.target); +		assert_equal("target1"s, targets[0].config.target, __FILE__, __LINE__); +		assert_equal("target2"s, targets[1].config.target, __FILE__, __LINE__); +		assert_equal("target3"s, targets[2].config.target, __FILE__, __LINE__); +		assert_equal("target4"s, targets[3].config.target, __FILE__, __LINE__); -		uASSERT_EQUAL("test"s, targets[0].path); -		uASSERT_EQUAL("test"s, targets[1].path); -		uASSERT_EQUAL("test"s, targets[2].path); -		uASSERT_EQUAL("test"s, targets[3].path); +		assert_equal("test"s, targets[0].path, __FILE__, __LINE__); +		assert_equal("test"s, targets[1].path, __FILE__, __LINE__); +		assert_equal("test"s, targets[2].path, __FILE__, __LINE__); +		assert_equal("test"s, targets[3].path, __FILE__, __LINE__);  	}  	void getTasks_test() @@ -112,26 +112,26 @@ public:  		ctor::settings settings{ .builddir = "foo" };  		{  			auto tasks = getTasks(settings); -			uASSERT_EQUAL(6u, tasks.size()); +			assert_equal(6u, tasks.size(), __FILE__, __LINE__);  			// Note: count() is used here because the order doesn't matter -			uASSERT_EQUAL(1u, count(tasks, "target1"s)); -			uASSERT_EQUAL(1u, count(tasks, "target2"s)); -			uASSERT_EQUAL(1u, count(tasks, "target3"s)); -			uASSERT_EQUAL(1u, count(tasks, "target4"s)); -			uASSERT_EQUAL(1u, count(tasks, "test/target1-foo_cc.o"s)); -			uASSERT_EQUAL(1u, count(tasks, "test/target1-bar_c.o"s)); +			assert_equal(1u, count(tasks, "target1"s), __FILE__, __LINE__); +			assert_equal(1u, count(tasks, "target2"s), __FILE__, __LINE__); +			assert_equal(1u, count(tasks, "target3"s), __FILE__, __LINE__); +			assert_equal(1u, count(tasks, "target4"s), __FILE__, __LINE__); +			assert_equal(1u, count(tasks, "test/target1-foo_cc.o"s), __FILE__, __LINE__); +			assert_equal(1u, count(tasks, "test/target1-bar_c.o"s), __FILE__, __LINE__);  		}  		{  			auto tasks = getTasks(settings, {"target1", "target3"}); -			uASSERT_EQUAL(4u, tasks.size()); -			uASSERT_EQUAL(1u, count(tasks, "target1"s)); -			uASSERT_EQUAL(1u, count(tasks, "target3"s)); -			uASSERT_EQUAL(1u, count(tasks, "test/target1-foo_cc.o"s)); -			uASSERT_EQUAL(1u, count(tasks, "test/target1-bar_c.o"s)); +			assert_equal(4u, tasks.size(), __FILE__, __LINE__); +			assert_equal(1u, count(tasks, "target1"s), __FILE__, __LINE__); +			assert_equal(1u, count(tasks, "target3"s), __FILE__, __LINE__); +			assert_equal(1u, count(tasks, "test/target1-foo_cc.o"s), __FILE__, __LINE__); +			assert_equal(1u, count(tasks, "test/target1-bar_c.o"s), __FILE__, __LINE__);  		}  		{  			auto tasks = getTasks(settings, {"no-such-target"}); -			uASSERT_EQUAL(0u, tasks.size()); +			assert_equal(0u, tasks.size(), __FILE__, __LINE__);  		}  	} @@ -146,10 +146,10 @@ public:  			for(auto& task : dirtyTasks)  			{ -				uASSERT_EQUAL(0, task->registerDepTasks(allTasks)); +				assert_equal(0, task->registerDepTasks(allTasks), __FILE__, __LINE__);  			} -			uASSERT_EQUAL(nullptr, getNextTask(allTasks, dirtyTasks)); +			assert_equal(nullptr, getNextTask(allTasks, dirtyTasks), __FILE__, __LINE__);  		}  		{ // Zero (One task, no dirty) @@ -162,10 +162,10 @@ public:  			for(auto& task : dirtyTasks)  			{ -				uASSERT_EQUAL(0, task->registerDepTasks(allTasks)); +				assert_equal(0, task->registerDepTasks(allTasks), __FILE__, __LINE__);  			} -			uASSERT_EQUAL(nullptr, getNextTask(allTasks, dirtyTasks)); +			assert_equal(nullptr, getNextTask(allTasks, dirtyTasks), __FILE__, __LINE__);  		}  		{ // One (One task, one dirty) @@ -179,11 +179,11 @@ public:  			for(auto& task : dirtyTasks)  			{ -				uASSERT_EQUAL(0, task->registerDepTasks(allTasks)); +				assert_equal(0, task->registerDepTasks(allTasks), __FILE__, __LINE__);  			} -			uASSERT_EQUAL(task1, getNextTask(allTasks, dirtyTasks)); -			uASSERT_EQUAL(0u, dirtyTasks.size()); +			assert_equal(task1, getNextTask(allTasks, dirtyTasks), __FILE__, __LINE__); +			assert_equal(0u, dirtyTasks.size(), __FILE__, __LINE__);  		}  		{ // One (Two tasks, one dirty) @@ -199,11 +199,11 @@ public:  			for(auto& task : dirtyTasks)  			{ -				uASSERT_EQUAL(0, task->registerDepTasks(allTasks)); +				assert_equal(0, task->registerDepTasks(allTasks), __FILE__, __LINE__);  			} -			uASSERT_EQUAL(task2, getNextTask(allTasks, dirtyTasks)); -			uASSERT_EQUAL(0u, dirtyTasks.size()); +			assert_equal(task2, getNextTask(allTasks, dirtyTasks), __FILE__, __LINE__); +			assert_equal(0u, dirtyTasks.size(), __FILE__, __LINE__);  		}  		{ // One (Two tasks, one dirty which depends on the other) @@ -221,11 +221,11 @@ public:  			for(auto& task : dirtyTasks)  			{ -				uASSERT_EQUAL(0, task->registerDepTasks(allTasks)); +				assert_equal(0, task->registerDepTasks(allTasks), __FILE__, __LINE__);  			} -			uASSERT_EQUAL(task2, getNextTask(allTasks, dirtyTasks)); -			uASSERT_EQUAL(0u, dirtyTasks.size()); +			assert_equal(task2, getNextTask(allTasks, dirtyTasks), __FILE__, __LINE__); +			assert_equal(0u, dirtyTasks.size(), __FILE__, __LINE__);  		}  		{ // One (Two tasks, Both dirty, one depends on the other) @@ -244,11 +244,11 @@ public:  			for(auto& task : dirtyTasks)  			{ -				uASSERT_EQUAL(0, task->registerDepTasks(allTasks)); +				assert_equal(0, task->registerDepTasks(allTasks), __FILE__, __LINE__);  			} -			uASSERT_EQUAL(task1, getNextTask(allTasks, dirtyTasks)); -			uASSERT_EQUAL(1u, dirtyTasks.size()); +			assert_equal(task1, getNextTask(allTasks, dirtyTasks), __FILE__, __LINE__); +			assert_equal(1u, dirtyTasks.size(), __FILE__, __LINE__);  		}  	} diff --git a/test/testprog.cc b/test/testprog.cc index dbfb665..58a31ac 100644 --- a/test/testprog.cc +++ b/test/testprog.cc @@ -2,7 +2,13 @@  #include <fstream>  #include <string> -extern const char **environ; // see 'man environ' +#if defined(_WIN32) +#define WINDOWS_LEAN_AND_MEAN +#include <windows.h> +#undef max +#else +extern char **environ; // see 'man environ' +#endif  int main(int argc, const char* argv[])  { @@ -19,11 +25,41 @@ int main(int argc, const char* argv[])  		{  			return 0;  		} +  		std::ofstream ostrm(argv[2], std::ios::binary); +		if(ostrm.bad()) +		{ +			std::cout << "Error: Could not write to " << argv[2] << "\n"; +		} +#if defined(_WIN32) +		auto env_strings = GetEnvironmentStrings(); +		const char* ptr = env_strings; +		std::string env; +		while(true) +		{ +			if(*ptr == '\0') +			{ +				if(env.empty()) +				{ +					// no more +					break; +				} +				ostrm << env << "\n"; +				env.clear(); +				++ptr; +				continue; +			} + +			env += *ptr; +			++ptr; +		} +		FreeEnvironmentStrings(env_strings); +#else  		for(auto current = environ; *current; ++current)  		{  			ostrm << (*current) << "\n";  		} +#endif  	}  	if(cmd == "retval") diff --git a/test/tmpfile.h b/test/tmpfile.h index 5d114d0..a5d4043 100644 --- a/test/tmpfile.h +++ b/test/tmpfile.h @@ -4,7 +4,7 @@  #pragma once  #include <cstdlib> -#include <unistd.h> +#include <cstring>  #ifdef _WIN32  #define WIN32_LEAN_AND_MEAN @@ -12,6 +12,9 @@  #include <sys/types.h>  #include <sys/stat.h>  #include <fcntl.h> +#include <io.h> +#else +#include <unistd.h>  #endif  struct tmp_file @@ -19,23 +22,35 @@ struct tmp_file  	tmp_file(const std::string& data = {})  	{  		int fd; +		auto tmp_dir = std::filesystem::temp_directory_path(); +		auto tmp_file_template = tmp_dir / "ctor_tmp_file-XXXXXX"; +		filename = tmp_file_template.string(); +		auto buf = new char[filename.size() + 2]; +		memcpy(buf, filename.data(), filename.size() + 1);  #ifdef _WIN32 -		char templ[] = "ctor_tmp_file-XXXXXX"; // buffer for filename -		_mktemp_s(templ, sizeof(templ)); -		fd = open(templ, O_CREAT | O_RDWR); +		_mktemp_s(buf, filename.size() + 2); +		filename = buf; +		fd = _open(filename.data(), O_CREAT | O_RDWR, _S_IWRITE); +		auto sz = _write(fd, data.data(), data.size()); +		(void)sz; +		_close(fd);  #else -		char templ[] = "/tmp/ctor_tmp_file-XXXXXX"; // buffer for filename -		fd = mkstemp(templ); -#endif -		filename = templ; +		fd = mkstemp(buf); +		filename = buf;  		auto sz = write(fd, data.data(), data.size());  		(void)sz;  		close(fd); +#endif +		delete[] buf;  	}  	~tmp_file()  	{ +#ifdef _WIN32 +		_unlink(filename.data()); +#else  		unlink(filename.data()); +#endif  	}  	const std::string& get() const diff --git a/test/tools_test.cc b/test/tools_test.cc index a428ea1..91da470 100644 --- a/test/tools_test.cc +++ b/test/tools_test.cc @@ -22,6 +22,9 @@ std::ostream& operator<<(std::ostream& stream, const ctor::toolchain& toolchain)  	case ctor::toolchain::clang:  		stream << "ctor::toolchain::clang";  		break; +	case ctor::toolchain::msvc: +		stream << "ctor::toolchain::msvc"; +		break;  	}  	return stream;  } @@ -125,7 +128,7 @@ const ctor::configuration& ctor::get_configuration()  	return cfg;  } -const std::string& ctor::configuration::get(const std::string& key, const std::string& defval) const +std::string ctor::configuration::get(const std::string& key, [[maybe_unused]]const std::string& default_value) const  {  	if(key == ctor::cfg::host_cxx)  	{ @@ -175,24 +178,24 @@ public:  		//  		// gcc  		// -		uASSERT_EQUAL(ctor::toolchain::gcc, getToolChain("/usr/bin/gcc")); -		uASSERT_EQUAL(ctor::toolchain::gcc, getToolChain("/usr/bin/gcc-10")); -		uASSERT_EQUAL(ctor::toolchain::gcc, getToolChain("/usr/bin/x86_64-pc-linux-gnu-g++-9.3.0")); +		assert_equal(ctor::toolchain::gcc, getToolChain("/usr/bin/gcc"), __FILE__, __LINE__); +		assert_equal(ctor::toolchain::gcc, getToolChain("/usr/bin/gcc-10"), __FILE__, __LINE__); +		assert_equal(ctor::toolchain::gcc, getToolChain("/usr/bin/x86_64-pc-linux-gnu-g++-9.3.0"), __FILE__, __LINE__); -		uASSERT_EQUAL(ctor::toolchain::gcc, getToolChain("/usr/bin/g++")); -		uASSERT_EQUAL(ctor::toolchain::gcc, getToolChain("/usr/bin/g++-10")); -		uASSERT_EQUAL(ctor::toolchain::gcc, getToolChain("/usr/bin/x86_64-pc-linux-gnu-g++-9.3.0")); +		assert_equal(ctor::toolchain::gcc, getToolChain("/usr/bin/g++"), __FILE__, __LINE__); +		assert_equal(ctor::toolchain::gcc, getToolChain("/usr/bin/g++-10"), __FILE__, __LINE__); +		assert_equal(ctor::toolchain::gcc, getToolChain("/usr/bin/x86_64-pc-linux-gnu-g++-9.3.0"), __FILE__, __LINE__);  		//  		// clang  		// -		uASSERT_EQUAL(ctor::toolchain::clang, getToolChain("/usr/bin/clang")); -		uASSERT_EQUAL(ctor::toolchain::clang, getToolChain("/usr/bin/clang-16")); -		uASSERT_EQUAL(ctor::toolchain::clang, getToolChain("/usr/lib/llvm/16/bin/i686-pc-linux-gnu-clang-16")); +		assert_equal(ctor::toolchain::clang, getToolChain("/usr/bin/clang"), __FILE__, __LINE__); +		assert_equal(ctor::toolchain::clang, getToolChain("/usr/bin/clang-16"), __FILE__, __LINE__); +		assert_equal(ctor::toolchain::clang, getToolChain("/usr/lib/llvm/16/bin/i686-pc-linux-gnu-clang-16"), __FILE__, __LINE__); -		uASSERT_EQUAL(ctor::toolchain::clang, getToolChain("/usr/bin/clang++")); -		uASSERT_EQUAL(ctor::toolchain::clang, getToolChain("/usr/bin/clang++-16")); -		uASSERT_EQUAL(ctor::toolchain::clang, getToolChain("/usr/lib/llvm/16/bin/i686-pc-linux-gnu-clang++-16")); +		assert_equal(ctor::toolchain::clang, getToolChain("/usr/bin/clang++"), __FILE__, __LINE__); +		assert_equal(ctor::toolchain::clang, getToolChain("/usr/bin/clang++-16"), __FILE__, __LINE__); +		assert_equal(ctor::toolchain::clang, getToolChain("/usr/lib/llvm/16/bin/i686-pc-linux-gnu-clang++-16"), __FILE__, __LINE__);  	} @@ -206,153 +209,153 @@ public:  		//  		exp = { "-o", "foo" };  		act = c_option(ctor::toolchain::gcc, ctor::c_opt::output, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-g" };  		act = c_option(ctor::toolchain::gcc, ctor::c_opt::debug); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Wall" };  		act = c_option(ctor::toolchain::gcc, ctor::c_opt::warn_all); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Werror" };  		act = c_option(ctor::toolchain::gcc, ctor::c_opt::warnings_as_errors); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-MMD" };  		act = c_option(ctor::toolchain::gcc, ctor::c_opt::generate_dep_tree); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-c" };  		act = c_option(ctor::toolchain::gcc, ctor::c_opt::no_link); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Ifoo" };  		act = c_option(ctor::toolchain::gcc, ctor::c_opt::include_path, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-std=foo" };  		act = c_option(ctor::toolchain::gcc, ctor::c_opt::c_std, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Ofoo" };  		act = c_option(ctor::toolchain::gcc, ctor::c_opt::optimization, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-fPIC" };  		act = c_option(ctor::toolchain::gcc, ctor::c_opt::position_independent_code); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-fPIE" };  		act = c_option(ctor::toolchain::gcc, ctor::c_opt::position_independent_executable); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-foo" };  		act = c_option(ctor::toolchain::gcc, ctor::c_opt::custom, "-foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		//  		// clang  		//  		exp = { "-o", "foo" };  		act = c_option(ctor::toolchain::clang, ctor::c_opt::output, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-g" };  		act = c_option(ctor::toolchain::clang, ctor::c_opt::debug); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Wall" };  		act = c_option(ctor::toolchain::clang, ctor::c_opt::warn_all); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Werror" };  		act = c_option(ctor::toolchain::clang, ctor::c_opt::warnings_as_errors); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-MMD" };  		act = c_option(ctor::toolchain::clang, ctor::c_opt::generate_dep_tree); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-c" };  		act = c_option(ctor::toolchain::clang, ctor::c_opt::no_link); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Ifoo" };  		act = c_option(ctor::toolchain::clang, ctor::c_opt::include_path, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-std=foo" };  		act = c_option(ctor::toolchain::clang, ctor::c_opt::c_std, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Ofoo" };  		act = c_option(ctor::toolchain::clang, ctor::c_opt::optimization, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-fPIC" };  		act = c_option(ctor::toolchain::clang, ctor::c_opt::position_independent_code); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-fPIE" };  		act = c_option(ctor::toolchain::clang, ctor::c_opt::position_independent_executable); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-foo" };  		act = c_option(ctor::toolchain::clang, ctor::c_opt::custom, "-foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		//  		// any  		//  		exp = { "{ctor::c_opt::output, \"foo\"}" };  		act = c_option(ctor::toolchain::any, ctor::c_opt::output, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::c_opt::debug}" };  		act = c_option(ctor::toolchain::any, ctor::c_opt::debug); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::c_opt::warn_all}" };  		act = c_option(ctor::toolchain::any, ctor::c_opt::warn_all); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::c_opt::warnings_as_errors}" };  		act = c_option(ctor::toolchain::any, ctor::c_opt::warnings_as_errors); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::c_opt::generate_dep_tree}" };  		act = c_option(ctor::toolchain::any, ctor::c_opt::generate_dep_tree); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::c_opt::no_link}" };  		act = c_option(ctor::toolchain::any, ctor::c_opt::no_link); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::c_opt::include_path, \"foo\"}" };  		act = c_option(ctor::toolchain::any, ctor::c_opt::include_path, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::c_opt::c_std, \"foo\"}" };  		act = c_option(ctor::toolchain::any, ctor::c_opt::c_std, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::c_opt::optimization, \"foo\"}" };  		act = c_option(ctor::toolchain::any, ctor::c_opt::optimization, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::c_opt::position_independent_code}" };  		act = c_option(ctor::toolchain::any, ctor::c_opt::position_independent_code); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::c_opt::position_independent_executable}" };  		act = c_option(ctor::toolchain::any, ctor::c_opt::position_independent_executable); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::c_opt::custom, \"-foo\"}" };  		act = c_option(ctor::toolchain::any, ctor::c_opt::custom, "-foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  	}  	void getOption_toolchain_cxx_test() @@ -365,153 +368,153 @@ public:  		//  		exp = { "-o", "foo" };  		act = cxx_option(ctor::toolchain::gcc, ctor::cxx_opt::output, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-g" };  		act = cxx_option(ctor::toolchain::gcc, ctor::cxx_opt::debug); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Wall" };  		act = cxx_option(ctor::toolchain::gcc, ctor::cxx_opt::warn_all); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Werror" };  		act = cxx_option(ctor::toolchain::gcc, ctor::cxx_opt::warnings_as_errors); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-MMD" };  		act = cxx_option(ctor::toolchain::gcc, ctor::cxx_opt::generate_dep_tree); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-c" };  		act = cxx_option(ctor::toolchain::gcc, ctor::cxx_opt::no_link); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Ifoo" };  		act = cxx_option(ctor::toolchain::gcc, ctor::cxx_opt::include_path, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-std=foo" };  		act = cxx_option(ctor::toolchain::gcc, ctor::cxx_opt::cpp_std, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Ofoo" };  		act = cxx_option(ctor::toolchain::gcc, ctor::cxx_opt::optimization, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-fPIC" };  		act = cxx_option(ctor::toolchain::gcc, ctor::cxx_opt::position_independent_code); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-fPIE" };  		act = cxx_option(ctor::toolchain::gcc, ctor::cxx_opt::position_independent_executable); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-foo" };  		act = cxx_option(ctor::toolchain::gcc, ctor::cxx_opt::custom, "-foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		//  		// clang  		//  		exp = { "-o", "foo" };  		act = cxx_option(ctor::toolchain::clang, ctor::cxx_opt::output, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-g" };  		act = cxx_option(ctor::toolchain::clang, ctor::cxx_opt::debug); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Wall" };  		act = cxx_option(ctor::toolchain::clang, ctor::cxx_opt::warn_all); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Werror" };  		act = cxx_option(ctor::toolchain::clang, ctor::cxx_opt::warnings_as_errors); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-MMD" };  		act = cxx_option(ctor::toolchain::clang, ctor::cxx_opt::generate_dep_tree); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-c" };  		act = cxx_option(ctor::toolchain::clang, ctor::cxx_opt::no_link); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Ifoo" };  		act = cxx_option(ctor::toolchain::clang, ctor::cxx_opt::include_path, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-std=foo" };  		act = cxx_option(ctor::toolchain::clang, ctor::cxx_opt::cpp_std, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Ofoo" };  		act = cxx_option(ctor::toolchain::clang, ctor::cxx_opt::optimization, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-fPIC" };  		act = cxx_option(ctor::toolchain::clang, ctor::cxx_opt::position_independent_code); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-fPIE" };  		act = cxx_option(ctor::toolchain::clang, ctor::cxx_opt::position_independent_executable); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-foo" };  		act = cxx_option(ctor::toolchain::clang, ctor::cxx_opt::custom, "-foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		//  		// any  		//  		exp = { "{ctor::cxx_opt::output, \"foo\"}" };  		act = cxx_option(ctor::toolchain::any, ctor::cxx_opt::output, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::cxx_opt::debug}" };  		act = cxx_option(ctor::toolchain::any, ctor::cxx_opt::debug); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::cxx_opt::warn_all}" };  		act = cxx_option(ctor::toolchain::any, ctor::cxx_opt::warn_all); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::cxx_opt::warnings_as_errors}" };  		act = cxx_option(ctor::toolchain::any, ctor::cxx_opt::warnings_as_errors); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::cxx_opt::generate_dep_tree}" };  		act = cxx_option(ctor::toolchain::any, ctor::cxx_opt::generate_dep_tree); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::cxx_opt::no_link}" };  		act = cxx_option(ctor::toolchain::any, ctor::cxx_opt::no_link); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::cxx_opt::include_path, \"foo\"}" };  		act = cxx_option(ctor::toolchain::any, ctor::cxx_opt::include_path, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::cxx_opt::cpp_std, \"foo\"}" };  		act = cxx_option(ctor::toolchain::any, ctor::cxx_opt::cpp_std, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::cxx_opt::optimization, \"foo\"}" };  		act = cxx_option(ctor::toolchain::any, ctor::cxx_opt::optimization, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::cxx_opt::position_independent_code}" };  		act = cxx_option(ctor::toolchain::any, ctor::cxx_opt::position_independent_code); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::cxx_opt::position_independent_executable}" };  		act = cxx_option(ctor::toolchain::any, ctor::cxx_opt::position_independent_executable); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::cxx_opt::custom, \"-foo\"}" };  		act = cxx_option(ctor::toolchain::any, ctor::cxx_opt::custom, "-foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  	}  	void getOption_toolchain_ld_test() @@ -524,153 +527,153 @@ public:  		//  		exp = { "-o", "foo" };  		act = ld_option(ctor::toolchain::gcc, ctor::ld_opt::output, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-s" };  		act = ld_option(ctor::toolchain::gcc, ctor::ld_opt::strip); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Wall" };  		act = ld_option(ctor::toolchain::gcc, ctor::ld_opt::warn_all); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Werror" };  		act = ld_option(ctor::toolchain::gcc, ctor::ld_opt::warnings_as_errors); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Lfoo" };  		act = ld_option(ctor::toolchain::gcc, ctor::ld_opt::library_path, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-lfoo" };  		act = ld_option(ctor::toolchain::gcc, ctor::ld_opt::link, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-std=foo" };  		act = ld_option(ctor::toolchain::gcc, ctor::ld_opt::cpp_std, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-shared" };  		act = ld_option(ctor::toolchain::gcc, ctor::ld_opt::build_shared); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-pthread" };  		act = ld_option(ctor::toolchain::gcc, ctor::ld_opt::threads); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-fPIC" };  		act = ld_option(ctor::toolchain::gcc, ctor::ld_opt::position_independent_code); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-fPIE" };  		act = ld_option(ctor::toolchain::gcc, ctor::ld_opt::position_independent_executable); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-foo" };  		act = ld_option(ctor::toolchain::gcc, ctor::ld_opt::custom, "-foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		//  		// clang  		//  		exp = { "-o", "foo" };  		act = ld_option(ctor::toolchain::clang, ctor::ld_opt::output, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-s" };  		act = ld_option(ctor::toolchain::clang, ctor::ld_opt::strip); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Wall" };  		act = ld_option(ctor::toolchain::clang, ctor::ld_opt::warn_all); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Werror" };  		act = ld_option(ctor::toolchain::clang, ctor::ld_opt::warnings_as_errors); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-Lfoo" };  		act = ld_option(ctor::toolchain::clang, ctor::ld_opt::library_path, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-lfoo" };  		act = ld_option(ctor::toolchain::clang, ctor::ld_opt::link, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-std=foo" };  		act = ld_option(ctor::toolchain::clang, ctor::ld_opt::cpp_std, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-shared" };  		act = ld_option(ctor::toolchain::clang, ctor::ld_opt::build_shared); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-pthread" };  		act = ld_option(ctor::toolchain::clang, ctor::ld_opt::threads); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-fPIC" };  		act = ld_option(ctor::toolchain::clang, ctor::ld_opt::position_independent_code); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-fPIE" };  		act = ld_option(ctor::toolchain::clang, ctor::ld_opt::position_independent_executable); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-foo" };  		act = ld_option(ctor::toolchain::clang, ctor::ld_opt::custom, "-foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		//  		// any  		//  		exp = { "{ctor::ld_opt::output, \"foo\"}" };  		act = ld_option(ctor::toolchain::any, ctor::ld_opt::output, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::ld_opt::strip}" };  		act = ld_option(ctor::toolchain::any, ctor::ld_opt::strip); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::ld_opt::warn_all}" };  		act = ld_option(ctor::toolchain::any, ctor::ld_opt::warn_all); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::ld_opt::warnings_as_errors}" };  		act = ld_option(ctor::toolchain::any, ctor::ld_opt::warnings_as_errors); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::ld_opt::library_path, \"foo\"}" };  		act = ld_option(ctor::toolchain::any, ctor::ld_opt::library_path, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::ld_opt::link, \"foo\"}" };  		act = ld_option(ctor::toolchain::any, ctor::ld_opt::link, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::ld_opt::cpp_std, \"foo\"}" };  		act = ld_option(ctor::toolchain::any, ctor::ld_opt::cpp_std, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::ld_opt::build_shared}" };  		act = ld_option(ctor::toolchain::any, ctor::ld_opt::build_shared); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::ld_opt::threads}" };  		act = ld_option(ctor::toolchain::any, ctor::ld_opt::threads); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::ld_opt::position_independent_code}" };  		act = ld_option(ctor::toolchain::any, ctor::ld_opt::position_independent_code); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::ld_opt::position_independent_executable}" };  		act = ld_option(ctor::toolchain::any, ctor::ld_opt::position_independent_executable); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "{ctor::ld_opt::custom, \"-foo\"}" };  		act = ld_option(ctor::toolchain::any, ctor::ld_opt::custom, "-foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  	}  	void getOption_toolchain_ar_test() @@ -683,53 +686,53 @@ public:  		//  		exp = { "-r" };  		act = ar_option(ctor::toolchain::gcc, ctor::ar_opt::replace); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-s" };  		act = ar_option(ctor::toolchain::gcc, ctor::ar_opt::add_index); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-c" };  		act = ar_option(ctor::toolchain::gcc, ctor::ar_opt::create); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "foo" };  		act = ar_option(ctor::toolchain::gcc, ctor::ar_opt::output, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-foo" };  		act = ar_option(ctor::toolchain::gcc, ctor::ar_opt::custom, "-foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		//  		// clang  		//  		exp = { "-r" };  		act = ar_option(ctor::toolchain::clang, ctor::ar_opt::replace); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-s" };  		act = ar_option(ctor::toolchain::clang, ctor::ar_opt::add_index); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-c" };  		act = ar_option(ctor::toolchain::clang, ctor::ar_opt::create); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "foo" };  		act = ar_option(ctor::toolchain::clang, ctor::ar_opt::output, "foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { "-foo" };  		act = ar_option(ctor::toolchain::clang, ctor::ar_opt::custom, "-foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		//  		// any  		//  		exp = { "{ctor::ar_opt::custom, \"-foo\"}" };  		act = ar_option(ctor::toolchain::any, ctor::ar_opt::custom, "-foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  }  	void getOption_toolchain_asm_test() @@ -742,21 +745,21 @@ public:  		//  		exp = { "-foo" };  		act = asm_option(ctor::toolchain::gcc, ctor::asm_opt::custom, "-foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		//  		// clang  		//  		exp = { "-foo" };  		act = asm_option(ctor::toolchain::clang, ctor::asm_opt::custom, "-foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		//  		// any  		//  		exp = { "{ctor::asm_opt::custom, \"-foo\"}" };  		act = asm_option(ctor::toolchain::any, ctor::asm_opt::custom, "-foo"); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  	} @@ -770,22 +773,22 @@ public:  		//  		exp = { ctor::c_opt::include_path, "foo" };  		act = c_option("-Ifoo", ctor::toolchain::gcc); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { ctor::c_opt::custom, "foo" };  		act = c_option("foo", ctor::toolchain::gcc); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		//  		// clang  		//  		exp = { ctor::c_opt::include_path, "foo" };  		act = c_option("-Ifoo", ctor::toolchain::clang); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { ctor::c_opt::custom, "foo" };  		act = c_option("foo", ctor::toolchain::clang); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  	}  	void getOption_str_cxx_test() @@ -798,22 +801,22 @@ public:  		//  		exp = { ctor::cxx_opt::include_path, "foo" };  		act = cxx_option("-Ifoo", ctor::toolchain::gcc); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { ctor::cxx_opt::custom, "foo" };  		act = cxx_option("foo", ctor::toolchain::gcc); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		//  		// clang  		//  		exp = { ctor::cxx_opt::include_path, "foo" };  		act = cxx_option("-Ifoo", ctor::toolchain::clang); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { ctor::cxx_opt::custom, "foo" };  		act = cxx_option("foo", ctor::toolchain::clang); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  	}  	void getOption_str_ld_test() @@ -826,22 +829,22 @@ public:  		//  		exp = { ctor::ld_opt::library_path, "foo" };  		act = ld_option("-Lfoo", ctor::toolchain::gcc); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { ctor::ld_opt::custom, "foo" };  		act = ld_option("foo", ctor::toolchain::gcc); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		//  		// clang  		//  		exp = { ctor::ld_opt::library_path, "foo" };  		act = ld_option("-Lfoo", ctor::toolchain::clang); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		exp = { ctor::ld_opt::custom, "foo" };  		act = ld_option("foo", ctor::toolchain::clang); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  	}  	void getOption_str_ar_test() @@ -854,14 +857,14 @@ public:  		//  		exp = { ctor::ar_opt::custom, "foo" };  		act = ar_option("foo", ctor::toolchain::gcc); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		//  		// clang  		//  		exp = { ctor::ar_opt::custom, "foo" };  		act = ar_option("foo", ctor::toolchain::clang); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  	}  	void getOption_str_asm_test() @@ -874,14 +877,14 @@ public:  		//  		exp = { ctor::asm_opt::custom, "foo" };  		act = asm_option("foo", ctor::toolchain::gcc); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  		//  		// clang  		//  		exp = { ctor::asm_opt::custom, "foo" };  		act = asm_option("foo", ctor::toolchain::clang); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  	} @@ -893,7 +896,7 @@ public:  		// Mismatching toolchain (required vs actual) results in no output  		// otherwise to_strings is just a proxy for c_option  		act = to_strings(ctor::toolchain::gcc, {ctor::toolchain::clang, ctor::c_opt::no_link}); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  	}  	void to_strings_cxx_test() @@ -904,7 +907,7 @@ public:  		// Mismatching toolchain (required vs actual) results in no output  		// otherwise to_strings is just a proxy for cxx_option  		act = to_strings(ctor::toolchain::gcc, {ctor::toolchain::clang, ctor::cxx_opt::no_link}); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  	}  	void to_strings_ld_test() @@ -915,7 +918,7 @@ public:  		// Mismatching toolchain (required vs actual) results in no output  		// otherwise to_strings is just a proxy for ld_option  		act = to_strings(ctor::toolchain::gcc, {ctor::toolchain::clang, ctor::ld_opt::strip}); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  	}  	void to_strings_ar_test() @@ -926,7 +929,7 @@ public:  		// Mismatching toolchain (required vs actual) results in no output  		// otherwise to_strings is just a proxy for ar_option  		act = to_strings(ctor::toolchain::gcc, {ctor::toolchain::clang, ctor::ar_opt::custom, "foo"}); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  	}  	void to_strings_asm_test() @@ -937,7 +940,7 @@ public:  		// Mismatching toolchain (required vs actual) results in no output  		// otherwise to_strings is just a proxy for asm_option  		act = to_strings(ctor::toolchain::gcc, {ctor::toolchain::clang, ctor::asm_opt::custom, "foo"}); -		uASSERT_EQUAL(exp, act); +		assert_equal(exp, act, __FILE__, __LINE__);  	}  };  | 
