From 135cac7602277b3f487b10e81ffbb3aa2310507e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Lasersk=C3=B6ld?= Date: Sat, 20 Mar 2021 17:21:26 +0100 Subject: [PATCH 1/6] Fix builds on windows #28 --- CMakeLists.txt | 1 + build-win-clang.bat | 8 +++--- build-win-gcc.bat | 7 +++--- build-win-msvc.bat | 13 ++++++---- matmake.cpp | 1 + src/env.cpp | 54 +++++++++++++++++++++++++++++++++++++++++ src/env.h | 5 ++++ src/msvcenvironment.cpp | 50 ++++++++++++++++++++------------------ src/nativecommands.cpp | 19 +++++++++++++++ src/os.h | 11 ++++++++- 10 files changed, 133 insertions(+), 36 deletions(-) create mode 100644 src/env.cpp create mode 100644 src/env.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a449f6..96e19db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,7 @@ add_library( "src/translateconfig.cpp" "src/msvcenvironment.cpp" "src/exampleproject.cpp" + "src/env.cpp" ) add_subdirectory(lib/json.h) diff --git a/build-win-clang.bat b/build-win-clang.bat index c1ba3da..299bfdd 100644 --- a/build-win-clang.bat +++ b/build-win-clang.bat @@ -1,8 +1,10 @@ + +setlocal + mkdir "build" -mkdir "build\clang" call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64 -clang++.exe -Iinclude -Ilib/json.h/include -Isrc matmake.cpp -std=c++17 -o build/clang/matmake.exe +clang++.exe -Iinclude -Ilib/json.h/include -Isrc matmake.cpp -std=c++17 -o build/matmake2.exe -echo matmake created in build/clang +echo matmake created in build diff --git a/build-win-gcc.bat b/build-win-gcc.bat index e468470..b904c5a 100644 --- a/build-win-gcc.bat +++ b/build-win-gcc.bat @@ -1,7 +1,8 @@ +setlocal + mkdir "build" -mkdir "build\gcc" -g++ -Iinclude -Ilib/json.h/include -Isrc matmake.cpp -std=c++17 -o build/gcc/matmake.exe +g++ -Iinclude -Ilib/json.h/include -Isrc matmake.cpp -std=c++17 -o build/matmake2.exe -echo matmake created in build/g++ +echo matmake created in build diff --git a/build-win-msvc.bat b/build-win-msvc.bat index 04ac3d1..7c54777 100644 --- a/build-win-msvc.bat +++ b/build-win-msvc.bat @@ -1,12 +1,15 @@ +setlocal + mkdir build -mkdir "build\msvc" -cd build/msvc +cd build call "%PROGRAMFILES(X86)%\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64 -cl.exe /I..\..\include /I..\..\lib/json.h/include /I..\..\src ..\..\matmake.cpp ^ - /std:c++17 /EHa /D NOMINMAX /link /out:matmake.exe +cl.exe /I..\include /I..\lib/json.h/include /I..\src ..\matmake.cpp ^ + /std:c++17 /EHa /D NOMINMAX /link /out:matmake2.exe + +echo matmake created in build/ -echo matmake created in build/msvc +cd ../ \ No newline at end of file diff --git a/matmake.cpp b/matmake.cpp index 2d3e435..4bc7780 100644 --- a/matmake.cpp +++ b/matmake.cpp @@ -2,6 +2,7 @@ //! Seems to speed up build around 4x #include "src/defaultfile.cpp" +#include "src/env.cpp" #include "src/exampleproject.cpp" #include "src/matmakefile.cpp" #include "src/msvcenvironment.cpp" diff --git a/src/env.cpp b/src/env.cpp new file mode 100644 index 0000000..a3f2113 --- /dev/null +++ b/src/env.cpp @@ -0,0 +1,54 @@ +//! This file handles all different ways to add to environment +//! Variables + +#include "os.h" +#include +#include + +#ifdef MATMAKE_USING_WINDOWS + +#if defined(__MINGW32__) || defined(__CYGWIN__) + +extern "C" int putenv(char *); + +void setenv(const char *name, const char *value, int overwrite) { + auto arg = std::string{name} + value; + putenv(arg.data()); +} + +std::string getEnvVar(std::string name) { + return getenv(name.c_str()); +} + +#else + +int setenv(const char *name, const char *value, int overwrite) { + return _putenv_s(name, value); +} + +std::string getEnvVar(std::string name) { + size_t size; + getenv_s(&size, 0, 0, name.c_str()); + + std::string var; + var.resize(size); + getenv_s(&size, var.data(), size, name.c_str()); + + return var; +} + +#endif + +#else + +std::string getEnvVar(std::string name) { + return getenv(name.c_str()); +} + +#endif + +void appendEnv(std::string name, std::string value) { + value = getEnvVar(name) + value; + + setenv(name.c_str(), value.c_str(), 1); +} diff --git a/src/env.h b/src/env.h new file mode 100644 index 0000000..c310702 --- /dev/null +++ b/src/env.h @@ -0,0 +1,5 @@ + +#include + +void appendEnv(std::string name, std::string value); +std::string getEnvVar(std::string name); diff --git a/src/msvcenvironment.cpp b/src/msvcenvironment.cpp index f4ca21e..bb11f88 100644 --- a/src/msvcenvironment.cpp +++ b/src/msvcenvironment.cpp @@ -1,21 +1,22 @@ +#include "env.h" #include "filesystem.h" #include "os.h" -#include #include #include #include +namespace { + #ifdef MATMAKE_USING_WINDOWS -int setenv(const char *name, const char *value, int overwrite) { - // auto s = std::string{name} + "=" + value; - return _putenv_s(name, value); -} +constexpr const char *msvcPathName = "PATH"; -#endif +#else -namespace { +constexpr const char *msvcPathName = "WINEPATH"; + +#endif //! Get the first folder in the path filesystem::path getHighest(filesystem::path path) { @@ -40,15 +41,22 @@ std::string concatPaths(std::vector paths) { }); } +filesystem::path cSpelling() { + if (usingMingw()) { + return filesystem::path{"C:/"}; + } + return filesystem::path{"C:\\"}; +} + } // namespace void setMsvcEnvironment() { filesystem::path driveC = [] { if (getOs() == Os::Windows) { - return filesystem::path{"C:"}; + return cSpelling(); } else { - auto home = filesystem::path{getenv("HOME")}; + auto home = filesystem::path{getEnvVar("HOME")}; return filesystem::path{home / ".wine" / "drive_c"}; } }(); @@ -63,7 +71,8 @@ void setMsvcEnvironment() { return it.path(); } } - throw std::runtime_error{"no program files folder was found"}; + throw std::runtime_error{"no program files folder was found in " + + driveC.string()}; }(); auto winSdk = programFiles / "Windows Kits" / "10"; @@ -72,24 +81,20 @@ void setMsvcEnvironment() { auto msvcPath = getHighest(getHighest(vsSdk) / "VC" / "Tools" / "MSVC"); { - // WINEPATH + // WINEPATH/PATH auto paths = std::vector{ // getHighest(vsSdk) / "Common7" / "IDE", // Required? msvcPath / "bin" / "Hostx86" / "x64", }; - auto regular = "C:\\windows;C:\\windows\\system32"; - for (auto &path : paths) { if (!filesystem::exists(path)) { std::cerr << "cannot find path " << path << "\n"; } - path = "C:" / compat_relative(path, driveC); + path = cSpelling() / compat_relative(path, driveC); } - auto path = regular + concatPaths(paths); - - setenv("WINEPATH", path.c_str(), 1); + appendEnv(msvcPathName, concatPaths(paths)); } { @@ -110,12 +115,10 @@ void setMsvcEnvironment() { if (!filesystem::exists(include)) { std::cerr << "cannot find path " << include << "\n"; } - include = "C:" / compat_relative(include, driveC); - // std::cout << include << std::endl; + include = cSpelling() / compat_relative(include, driveC); } - auto str = concatPaths(includes); - setenv("INCLUDE", str.c_str(), 1); + appendEnv("INCLUDE", concatPaths(includes)); } { @@ -134,10 +137,9 @@ void setMsvcEnvironment() { if (!filesystem::exists(lib)) { std::cerr << "cannot find path " << lib << "\n"; } - lib = "C:" / compat_relative(lib, driveC); + lib = cSpelling() / compat_relative(lib, driveC); } - auto str = concatPaths(libPaths); - setenv("LIB", str.c_str(), 1); + appendEnv("LIB", concatPaths(libPaths)); } } diff --git a/src/nativecommands.cpp b/src/nativecommands.cpp index 3f5047d..efbae46 100644 --- a/src/nativecommands.cpp +++ b/src/nativecommands.cpp @@ -1,6 +1,7 @@ #include "nativecommands.h" #include "filesystem.h" #include "task.h" +#include #include native::CommandType native::findCommand(std::string name) { @@ -29,6 +30,22 @@ native::CommandStatus native::copy(const Task &task) { auto in = task.in().front()->out(); auto out = task.out(); +#ifdef MATMAKE_USING_WINDOWS + + { + auto str = in.string(); + std::replace(str.begin(), str.end(), '/', '\\'); + in = str; + } + + { + auto str = out.string(); + std::replace(str.begin(), str.end(), '/', '\\'); + out = str; + } + +#endif + std::cout << (in.string() + " --> " + out.string()) << std::endl; if (filesystem::equivalent(in, out)) { @@ -38,6 +55,8 @@ native::CommandStatus native::copy(const Task &task) { filesystem::copy(in, out, filesystem::copy_options::overwrite_existing, ec); if (ec) { + std::cerr << "error: Failed to copy " << in << " --> " << out + << std::endl; return CommandStatus::Failed; } else { diff --git a/src/os.h b/src/os.h index 1f84b48..8fe0f37 100644 --- a/src/os.h +++ b/src/os.h @@ -5,7 +5,8 @@ enum Os { Windows, }; -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || \ + defined(__NT__) || defined(__MINGW32__) || defined(__CYGWIN__) #define MATMAKE_USING_WINDOWS #endif constexpr Os getOs() { @@ -15,3 +16,11 @@ constexpr Os getOs() { return Os::Linux; #endif } + +constexpr bool usingMingw() { +#if defined(__MINGW32__) || defined(__CYGWIN__) + return true; +#else + return false; +#endif +} \ No newline at end of file From 3b9451854d376f91fdc8d44573f014c660cfbe53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Lasersk=C3=B6ld?= Date: Sat, 20 Mar 2021 18:36:13 +0100 Subject: [PATCH 2/6] Fix Matmakefile for demo1 --- demos/project1/Matmakefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/demos/project1/Matmakefile b/demos/project1/Matmakefile index e7cb7b9..d10980e 100644 --- a/demos/project1/Matmakefile +++ b/demos/project1/Matmakefile @@ -1,10 +1,14 @@ main src = src/*.cpp + out = main config = debug c++17 command = [exe] + includes = + src + include all in = @main From 175bfea23e0210ec3523a9e32fea539161fb4e9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Lasersk=C3=B6ld?= Date: Sun, 21 Mar 2021 15:59:48 +0100 Subject: [PATCH 3/6] Fix stuff with envirionment in windows #28 --- src/env.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/env.cpp b/src/env.cpp index a3f2113..5b2b206 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -2,6 +2,7 @@ //! Variables #include "os.h" +#include #include #include @@ -22,19 +23,18 @@ std::string getEnvVar(std::string name) { #else +#include + int setenv(const char *name, const char *value, int overwrite) { - return _putenv_s(name, value); + return -!SetEnvironmentVariableA(name, value); } std::string getEnvVar(std::string name) { - size_t size; - getenv_s(&size, 0, 0, name.c_str()); + auto arr = std::array{}; - std::string var; - var.resize(size); - getenv_s(&size, var.data(), size, name.c_str()); + size_t size = GetEnvironmentVariableA(name.c_str(), arr.data(), arr.size()); - return var; + return std::string(arr.data(), size); } #endif @@ -48,7 +48,9 @@ std::string getEnvVar(std::string name) { #endif void appendEnv(std::string name, std::string value) { - value = getEnvVar(name) + value; + auto oldVar = getEnvVar(name); + + value = oldVar + value; setenv(name.c_str(), value.c_str(), 1); } From a5026566fad3685041768642393d80f01de3f2e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Lasersk=C3=B6ld?= Date: Sun, 21 Mar 2021 17:24:57 +0100 Subject: [PATCH 4/6] Fix bugs --- build-win-clang.bat | 2 +- build-win-msvc.bat | 4 ++-- src/env.cpp | 2 +- src/main/main.cpp | 7 +++++++ src/prescan.h | 8 ++++++-- src/task.h | 5 +++++ 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/build-win-clang.bat b/build-win-clang.bat index 299bfdd..d9bb2ec 100644 --- a/build-win-clang.bat +++ b/build-win-clang.bat @@ -5,6 +5,6 @@ mkdir "build" call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64 -clang++.exe -Iinclude -Ilib/json.h/include -Isrc matmake.cpp -std=c++17 -o build/matmake2.exe +clang++.exe -Iinclude -Ilib/json.h/include -Isrc matmake.cpp -std=c++17 -o build/matmake2.exe -g echo matmake created in build diff --git a/build-win-msvc.bat b/build-win-msvc.bat index 7c54777..fdd7bea 100644 --- a/build-win-msvc.bat +++ b/build-win-msvc.bat @@ -8,8 +8,8 @@ cd build call "%PROGRAMFILES(X86)%\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64 cl.exe /I..\include /I..\lib/json.h/include /I..\src ..\matmake.cpp ^ - /std:c++17 /EHa /D NOMINMAX /link /out:matmake2.exe + /std:c++17 /EHa /D NOMINMAX /link /out:matmake2.exe /DEBUG:FULL echo matmake created in build/ -cd ../ \ No newline at end of file +cd ../ diff --git a/src/env.cpp b/src/env.cpp index 5b2b206..1821e14 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -10,7 +10,7 @@ #if defined(__MINGW32__) || defined(__CYGWIN__) -extern "C" int putenv(char *); +extern "C" int putenv(const char *); void setenv(const char *name, const char *value, int overwrite) { auto arg = std::string{name} + value; diff --git a/src/main/main.cpp b/src/main/main.cpp index af7b3a3..095949f 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -277,6 +277,13 @@ int main(int argc, char **argv) { std::cerr << "error: " << e.what() << "\n"; return 1; } + catch (std::exception &e) { + std::cerr << "error: " << e.what() << "\n"; + } + + catch (...) { + std::cerr << "unknown error\n"; + } return 0; } diff --git a/src/prescan.h b/src/prescan.h index 147e6b1..df802fe 100644 --- a/src/prescan.h +++ b/src/prescan.h @@ -160,6 +160,11 @@ PrescanResult parseExpandedFile(filesystem::path expandedFile, PrescanResult prescan(Task &task) { auto expandedFile = task.out(); + + if (task.in().empty()) { + throw std::runtime_error{"error: in prescan(): task " + task.name() + + " does not have in tasks"}; + } auto source = task.in().front()->out(); auto jsonFile = task.dir() / (source.string() + ".json"); @@ -215,8 +220,7 @@ void prescan(TaskList &tasks) { std::vector> connections; for (auto &task : tasks) { - if (auto t = getType(task->out()); - t == SourceType::ExpandedModuleSource) { + if (task->shouldPrescan()) { auto prescanResult = prescan(*task); auto pcm = task->parent(); diff --git a/src/task.h b/src/task.h index 2165dd0..613a4d1 100644 --- a/src/task.h +++ b/src/task.h @@ -740,6 +740,11 @@ class Task { return _shouldLinkFile; } + bool shouldPrescan() { + return getType(out()) == SourceType::ExpandedModuleSource && + _command == "[cxxm]"; + } + Json dump(); //! Print tree view from node From cb4a52f2279a6121c28ed98228fa2793d5171eb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Lasersk=C3=B6ld?= Date: Sun, 21 Mar 2021 19:51:56 +0100 Subject: [PATCH 5/6] More fixes --- src/createtasks.h | 16 +++++------ src/defaultfile.cpp | 60 ++++++++++++++++++++++++------------------ src/filesystem.h | 28 +++++++++++++++++++- src/nativecommands.cpp | 3 +++ src/property.h | 7 +++++ 5 files changed, 80 insertions(+), 34 deletions(-) diff --git a/src/createtasks.h b/src/createtasks.h index a921a9a..8ec1788 100644 --- a/src/createtasks.h +++ b/src/createtasks.h @@ -207,19 +207,19 @@ inline std::pair createTree( style = task.flagStyle(); } if (auto p = root.property("dir")) { - task.dir(BuildLocation::Real, p->value()); + task.dir(BuildLocation::Real, p->path()); } if (auto p = root.property("objdir")) { - task.dir(BuildLocation::Intermediate, p->value()); + task.dir(BuildLocation::Intermediate, p->path()); } if (auto p = root.property("cxx")) { - task.cxx(p->value()); + task.cxx(p->path()); } if (auto p = root.property("cc")) { - task.cc(p->value()); + task.cc(p->path()); } if (auto p = root.property("ar")) { - task.ar(p->value()); + task.ar(p->path()); } if (auto p = root.property("command")) { task.command(p->value()); @@ -227,7 +227,7 @@ inline std::pair createTree( if (auto p = root.property("src")) { // Requires command to be red before becauso of flag style for (auto &src : p->values) { - auto paths = expandPaths(src); + auto paths = expandPaths(normalizePath(src)); for (auto &path : paths) { if (auto f = duplicateMap.find(path); f != duplicateMap.end()) { @@ -277,7 +277,7 @@ inline std::pair createTree( } } if (auto p = root.property("out")) { - task.out(p->value()); + task.out(p->path()); } if (auto p = root.property("flags")) { task.flags(p->concat()); @@ -294,7 +294,7 @@ inline std::pair createTree( } } if (auto p = root.property(("depprefix"))) { - task.depfile(p->value()); + task.depfile(p->path()); } if (auto p = root.property("config")) { task.config(p->values); diff --git a/src/defaultfile.cpp b/src/defaultfile.cpp index 4e641ea..df328ec 100644 --- a/src/defaultfile.cpp +++ b/src/defaultfile.cpp @@ -59,36 +59,46 @@ bool hasCommand(std::string command) { std::to_string(__LINE__) + " is not implemented "}; } -} // namespace +} std::string getHighestClang() { - if (getOs() == Os::Windows) { - return "clang++.exe"; - } - - for (size_t i = 20; i > 2; --i) { - auto command = "clang++-" + std::to_string(i); - if (hasCommand(command)) { - return command; - } - } - - return "clang++"; + if (getOs() == Os::Windows) { + return "clang++.exe"; + } + + for (size_t i = 20; i > 2; --i) { + auto command = "clang++-" + std::to_string(i); + if (hasCommand(command)) { + return command; + } + } + + return "clang++"; } std::string getHighestGcc() { - if (getOs() == Os::Windows) { - return "g++.exe"; - } - - for (size_t i = 20; i > 2; --i) { - auto command = "g++-" + std::to_string(i); - if (hasCommand(command)) { - return command; - } - } - - return "g++"; + if (getOs() == Os::Windows) { + return "g++.exe"; + } + + for (size_t i = 20; i > 2; --i) { + auto command = "g++-" + std::to_string(i); + if (hasCommand(command)) { + return command; + } + } + + return "g++"; +} + +void normalize(Json &json) { +#ifdef MATMAKE_USING_WINDOWS + for (auto &c : json.value) { + if (c == '/') { + c = '\\'; + } + } +#endif } } // namespace diff --git a/src/filesystem.h b/src/filesystem.h index 8513555..b9a3ad8 100644 --- a/src/filesystem.h +++ b/src/filesystem.h @@ -1,5 +1,7 @@ #pragma once +#include "os.h" + #ifdef USE_EXPERIMENTAL_FILESYSTEM // Se below @@ -27,7 +29,8 @@ namespace filesystem = std::experimental::filesystem; //! Compatabilityt function, that only removes the first part of a path, //! It is enough for the usecases of this project though -inline filesystem::path compat_relative(filesystem::path path, filesystem::path base) { +inline filesystem::path compat_relative(filesystem::path path, + filesystem::path base) { return path.string().substr(base.string().size()); } @@ -39,3 +42,26 @@ inline filesystem::path compat_relative(filesystem::path path, } #endif + +#ifdef MATMAKE_USING_WINDOWS + +filesystem::path normalizePath(std::string path) { + for (auto &c : path) { + if (c == '/') { + c = '\\'; + } + } + return filesystem::path{path}; +} + +filesystem::path normalizePath(filesystem::path path) { + return normalizePath(path.string()); +} + +#else + +filesystem::path normalizePath(filesystem::path path) { + return path; +} + +#endif diff --git a/src/nativecommands.cpp b/src/nativecommands.cpp index efbae46..3e7afad 100644 --- a/src/nativecommands.cpp +++ b/src/nativecommands.cpp @@ -48,9 +48,12 @@ native::CommandStatus native::copy(const Task &task) { std::cout << (in.string() + " --> " + out.string()) << std::endl; +#ifndef MATMAKE_USING_WINDOWS + // This causes a crash on msvc.. if (filesystem::equivalent(in, out)) { return CommandStatus::Normal; } +#endif filesystem::copy(in, out, filesystem::copy_options::overwrite_existing, ec); diff --git a/src/property.h b/src/property.h index 4363bfa..b08b27a 100644 --- a/src/property.h +++ b/src/property.h @@ -2,6 +2,7 @@ #include "task.h" #include "json/json.h" +#include #include struct Property { @@ -42,6 +43,12 @@ struct Property { return values.front(); } + //! Convert to a filesystem path with the right separater type + filesystem::path path() const { + auto value = this->value(); + return normalizePath(value); + } + std::string concat() const { if (values.empty()) { return {}; From 8812f08739ad68ea584e1554c664404dd8ec1f29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Lasersk=C3=B6ld?= Date: Sun, 21 Mar 2021 20:00:25 +0100 Subject: [PATCH 6/6] fix build errors --- src/filesystem.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/filesystem.h b/src/filesystem.h index b9a3ad8..c178c95 100644 --- a/src/filesystem.h +++ b/src/filesystem.h @@ -45,7 +45,7 @@ inline filesystem::path compat_relative(filesystem::path path, #ifdef MATMAKE_USING_WINDOWS -filesystem::path normalizePath(std::string path) { +inline filesystem::path normalizePath(std::string path) { for (auto &c : path) { if (c == '/') { c = '\\'; @@ -54,13 +54,17 @@ filesystem::path normalizePath(std::string path) { return filesystem::path{path}; } -filesystem::path normalizePath(filesystem::path path) { +inline filesystem::path normalizePath(filesystem::path path) { return normalizePath(path.string()); } #else -filesystem::path normalizePath(filesystem::path path) { +inline filesystem::path normalizePath(std::string path) { + return filesystem::path{path}; +} + +inline filesystem::path normalizePath(filesystem::path path) { return path; }