summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bootstrap.bat22
-rwxr-xr-xbootstrap.sh2
-rwxr-xr-xclbootstrap.sh48
-rwxr-xr-xclrun.sh31
-rw-r--r--ctor.cc25
-rw-r--r--src/bootstrap.cc2
-rw-r--r--src/configure.cc120
-rw-r--r--src/ctor.h29
-rw-r--r--src/execute.cc206
-rw-r--r--src/libctor.cc3
-rw-r--r--src/rebuild.cc21
-rw-r--r--src/task.cc12
-rw-r--r--src/task_ar.cc3
-rw-r--r--src/task_cc.cc7
-rw-r--r--src/task_fn.cc2
-rw-r--r--src/task_ld.cc23
-rw-r--r--src/task_so.cc3
-rw-r--r--src/tools.cc500
-rw-r--r--src/tools.h15
-rw-r--r--src/util.cc23
-rw-r--r--test/ctor.cc47
-rwxr-xr-xtest/suite/test.sh2
-rw-r--r--test/testprog.cc2
-rw-r--r--test/tmpfile.h16
-rw-r--r--test/tools_test.cc5
25 files changed, 1075 insertions, 94 deletions
diff --git a/bootstrap.bat b/bootstrap.bat
new file mode 100644
index 0000000..7f236fc
--- /dev/null
+++ b/bootstrap.bat
@@ -0,0 +1,22 @@
+@echo off
+
+set CXX=cl.exe
+set CC=cl.exe
+set AR=lib.exe
+set LD=link.exe
+
+cl /nologo /std:c++20 /D_X86_ /EHsc /Isrc /Fo:build\ ctor.cc src\bootstrap.cc /link /out:ctor.exe
+if %errorlevel% neq 0 exit /b %errorlevel%
+
+ctor.exe
+if %errorlevel% neq 0 exit /b %errorlevel%
+
+cl /nologo /std:c++20 /D_X86_ /EHsc /Isrc /Fo:build\ ctor.cc /c
+if %errorlevel% neq 0 exit /b %errorlevel%
+cl /nologo /std:c++20 /D_X86_ /EHsc /Isrc /Fo:build\test\ test\ctor.cc /c
+if %errorlevel% neq 0 exit /b %errorlevel%
+link /nologo build\libctor.lib build\ctor.obj build\test\ctor.obj /subsystem:console /out:ctor.exe
+if %errorlevel% neq 0 exit /b %errorlevel%
+
+ctor.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
+
+$*
+
diff --git a/ctor.cc b/ctor.cc
index 92135c2..11828c3 100644
--- a/ctor.cc
+++ b/ctor.cc
@@ -29,19 +29,40 @@ 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",
- "-g",
+// "-g",
"-Wall",
"-Werror",
"-Wextra",
- "-Wshadow",
+// "-Wshadow",
"-Wconversion",
// "-Wnrvo",
"-Isrc",
+ {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/src/bootstrap.cc b/src/bootstrap.cc
index 471c844..0ed2b70 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..bb663d6 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,14 +125,68 @@ 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;
}
+/*
+class Args
+ : public std::vector<char*>
+{
+public:
+ Args(const std::vector<std::string>& args)
+ {
+ string_data.push_back("./ctor");
+ push_back(string_data.back().data());
+ for(const auto& arg : args)
+ {
+ string_data.push_back(arg);
+ push_back(string_data.back().data());
+ }
+ }
+ std::deque<std::string> string_data;
+};
+ */
class Args
: public std::vector<char*>
{
@@ -136,6 +224,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 +449,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 +741,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 +954,25 @@ 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 ret = regenerateCache(settings, args_span[0], args, env);
if(ret != 0)
{
diff --git a/src/ctor.h b/src/ctor.h
index e0e2bef..dd88101 100644
--- a/src/ctor.h
+++ b/src/ctor.h
@@ -59,6 +59,7 @@ enum class toolchain
none,
gcc,
clang,
+ msvc,
};
struct source
@@ -90,6 +91,8 @@ enum class cxx_opt
output, // -o
debug, // -g
warn_all, // -Wall
+ warn_conversion, // -Wconversion
+ warn_extra, // -Wextra
warnings_as_errors, // -Werror
generate_dep_tree, // -MMD
no_link, // -c
@@ -98,6 +101,7 @@ enum class cxx_opt
optimization, // -O<arg>
position_independent_code, // -fPIC
position_independent_executable, // -fPIE
+ define, // -D<arg>[=<arg2>]
custom, // entire option taken verbatim from <arg>
};
@@ -107,6 +111,8 @@ enum class c_opt
output, // -o
debug, // -g
warn_all, // -Wall
+ warn_conversion, // -Wconversion
+ warn_extra, // -Wextra
warnings_as_errors, // -Werror
generate_dep_tree, // -MMD
no_link, // -c
@@ -115,6 +121,7 @@ enum class c_opt
optimization, // -O<arg>
position_independent_code, // -fPIC
position_independent_executable, // -fPIE
+ define, // -D<arg>[=<arg2>]
custom, // entire option taken verbatim from <arg>
};
@@ -159,15 +166,21 @@ public:
flag(std::string_view str);
flag(const char* str);
flag(T opt_) : opt(opt_) {}
- flag(T opt_, std::string_view arg_) : opt(opt_), arg(arg_) {}
- flag(T opt_, const char* arg_) : opt(opt_), arg(arg_) {}
- flag(ctor::toolchain toolchain_, T opt_) : toolchain(toolchain_), opt(opt_) {}
- flag(ctor::toolchain toolchain_, T opt_, const char* arg_) : toolchain(toolchain_), opt(opt_), arg(arg_) {}
- flag(ctor::toolchain toolchain_, T opt_, std::string_view arg_) : toolchain(toolchain_), opt(opt_), arg(arg_) {}
+ flag(T opt_, std::string_view arg_, std::string_view arg2_ = "")
+ : opt(opt_), arg(arg_), arg2(arg2_) {}
+ flag(T opt_, const char* arg_, const char* arg2_ = "")
+ : opt(opt_), arg(arg_), arg2(arg2_) {}
+ flag(ctor::toolchain toolchain_, T opt_)
+ : toolchain(toolchain_), opt(opt_) {}
+ flag(ctor::toolchain toolchain_, T opt_, const char* arg_, const char* arg2_ = "")
+ : toolchain(toolchain_), opt(opt_), arg(arg_), arg2(arg2_) {}
+ flag(ctor::toolchain toolchain_, T opt_, std::string_view arg_, std::string_view arg2_ = "")
+ : toolchain(toolchain_), opt(opt_), arg(arg_), arg2(arg2_) {}
ctor::toolchain toolchain{ctor::toolchain::any};
T opt{};
std::string arg;
+ std::string arg2;
};
using c_flag = ctor::flag<ctor::c_opt>;
@@ -253,12 +266,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";
@@ -269,7 +282,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/execute.cc b/src/execute.cc
index cbae899..3d8fe62 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/
@@ -22,6 +32,7 @@ https://stackoverflow.com/questions/4259629/what-is-the-difference-between-fork-
namespace
{
+/*
class Env
: public std::vector<char*>
{
@@ -30,7 +41,27 @@ public:
{
for(const auto& arg : args)
{
+ string_data.push_back(arg);
+ push_back(string_data.back().data());
+ }
+ }
+
+ std::deque<std::string> string_data;
+};
+*/
+class Env
+ : public std::vector<char*>
+{
+public:
+ Env(const std::vector<std::string>& args)
+ {
+ 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 +75,7 @@ public:
}
};
+#if !defined(_WIN32)
int parent_waitpid(pid_t pid)
{
int status{};
@@ -55,6 +87,7 @@ int parent_waitpid(pid_t pid)
return WEXITSTATUS(status);
}
+#endif //_WIN32
} // namespace ::
extern char **environ; // see 'man environ'
@@ -92,6 +125,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 +168,166 @@ 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';
+
+ 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
+ {
+ return 1; // Could not start process;
+ }
+
+ // 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 1db5e83..ca450dc 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());
+ 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,9 @@ 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,13 +186,20 @@ 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.
- settings.builddir += "/ctor"; // override builddir to use ctor subdir
+
+ // override builddir to use ctor subdir
+ auto ctor_builddir = std::filesystem::path(settings.builddir) / "ctor";
+ settings.builddir = ctor_builddir.string();
{
std::filesystem::path buildfile = settings.builddir;
diff --git a/src/task.cc b/src/task.cc
index a9c0fee..ef7731b 100644
--- a/src/task.cc
+++ b/src/task.cc
@@ -3,7 +3,6 @@
// See accompanying file LICENSE for details.
#include "task.h"
-#include <unistd.h>
#include <iostream>
#include <algorithm>
#include <utility>
@@ -46,11 +45,14 @@ int Task::registerDepTasks(const std::vector<std::shared_ptr<Task>>& tasks)
bool Task::operator==(const std::string& depStr)
{
+ std::filesystem::path generated_output = sourceDir;
+ generated_output /= target();
return
- name() == depStr ||
- target() == depStr ||
- sourceDir + "/" + target() == 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 b16a2f9..406dbdb 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());
@@ -188,7 +190,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 e1f3023..ad62763 100644
--- a/src/task_cc.cc
+++ b/src/task_cc.cc
@@ -275,18 +275,21 @@ 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";
exit(1);
break;
}
+
}
std::string TaskCC::flagsString() const
@@ -310,7 +313,7 @@ std::vector<std::string> TaskCC::getCompilerArgs() const
{
case ctor::language::c:
{
- append(args, c_option(toolchain, ctor::c_opt::generate_dep_tree));
+ append(args, c_option(toolchain, ctor::c_opt::generate_dep_tree, depsFile.string()));
if(std::filesystem::path(config.target).extension() == ".so")
{
@@ -352,7 +355,7 @@ std::vector<std::string> TaskCC::getCompilerArgs() const
case ctor::language::cpp:
{
- append(args, cxx_option(toolchain, ctor::cxx_opt::generate_dep_tree));
+ append(args, cxx_option(toolchain, ctor::cxx_opt::generate_dep_tree, depsFile.string()));
if(std::filesystem::path(config.target).extension() == ".so")
{
diff --git a/src/task_fn.cc b/src/task_fn.cc
index 2fa0ad6..258897c 100644
--- a/src/task_fn.cc
+++ b/src/task_fn.cc
@@ -97,7 +97,7 @@ std::vector<std::string> TaskFn::depends() const
std::string TaskFn::target() const
{
- return _targetFile;
+ return _targetFile.string();
}
std::filesystem::path TaskFn::targetFile() const
diff --git a/src/task_ld.cc b/src/task_ld.cc
index c8cd1ea..dbe17c5 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);
@@ -126,8 +127,27 @@ int TaskLD::runInner()
std::cout << "LD => " << targetFile().string() << std::endl;
}
- 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);
}
@@ -196,7 +216,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 75b5f3c..d818d94 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());
@@ -183,7 +185,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 394a91c..4dc6b3b 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,8 @@ 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_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;
@@ -28,6 +31,7 @@ std::ostream& operator<<(std::ostream& stream, const ctor::c_opt& opt)
case ctor::c_opt::optimization: stream << "ctor::c_opt::optimization"; break;
case ctor::c_opt::position_independent_code: stream << "ctor::c_opt::position_independent_code"; break;
case ctor::c_opt::position_independent_executable: stream << "ctor::c_opt::position_independent_executable"; break;
+ case ctor::c_opt::define: stream << "ctor::c_opt::define"; break;
case ctor::c_opt::custom: stream << "ctor::c_opt::custom"; break;
}
@@ -42,6 +46,8 @@ 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_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;
@@ -50,6 +56,7 @@ std::ostream& operator<<(std::ostream& stream, const ctor::cxx_opt& opt)
case ctor::cxx_opt::optimization: stream << "ctor::cxx_opt::optimization"; break;
case ctor::cxx_opt::position_independent_code: stream << "ctor::cxx_opt::position_independent_code"; break;
case ctor::cxx_opt::position_independent_executable: stream << "ctor::cxx_opt::position_independent_executable"; break;
+ case ctor::cxx_opt::define: stream << "ctor::cxx_opt::define"; break;
case ctor::cxx_opt::custom: stream << "ctor::cxx_opt::custom"; break;
}
@@ -109,18 +116,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;
@@ -146,12 +162,258 @@ 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_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_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)
{
@@ -172,7 +434,6 @@ std::string get_arch(ctor::output_system system)
return {};//ctor::arch::unknown;
}
- std::string arch;
while(!feof(pipe))
{
constexpr auto buffer_size{1024};
@@ -198,6 +459,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;
}
@@ -245,6 +507,56 @@ 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("-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);
+ auto pos = def.find('=');
+ if(pos != def.npos)
+ {
+ return { ctor::c_opt::define, def.substr(0, pos), def.substr(pos + 1) };
+ }
+ else
+ {
+ return { ctor::c_opt::define, def };
+ }
+ }
return { ctor::c_opt::custom, flag };
}
@@ -257,6 +569,57 @@ 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("-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);
+ auto pos = def.find('=');
+ if(pos != def.npos)
+ {
+ return { ctor::cxx_opt::define, def.substr(0, pos), def.substr(pos + 1) };
+ }
+ else
+ {
+ return { ctor::cxx_opt::define, def };
+ }
+ }
+
return { ctor::cxx_opt::custom, flag };
}
@@ -269,6 +632,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 };
}
@@ -277,7 +645,8 @@ 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)
+std::vector<std::string> cxx_option(ctor::cxx_opt opt, const std::string& arg,
+ const std::string& arg2)
{
switch(opt)
{
@@ -287,6 +656,10 @@ 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_extra:
+ return {"-Wextra"};
case ctor::cxx_opt::warnings_as_errors:
return {"-Werror"};
case ctor::cxx_opt::generate_dep_tree:
@@ -303,6 +676,12 @@ std::vector<std::string> cxx_option(ctor::cxx_opt opt, const std::string& arg)
return {"-fPIC"};
case ctor::cxx_opt::position_independent_executable:
return {"-fPIE"};
+ case ctor::cxx_opt::define:
+ if(!arg2.empty())
+ {
+ return {"-D" + arg + "=" + arg2};
+ }
+ return {"-D" + arg};
case ctor::cxx_opt::custom:
return {arg};
}
@@ -311,7 +690,8 @@ std::vector<std::string> cxx_option(ctor::cxx_opt opt, const std::string& arg)
return {};
}
-std::vector<std::string> c_option(ctor::c_opt opt, const std::string& arg)
+std::vector<std::string> c_option(ctor::c_opt opt, const std::string& arg,
+ const std::string& arg2)
{
switch(opt)
{
@@ -321,6 +701,10 @@ 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_extra:
+ return {"-Wextra"};
case ctor::c_opt::warnings_as_errors:
return {"-Werror"};
case ctor::c_opt::generate_dep_tree:
@@ -337,6 +721,12 @@ std::vector<std::string> c_option(ctor::c_opt opt, const std::string& arg)
return {"-fPIC"};
case ctor::c_opt::position_independent_executable:
return {"-fPIE"};
+ case ctor::c_opt::define:
+ if(!arg2.empty())
+ {
+ return {"-D" + arg + "=" + arg2};
+ }
+ return {"-D" + arg};
case ctor::c_opt::custom:
return {arg};
}
@@ -345,7 +735,8 @@ std::vector<std::string> c_option(ctor::c_opt opt, const std::string& arg)
return {};
}
-std::vector<std::string> ld_option(ctor::ld_opt opt, const std::string& arg)
+std::vector<std::string> ld_option(ctor::ld_opt opt, const std::string& arg,
+ [[maybe_unused]]const std::string& arg2)
{
switch(opt)
{
@@ -379,7 +770,8 @@ std::vector<std::string> ld_option(ctor::ld_opt opt, const std::string& arg)
return {};
}
-std::vector<std::string> ar_option(ctor::ar_opt opt, const std::string& arg)
+std::vector<std::string> ar_option(ctor::ar_opt opt, const std::string& arg,
+ [[maybe_unused]]const std::string& arg2)
{
switch(opt)
{
@@ -399,7 +791,8 @@ std::vector<std::string> ar_option(ctor::ar_opt opt, const std::string& arg)
return {};
}
-std::vector<std::string> asm_option(ctor::asm_opt opt, const std::string& arg)
+std::vector<std::string> asm_option(ctor::asm_opt opt, const std::string& arg,
+ [[maybe_unused]]const std::string& arg2)
{
switch(opt)
{
@@ -420,6 +813,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;
@@ -435,6 +830,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;
@@ -444,13 +841,16 @@ ctor::arch get_arch(ctor::output_system system, const std::string& str)
std::vector<std::string> c_option(ctor::toolchain toolchain,
ctor::c_opt opt,
- const std::string& arg)
+ const std::string& arg,
+ const std::string& arg2)
{
switch(toolchain)
{
case ctor::toolchain::gcc:
case ctor::toolchain::clang:
- return gcc::c_option(opt, arg);
+ 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;
@@ -459,6 +859,10 @@ std::vector<std::string> c_option(ctor::toolchain toolchain,
{
ss << ", \"" << arg << "\"";
}
+ if(!arg2.empty())
+ {
+ ss << ", \"" << arg2 << "\"";
+ }
ss << "}";
return { ss.str() };
}
@@ -472,13 +876,16 @@ std::vector<std::string> c_option(ctor::toolchain toolchain,
std::vector<std::string> cxx_option(ctor::toolchain toolchain,
ctor::cxx_opt opt,
- const std::string& arg)
+ const std::string& arg,
+ const std::string& arg2)
{
switch(toolchain)
{
case ctor::toolchain::gcc:
case ctor::toolchain::clang:
- return gcc::cxx_option(opt, arg);
+ 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;
@@ -487,6 +894,10 @@ std::vector<std::string> cxx_option(ctor::toolchain toolchain,
{
ss << ", \"" << arg << "\"";
}
+ if(!arg2.empty())
+ {
+ ss << ", \"" << arg2 << "\"";
+ }
ss << "}";
return { ss.str() };
}
@@ -500,13 +911,16 @@ std::vector<std::string> cxx_option(ctor::toolchain toolchain,
std::vector<std::string> ld_option(ctor::toolchain toolchain,
ctor::ld_opt opt,
- const std::string& arg)
+ const std::string& arg,
+ const std::string& arg2)
{
switch(toolchain)
{
case ctor::toolchain::gcc:
case ctor::toolchain::clang:
- return gcc::ld_option(opt, arg);
+ 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;
@@ -515,6 +929,10 @@ std::vector<std::string> ld_option(ctor::toolchain toolchain,
{
ss << ", \"" << arg << "\"";
}
+ if(!arg2.empty())
+ {
+ ss << ", \"" << arg2 << "\"";
+ }
ss << "}";
return { ss.str() };
}
@@ -528,13 +946,16 @@ std::vector<std::string> ld_option(ctor::toolchain toolchain,
std::vector<std::string> ar_option(ctor::toolchain toolchain,
ctor::ar_opt opt,
- const std::string& arg)
+ const std::string& arg,
+ const std::string& arg2)
{
switch(toolchain)
{
case ctor::toolchain::gcc:
case ctor::toolchain::clang:
- return gcc::ar_option(opt, arg);
+ 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;
@@ -543,6 +964,10 @@ std::vector<std::string> ar_option(ctor::toolchain toolchain,
{
ss << ", \"" << arg << "\"";
}
+ if(!arg2.empty())
+ {
+ ss << ", \"" << arg2 << "\"";
+ }
ss << "}";
return { ss.str() };
}
@@ -556,13 +981,16 @@ std::vector<std::string> ar_option(ctor::toolchain toolchain,
std::vector<std::string> asm_option(ctor::toolchain toolchain,
ctor::asm_opt opt,
- const std::string& arg)
+ const std::string& arg,
+ const std::string& arg2)
{
switch(toolchain)
{
case ctor::toolchain::gcc:
case ctor::toolchain::clang:
- return gcc::asm_option(opt, arg);
+ 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;
@@ -571,6 +999,10 @@ std::vector<std::string> asm_option(ctor::toolchain toolchain,
{
ss << ", \"" << arg << "\"";
}
+ if(!arg2.empty())
+ {
+ ss << ", \"" << arg2 << "\"";
+ }
ss << "}";
return { ss.str() };
}
@@ -590,6 +1022,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;
@@ -605,6 +1039,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;
@@ -620,6 +1056,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;
@@ -635,6 +1073,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;
@@ -649,6 +1089,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;
@@ -665,7 +1106,7 @@ std::vector<std::string> to_strings(ctor::toolchain toolchain,
if(flag.toolchain == ctor::toolchain::any ||
flag.toolchain == toolchain)
{
- return c_option(toolchain, flag.opt, flag.arg);
+ return c_option(toolchain, flag.opt, flag.arg, flag.arg2);
}
return {};
@@ -677,7 +1118,7 @@ std::vector<std::string> to_strings(ctor::toolchain toolchain,
if(flag.toolchain == ctor::toolchain::any ||
flag.toolchain == toolchain)
{
- return cxx_option(toolchain, flag.opt, flag.arg);
+ return cxx_option(toolchain, flag.opt, flag.arg, flag.arg2);
}
return {};
@@ -689,7 +1130,7 @@ std::vector<std::string> to_strings(ctor::toolchain toolchain,
if(flag.toolchain == ctor::toolchain::any ||
flag.toolchain == toolchain)
{
- return ld_option(toolchain, flag.opt, flag.arg);
+ return ld_option(toolchain, flag.opt, flag.arg, flag.arg2);
}
return {};
@@ -701,7 +1142,7 @@ std::vector<std::string> to_strings(ctor::toolchain toolchain,
if(flag.toolchain == ctor::toolchain::any ||
flag.toolchain == toolchain)
{
- return ar_option(toolchain, flag.opt, flag.arg);
+ return ar_option(toolchain, flag.opt, flag.arg, flag.arg2);
}
return {};
@@ -713,7 +1154,7 @@ std::vector<std::string> to_strings(ctor::toolchain toolchain,
if(flag.toolchain == ctor::toolchain::any ||
flag.toolchain == toolchain)
{
- return asm_option(toolchain, flag.opt, flag.arg);
+ return asm_option(toolchain, flag.opt, flag.arg, flag.arg2);
}
return {};
@@ -732,10 +1173,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;
}
}
@@ -806,8 +1248,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/tools.h b/src/tools.h
index 188d49f..0e7fc15 100644
--- a/src/tools.h
+++ b/src/tools.h
@@ -32,31 +32,36 @@ ctor::toolchain getToolChain(ctor::output_system system);
//! tool-chain
std::vector<std::string> c_option(ctor::toolchain toolchain,
ctor::c_opt option,
- const std::string& arg = {});
+ const std::string& arg = {},
+ const std::string& arg2 = {});
//! Get tool argument(s) for specific option type matching the supplied
//! tool-chain
std::vector<std::string> cxx_option(ctor::toolchain toolchain,
ctor::cxx_opt option,
- const std::string& arg = {});
+ const std::string& arg = {},
+ const std::string& arg2 = {});
//! Get tool argument(s) for specific option type matching the supplied
//! tool-chain
std::vector<std::string> ld_option(ctor::toolchain toolchain,
ctor::ld_opt option,
- const std::string& arg = {});
+ const std::string& arg = {},
+ const std::string& arg2 = {});
//! Get tool argument(s) for specific option type matching the supplied
//! tool-chain
std::vector<std::string> ar_option(ctor::toolchain toolchain,
ctor::ar_opt option,
- const std::string& arg = {});
+ const std::string& arg = {},
+ const std::string& arg2 = {});
//! Get tool argument(s) for specific option type matching the supplied
//! tool-chain
std::vector<std::string> asm_option(ctor::toolchain toolchain,
ctor::asm_opt option,
- const std::string& arg = {});
+ const std::string& arg = {},
+ const std::string& arg2 = {});
diff --git a/src/util.cc b/src/util.cc
index 73b158d..d1f20d8 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,17 +26,23 @@ 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<std::streamsize>(bytes.size()));
- return {bytes.data(), static_cast<std::size_t>(fileSize)};
+ return { bytes.data(), bytes.size() };
}
std::vector<std::string> readDeps(const std::string& depFile)
{
+ return {};// TODO: parse json
if(!std::filesystem::exists(depFile))
{
return {};
diff --git a/test/ctor.cc b/test/ctor.cc
index ccf1c31..56218f9 100644
--- a/test/ctor.cc
+++ b/test/ctor.cc
@@ -10,15 +10,17 @@ ctor::build_configurations ctorTestConfigs(const ctor::settings& settings)
return
{
{
+ .name = "testprog",
.type = ctor::target_type::unit_test,
.system = ctor::output_system::build,
.target = "testprog",
.sources = {
- "testprog.cc",
+ {"testprog.cc"},
},
.flags = {
.cxxflags = {
- "-std=c++20", "-O3", "-Wall", "-Werror",
+ "-std=c++20", "-O3", "-Wall",// "-Werror",
+ {ctor::toolchain::msvc, ctor::cxx_opt::custom, "/EHsc"},
},
},
},
@@ -35,9 +37,10 @@ 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"},
},
.ldflags = { "-pthread" },
},
@@ -50,12 +53,13 @@ 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"},
},
.ldflags = { "-pthread" },
},
@@ -68,12 +72,13 @@ 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"},
},
.ldflags = { "-pthread" },
},
@@ -91,16 +96,17 @@ 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"},
},
},
},
{
.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",
@@ -116,11 +122,32 @@ 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",
+ {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/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/testprog.cc b/test/testprog.cc
index dbfb665..2b6619e 100644
--- a/test/testprog.cc
+++ b/test/testprog.cc
@@ -2,7 +2,7 @@
#include <fstream>
#include <string>
-extern const char **environ; // see 'man environ'
+extern char **environ; // see 'man environ'
int main(int argc, const char* argv[])
{
diff --git a/test/tmpfile.h b/test/tmpfile.h
index 5d114d0..e1a2ff6 100644
--- a/test/tmpfile.h
+++ b/test/tmpfile.h
@@ -4,7 +4,6 @@
#pragma once
#include <cstdlib>
-#include <unistd.h>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
@@ -12,6 +11,9 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <io.h>
+#else
+#include <unistd.h>
#endif
struct tmp_file
@@ -22,20 +24,28 @@ struct tmp_file
#ifdef _WIN32
char templ[] = "ctor_tmp_file-XXXXXX"; // buffer for filename
_mktemp_s(templ, sizeof(templ));
- fd = open(templ, O_CREAT | O_RDWR);
+ fd = _open(templ, O_CREAT | O_RDWR);
+ filename = templ;
+ 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;
auto sz = write(fd, data.data(), data.size());
(void)sz;
close(fd);
+#endif
}
~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..d5f84f4 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)
{