aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2017-12-30 05:33:25 +0100
committerdec05eba <dec05eba@protonmail.com>2017-12-30 05:33:25 +0100
commit7c215c39d530f01235043a131d64d4c7f766e9ab (patch)
treed72effe043a46566e34276525081637cad1bb7a0
parentabab2184ade33097f3441f8cdd95dd27c5653930 (diff)
parent98ad7dd049a366e21d60a34548736a3c8ef72877 (diff)
Merge release_0.1.0 to master
Add support for windows
-rw-r--r--backend/ninja/Ninja.cpp317
-rw-r--r--backend/ninja/Ninja.hpp4
-rw-r--r--include/Archive.hpp3
-rw-r--r--include/Conf.hpp27
-rw-r--r--include/Exec.hpp3
-rw-r--r--include/FileUtil.hpp44
-rw-r--r--include/GlobalLib.hpp4
-rw-r--r--include/PkgConfig.hpp5
-rw-r--r--include/curl.hpp3
-rw-r--r--include/env.hpp28
-rw-r--r--src/Archive.cpp38
-rw-r--r--src/Conf.cpp16
-rw-r--r--src/Exec.cpp49
-rw-r--r--src/FileUtil.cpp246
-rw-r--r--src/GlobalLib.cpp157
-rw-r--r--src/PkgConfig.cpp4
-rw-r--r--src/curl.cpp21
-rw-r--r--src/main.cpp160
18 files changed, 857 insertions, 272 deletions
diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp
index d9b4eed..49bda4f 100644
--- a/backend/ninja/Ninja.cpp
+++ b/backend/ninja/Ninja.cpp
@@ -8,6 +8,12 @@
using namespace std;
using namespace sibs;
+#if OS_FAMILY == OS_FAMILY_POSIX
+#define nprintf printf
+#else
+#define nprintf wprintf
+#endif
+
namespace backend
{
string join(const vector<string> &list, const char *joinStr)
@@ -38,7 +44,7 @@ namespace backend
return result;
}
-
+
bool endsWith(const string &str, const string &endWithStr)
{
if(endWithStr.size() > str.size())
@@ -46,7 +52,7 @@ namespace backend
else
return strncmp(&str[str.size() - endWithStr.size()], &endWithStr[0], endWithStr.size()) == 0;
}
-
+
Ninja::LibraryType getNinjaLibraryType(PackageType packageType)
{
switch(packageType)
@@ -61,6 +67,78 @@ namespace backend
}
}
+ string getIncludeOptionFlag(Compiler compiler, const string &filepath)
+ {
+ string result;
+ switch (compiler)
+ {
+ case Compiler::GCC:
+ {
+ result = "'-I";
+ result += filepath;
+ result += "'";
+ break;
+ }
+ case Compiler::MSVC:
+ {
+ result = "/I \"";
+ result += filepath;
+ result += "\"";
+ break;
+ }
+ }
+ return result;
+ }
+
+ string getCompileWithoutLinkingFlag(Compiler compiler)
+ {
+ string result;
+ switch (compiler)
+ {
+ case Compiler::GCC:
+ {
+ result = "-c";
+ break;
+ }
+ case Compiler::MSVC:
+ {
+ result = "/c";
+ break;
+ }
+ }
+ return result;
+ }
+
+ string getObjectFileNameFlag(Compiler compiler, const string &objectFileName)
+ {
+ string result;
+ switch (compiler)
+ {
+ case Compiler::GCC:
+ {
+ result = "-o ";
+ result += objectFileName;
+ break;
+ }
+ case Compiler::MSVC:
+ {
+ result = "/Fo";
+ result += objectFileName;
+ break;
+ }
+ }
+ return result;
+ }
+
+ const char* getObjectFileExtension(Compiler compiler)
+ {
+ switch (compiler)
+ {
+ case Compiler::GCC: return ".o";
+ case Compiler::MSVC: return ".obj";
+ }
+ }
+
Ninja::Ninja()
{
@@ -127,6 +205,7 @@ namespace backend
return false;
}
+#if OS_FAMILY == OS_FAMILY_POSIX
Result<bool> validatePkgConfigPackageVersionExists(const Dependency &dependency)
{
Result<bool> dependencyValidationResult = PkgConfig::validatePackageExists(dependency.name);
@@ -139,7 +218,7 @@ namespace backend
return Result<bool>::Ok(true);
}
-
+#endif
// TODO: First check if pkg-config is installed. If it's not, only check dependencies that exists in the dependencies sub directory.
// If pkg-config is installed and dependency is not installed, check in dependencies sub directory.
Result<bool> Ninja::getLinkerFlags(const SibsConfig &config, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback) const
@@ -147,14 +226,18 @@ namespace backend
const vector<Dependency> &dependencies = config.getDependencies();
if(dependencies.empty()) return Result<bool>::Ok(true);
- string globalLibDir = getHomeDir();
- globalLibDir += "/.sibs/lib";
+ Result<FileString> globalLibDirResult = getHomeDir();
+ if (!globalLibDirResult)
+ return Result<bool>::Err(globalLibDirResult);
+ FileString globalLibDir = globalLibDirResult.unwrap();
+ globalLibDir += TINYDIR_STRING("/.sibs/lib");
Result<bool> createGlobalLibDirResult = createDirectoryRecursive(globalLibDir.c_str());
if(createGlobalLibDirResult.isErr())
return createGlobalLibDirResult;
- vector<Dependency> pkgConfigDependencies;
vector<Dependency> globalLibDependencies;
+#if OS_FAMILY == OS_FAMILY_POSIX
+ vector<Dependency> pkgConfigDependencies;
for(const Dependency &dependency : dependencies)
{
Result<bool> pkgConfigDependencyValidation = validatePkgConfigPackageVersionExists(dependency);
@@ -169,11 +252,11 @@ namespace backend
}
Result<string> pkgConfigLinkerFlagsResult = PkgConfig::getDynamicLibsLinkerFlags(pkgConfigDependencies);
- if(pkgConfigLinkerFlagsResult.isErr())
+ if (pkgConfigLinkerFlagsResult.isErr())
{
printf("%s, using global lib...\n", pkgConfigLinkerFlagsResult.getErrMsg().c_str());
globalLibDependencies.reserve(globalLibDependencies.size() + pkgConfigDependencies.size());
- for(const Dependency &pkgConfigDependency : pkgConfigDependencies)
+ for (const Dependency &pkgConfigDependency : pkgConfigDependencies)
{
globalLibDependencies.push_back(pkgConfigDependency);
}
@@ -181,9 +264,15 @@ namespace backend
}
else
{
- if(!pkgConfigLinkerFlagsResult.unwrap().empty())
+ if (!pkgConfigLinkerFlagsResult.unwrap().empty())
dynamicLinkerFlagCallback(pkgConfigLinkerFlagsResult.unwrap());
}
+#else
+ for (const Dependency &dependency : dependencies)
+ {
+ globalLibDependencies.push_back(dependency);
+ }
+#endif
for(const Dependency &globalLibDependency : globalLibDependencies)
{
@@ -221,7 +310,7 @@ namespace backend
return Result<bool>::Ok(true);
}
- Result<bool> Ninja::build(const SibsConfig &config, const char *savePath, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback)
+ Result<bool> Ninja::build(const SibsConfig &config, const _tinydir_char_t *savePath, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback)
{
// TODO: Do not quit here if no source files are provided. The source-less project could have dependencies
if(sourceFiles.empty())
@@ -230,29 +319,35 @@ namespace backend
Result<bool> createBuildDirResult = createDirectoryRecursive(savePath);
if(createBuildDirResult.isErr())
return createBuildDirResult;
-
+
LibraryType libraryType = getNinjaLibraryType(config.getPackageType());
- string ninjaBuildFilePath = savePath;
- ninjaBuildFilePath += "/build.ninja";
+ string savePathUtf8 = toUtf8(savePath);
+
+ FileString ninjaBuildFilePath = savePath;
+ ninjaBuildFilePath += TINYDIR_STRING("/build.ninja");
string result;
result.reserve(16384);
- string globalIncDir = getHomeDir();
- globalIncDir += "/.sibs/lib";
+ Result<FileString> globalIncDirResult = getHomeDir();
+ if (!globalIncDirResult)
+ return Result<bool>::Err(globalIncDirResult);
- result += "globalIncDir = '-I";
- result += globalIncDir;
- result += "'";
+ FileString globalIncDir = globalIncDirResult.unwrap();
+ globalIncDir += TINYDIR_STRING("/.sibs/lib");
+
+ result += "globalIncDir = ";
+ result += getIncludeOptionFlag(config.getCompiler(), toUtf8(globalIncDir));
for(const auto &includeDir : config.getIncludeDirs())
{
- result += " '-I../../";
- result += includeDir;
- result += "'";
+ string includeDirRelative = "../../";
+ includeDirRelative += includeDir;
+ result += " ";
+ result += getIncludeOptionFlag(config.getCompiler(), includeDirRelative);
}
result += "\n\n";
-
+
string defines;
for(const auto &definePair : config.getDefines())
{
@@ -262,25 +357,54 @@ namespace backend
defines += definePair.second;
defines += "'";
}
-
+
if(!defines.empty())
printf("Custom define: %s\n", defines.c_str());
+ string compilerName;
+ switch (config.getCompiler())
+ {
+ case Compiler::GCC:
+ compilerName = "ccache c++";
+ break;
+ case Compiler::MSVC:
+ compilerName = "cl.exe";
+ break;
+ }
+
string buildJob;
switch(libraryType)
{
case LibraryType::EXECUTABLE:
{
- result += "rule cpp_COMPILER\n";
- result += " command = ccache c++ $ARGS -c $in -o $out\n\n";
+ switch (config.getCompiler())
+ {
+ case Compiler::GCC:
+ {
+ result += "rule cpp_COMPILER\n";
+ result += " command = ccache c++ $ARGS -c $in -o $out\n\n";
+
+ result += "rule cpp_BUILD_EXEC\n";
+ result += " command = ccache c++ $ARGS -o $out $in $LINK_ARGS $aliasing\n\n";
+ break;
+ }
+ case Compiler::MSVC:
+ {
+ result += "rule cpp_COMPILER\n";
+ result += " command = cl.exe $ARGS /c $in /Fo$out\n\n";
+
+ result += "rule cpp_BUILD_EXEC\n";
+ result += " command = cl.exe $ARGS $in /Fe$out $LINK_ARGS\n\n";
+ break;
+ }
+ }
- result += "rule cpp_BUILD_EXEC\n";
- result += " command = ccache c++ $ARGS -o $out $in $LINK_ARGS $aliasing\n\n";
buildJob = "cpp_BUILD_EXEC";
break;
}
case LibraryType::STATIC:
{
+ // TODO: Write equivalent code for msvc
result += "rule cpp_COMPILER\n";
result += " command = ccache c++ $ARGS -c -fPIC $in -o $out\n\n";
@@ -294,12 +418,32 @@ namespace backend
}
case LibraryType::DYNAMIC:
{
- result += "rule cpp_COMPILER\n";
- result += " command = ccache c++ $ARGS -c -fPIC $in -o $out\n\n";
+ switch (config.getCompiler())
+ {
+ case Compiler::GCC:
+ {
+ result += "rule cpp_COMPILER\n";
+ result += " command = ccache c++ $ARGS -c -fPIC $in -o $out\n\n";
+
+ // --whole-archive
+ result += "rule cpp_BUILD_DYNAMIC\n";
+ result += " command = ccache c++ $in -shared -o $out $LINK_ARGS $aliasing\n\n";
+ break;
+ }
+ case Compiler::MSVC:
+ {
+ result += "rule cpp_COMPILER\n";
+ result += " command = cl.exe $ARGS /c $in /Fo$out\n\n";
+
+ //result += "rule cpp_BUILD_DYNAMIC\n";
+ //result += " command = cl.exe /LD $in /Fe$out $LINK_ARGS\n\n";
+
+ result += "rule cpp_BUILD_DYNAMIC\n";
+ result += " command = lib.exe /OUT:$out $in\n\n";
+ break;
+ }
+ }
- // --whole-archive
- result += "rule cpp_BUILD_DYNAMIC\n";
- result += " command = ccache c++ $in -shared -o $out $LINK_ARGS $aliasing\n\n";
buildJob = "cpp_BUILD_DYNAMIC";
break;
}
@@ -328,21 +472,28 @@ namespace backend
sourceFileLanguage = "c";
//string sourceFileEncoded = sourceFile;
//replace(sourceFileEncoded, '/', '@');
- string objectName = config.getPackageName() + "@exe/" + sourceFile + ".o";
+ string objectName = config.getPackageName() + "@exe/" + sourceFile;
+ objectName += getObjectFileExtension(config.getCompiler());
result += "build ";
result += objectName;
result += ": cpp_COMPILER ../../";
result += sourceFile;
result += "\n";
- result += " ARGS = $globalIncDir '-I" + config.getPackageName() + "@exe' '-I..' ";
+ result += " ARGS = $globalIncDir ";
if(!defines.empty())
result += defines;
- result += " '-fdiagnostics-color=always' '-pipe' '-D_FILE_OFFSET_BITS=64' '-Wall' '-Winvalid-pch' '-Wnon-virtual-dtor' " + optimizationFlags + " '-g'\n\n";
+ if(config.getCompiler() != Compiler::MSVC)
+ result += " '-I" + config.getPackageName() + "@exe' '-I..' '-fdiagnostics-color=always' '-pipe' '-D_FILE_OFFSET_BITS=64' '-Wall' '-Winvalid-pch' '-Wnon-virtual-dtor' " + optimizationFlags + " '-g'";
+ result += "\n\n";
objectNames.emplace_back(objectName);
}
+#if OS_TYPE == OS_TYPE_LINUX
// TODO: Allow configuring default linking flags. Maybe have `package.useThreads = false` to disable this flag
string allLinkerFlags = "-pthread";
+#else
+ string allLinkerFlags = "";
+#endif
// TODO: Somehow check loading order, because it has to be correct to work.. Or does it for dynamic libraries?
// Anyways it's required for static libraries (especially on Windows)
@@ -374,7 +525,7 @@ namespace backend
string projectGeneratedBinary = allLinkerFlags;
projectGeneratedBinary += " '";
- projectGeneratedBinary += savePath;
+ projectGeneratedBinary += savePathUtf8;
projectGeneratedBinary += "/";
switch(libraryType)
{
@@ -385,7 +536,20 @@ namespace backend
result += ": " + buildJob + " ";
result += join(objectNames, " ");
result += "\n";
- result += " LINK_ARGS = '-Wl,--no-undefined,--as-needed' ";
+ switch (config.getCompiler())
+ {
+ case Compiler::GCC:
+ {
+ result += " LINK_ARGS = '-Wl,--no-undefined,--as-needed' ";
+ break;
+ }
+ case Compiler::MSVC:
+ {
+ result += " LINK_ARGS = ";
+ break;
+ }
+ }
+
if(!allLinkerFlags.empty())
{
result += allLinkerFlags;
@@ -401,24 +565,56 @@ namespace backend
result += ": " + buildJob + " ";
result += join(objectNames, " ");
result += "\n\n";
- projectGeneratedBinary += config.getPackageName() + ".a";
+
+ switch (config.getCompiler())
+ {
+ case Compiler::GCC:
+ {
+ projectGeneratedBinary += config.getPackageName() + ".a";
+ break;
+ }
+ case Compiler::MSVC:
+ {
+ projectGeneratedBinary += config.getPackageName() + ".lib";
+ break;
+ }
+ }
break;
}
case LibraryType::DYNAMIC:
{
- result += "build lib";
- result += config.getPackageName();
- result += ".so: " + buildJob + " ";
- result += join(objectNames, " ");
- result += "\n";
- result += " LINK_ARGS = '-Wl,--no-undefined,--as-needed' ";
+ switch (config.getCompiler())
+ {
+ case Compiler::GCC:
+ {
+ result += "build lib";
+ result += config.getPackageName();
+ result += ".so: " + buildJob + " ";
+ result += join(objectNames, " ");
+ result += "\n";
+ result += " LINK_ARGS = '-Wl,--no-undefined,--as-needed' ";
+ projectGeneratedBinary += "lib" + config.getPackageName() + ".so";
+ break;
+ }
+ case Compiler::MSVC:
+ {
+ result += "build ";
+ result += config.getPackageName();
+ result += ".lib: " + buildJob + " ";
+ result += join(objectNames, " ");
+ result += "\n";
+ result += " LINK_ARGS = ";
+ projectGeneratedBinary += config.getPackageName() + ".lib";
+ break;
+ }
+ }
+
if(!allLinkerFlags.empty())
{
result += allLinkerFlags;
//result += " '-Wl,--no-whole-archive'";
}
result += "\n\n";
- projectGeneratedBinary += "lib" + config.getPackageName() + ".so";
break;
}
default:
@@ -431,7 +627,7 @@ namespace backend
if(fileOverwriteResult.isErr())
return fileOverwriteResult;
- printf("Created ninja build file: %s\n", ninjaBuildFilePath.c_str());
+ nprintf(TINYDIR_STRING("Created ninja build file: %s\n"), ninjaBuildFilePath.c_str());
Result<bool> buildResult = build(savePath);
if(!buildResult)
@@ -444,13 +640,13 @@ namespace backend
return Result<bool>::Ok(true);
}
- const char *sourceFileExtensions[] = { "c", "cc", "cpp", "cxx" };
+ const _tinydir_char_t *sourceFileExtensions[] = { TINYDIR_STRING("c"), TINYDIR_STRING("cc"), TINYDIR_STRING("cpp"), TINYDIR_STRING("cxx") };
bool isSourceFile(tinydir_file *file)
{
if(!file->is_reg)
return false;
- for(const char *sourceFileExtension : sourceFileExtensions)
+ for(const _tinydir_char_t *sourceFileExtension : sourceFileExtensions)
{
if(_tinydir_strcmp(sourceFileExtension, file->extension) == 0)
return true;
@@ -480,11 +676,17 @@ namespace backend
for(const string &testSourceDir : testSourceDirs)
{
- string projectConfFilePath = testSourceDir;
- projectConfFilePath += "/project.conf";
+#if OS_FAMILY == OS_FAMILY_POSIX
+ FileString testSourceDirNative = testSourceDir;
+ FileString projectConfFilePath = testSourceDir;
+#else
+ FileString testSourceDirNative = utf8To16(testSourceDir);
+ FileString projectConfFilePath = testSourceDirNative;
+#endif
+ projectConfFilePath += TINYDIR_STRING("/project.conf");
FileType projectConfFileType = getFileType(projectConfFilePath.c_str());
- SibsTestConfig sibsTestConfig(testSourceDir);
+ SibsTestConfig sibsTestConfig(config.getCompiler(), testSourceDirNative);
if(projectConfFileType == FileType::REGULAR)
{
Result<bool> result = Config::readFromFile(projectConfFilePath.c_str(), sibsTestConfig);
@@ -494,11 +696,12 @@ namespace backend
backend::Ninja ninja;
ninja.addDependency(projectGeneratedBinary);
- walkDirFilesRecursive(testSourceDir.c_str(), [&ninja, &sibsTestConfig](tinydir_file *file)
+ walkDirFilesRecursive(testSourceDirNative.c_str(), [&ninja, &sibsTestConfig](tinydir_file *file)
{
if (isSourceFile(file))
{
- ninja.addSourceFile(file->path + sibsTestConfig.getProjectPath().size() + 1);
+ string filePathUtf8 = toUtf8(file->path + sibsTestConfig.getProjectPath().size() + 1);
+ ninja.addSourceFile(filePathUtf8.c_str());
}
else
{
@@ -508,7 +711,7 @@ namespace backend
if(!ninja.getSourceFiles().empty())
{
- string debugBuildPath = testSourceDir + "/sibs-build/debug";
+ FileString debugBuildPath = testSourceDirNative + TINYDIR_STRING("/sibs-build/debug");
Result<bool> buildFileResult = ninja.build(sibsTestConfig, debugBuildPath.c_str());
if (!buildFileResult)
return buildFileResult;
@@ -522,11 +725,11 @@ namespace backend
return Result<bool>::Ok(true);
}
- Result<bool> Ninja::build(const char *buildFilePath)
+ Result<bool> Ninja::build(const _tinydir_char_t *buildFilePath)
{
- string command = "ninja -C '";
+ FileString command = TINYDIR_STRING("ninja -C \"");
command += buildFilePath;
- command += "'";
+ command += TINYDIR_STRING("\"");
Result<ExecResult> execResult = exec(command.c_str(), true);
if(execResult.isOk())
{
diff --git a/backend/ninja/Ninja.hpp b/backend/ninja/Ninja.hpp
index 17649aa..36a57ff 100644
--- a/backend/ninja/Ninja.hpp
+++ b/backend/ninja/Ninja.hpp
@@ -28,14 +28,14 @@ namespace backend
void addTestSourceDir(const char *dir);
void addDependency(const std::string &binaryFile);
const std::vector<std::string>& getSourceFiles() const;
- sibs::Result<bool> build(const sibs::SibsConfig &config, const char *savePath, sibs::LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc = nullptr, sibs::LinkerFlagCallbackFunc dynamicLinkerFlagCallback = nullptr);
+ sibs::Result<bool> build(const sibs::SibsConfig &config, const _tinydir_char_t *savePath, sibs::LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc = nullptr, sibs::LinkerFlagCallbackFunc dynamicLinkerFlagCallback = nullptr);
private:
sibs::Result<bool> buildTests(const std::string &projectGeneratedBinary, const sibs::SibsConfig &config, const char *savePath);
bool containsSourceFile(const std::string &filepath) const;
bool containsTestSourceDir(const std::string &dir) const;
bool containsDependency(const std::string &dependency) const;
sibs::Result<bool> getLinkerFlags(const sibs::SibsConfig &config, sibs::LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, sibs::LinkerFlagCallbackFunc dynamicLinkerFlagCallback) const;
- sibs::Result<bool> build(const char *buildFilePath);
+ sibs::Result<bool> build(const _tinydir_char_t *buildFilePath);
private:
std::vector<std::string> sourceFiles;
std::vector<std::string> testSourceDirs;
diff --git a/include/Archive.hpp b/include/Archive.hpp
index 2545f77..10811ab 100644
--- a/include/Archive.hpp
+++ b/include/Archive.hpp
@@ -2,6 +2,7 @@
#define SIBS_ZLIB_HPP
#include "Result.hpp"
+#include "FileUtil.hpp"
namespace sibs
{
@@ -9,7 +10,7 @@ namespace sibs
{
public:
// Note: renames root directory in archive to @destination
- static Result<bool> extract(const char *source, const char *destination);
+ static Result<bool> extract(const _tinydir_char_t *source, const _tinydir_char_t *destination);
};
}
diff --git a/include/Conf.hpp b/include/Conf.hpp
index 5e3ed87..d147fca 100644
--- a/include/Conf.hpp
+++ b/include/Conf.hpp
@@ -1,6 +1,7 @@
#ifndef SIBS_CONF_HPP
#define SIBS_CONF_HPP
+#include "FileUtil.hpp"
#include "Result.hpp"
#include "StringView.hpp"
#include "utils.hpp"
@@ -82,7 +83,7 @@ namespace sibs
class Config
{
public:
- static Result<bool> readFromFile(const char *filepath, const ConfigCallback &callback);
+ static Result<bool> readFromFile(const _tinydir_char_t *filepath, const ConfigCallback &callback);
};
enum OptimizationLevel
@@ -92,14 +93,25 @@ namespace sibs
OPT_LEV_RELEASE
};
+ enum class Compiler
+ {
+ GCC,
+ MSVC
+ };
+
const char* asString(OptimizationLevel optLevel);
class SibsConfig : public ConfigCallback
{
public:
- SibsConfig(const std::string &_projectPath, OptimizationLevel _optimizationLevel = OPT_LEV_DEBUG) : projectPath(_projectPath), packageType((PackageType)-1), optimizationLevel(_optimizationLevel), finishedProcessing(false) {}
+ SibsConfig(Compiler _compiler, const FileString &_projectPath, OptimizationLevel _optimizationLevel = OPT_LEV_DEBUG) : compiler(_compiler), projectPath(_projectPath), packageType((PackageType)-1), optimizationLevel(_optimizationLevel), finishedProcessing(false) {}
virtual ~SibsConfig(){}
+ Compiler getCompiler() const
+ {
+ return compiler;
+ }
+
virtual const std::string& getPackageName() const
{
assert(finishedProcessing);
@@ -112,7 +124,7 @@ namespace sibs
return packageType;
}
- virtual const std::string& getTestPath() const
+ virtual const FileString& getTestPath() const
{
return testPath;
}
@@ -122,7 +134,7 @@ namespace sibs
return dependencies;
}
- virtual const std::string& getProjectPath() const
+ virtual const FileString& getProjectPath() const
{
return projectPath;
}
@@ -151,9 +163,10 @@ namespace sibs
virtual void finished() override;
protected:
StringView currentObject;
- std::string projectPath;
+ Compiler compiler;
+ FileString projectPath;
std::string packageName;
- std::string testPath;
+ FileString testPath;
PackageType packageType;
std::vector<Dependency> dependencies;
std::vector<std::string> includeDirs;
@@ -165,7 +178,7 @@ namespace sibs
class SibsTestConfig : public SibsConfig
{
public:
- SibsTestConfig(const std::string &_projectPath) : SibsConfig(_projectPath)
+ SibsTestConfig(Compiler _compiler, const FileString &_projectPath) : SibsConfig(_compiler, _projectPath)
{
packageName = "test";
}
diff --git a/include/Exec.hpp b/include/Exec.hpp
index 42b6905..9996073 100644
--- a/include/Exec.hpp
+++ b/include/Exec.hpp
@@ -2,6 +2,7 @@
#define SIBS_EXEC_HPP
#include "Result.hpp"
+#include "../include/FileUtil.hpp"
#include <string>
namespace sibs
@@ -12,7 +13,7 @@ namespace sibs
int exitCode;
};
- Result<ExecResult> exec(const char *cmd, bool print = false);
+ Result<ExecResult> exec(const _tinydir_char_t *cmd, bool print = false);
}
#endif //SIBS_EXEC_HPP
diff --git a/include/FileUtil.hpp b/include/FileUtil.hpp
index 5d1594a..89eaa84 100644
--- a/include/FileUtil.hpp
+++ b/include/FileUtil.hpp
@@ -1,13 +1,37 @@
#ifndef SIBS_FILEUTIL_HPP
#define SIBS_FILEUTIL_HPP
+#ifndef UNICODE
+#define UNICODE
+#endif
+
+#ifndef _UNICODE
+#define _UNICODE
+#endif
+
+#include "env.hpp"
#include "../external/tinydir.h"
+#include "../external/utf8/checked.h"
#include "Result.hpp"
#include "StringView.hpp"
#include <functional>
namespace sibs
{
+ using FileString = std::basic_string<_tinydir_char_t, std::char_traits<_tinydir_char_t>, std::allocator<_tinydir_char_t>>;
+
+#if OS_FAMILY == OS_FAMILY_POSIX
+#define toUtf8(input) input
+ FileString toFileString(const std::string &utf8Str);
+#else
+ std::string toUtf8(const sibs::FileString &input);
+ std::string toUtf8(const TCHAR *input);
+ FileString utf8To16(const StringView &utf8Str);
+ FileString utf8To16(const std::string &utf8Str);
+ FileString toFileString(const std::string &utf8Str);
+ FileString getLastErrorAsString();
+#endif
+
using FileWalkCallbackFunc = std::function<void(tinydir_file*)>;
enum class FileType
@@ -17,17 +41,17 @@ namespace sibs
DIRECTORY
};
- FileType getFileType(const char *path);
- void walkDir(const char *directory, FileWalkCallbackFunc callbackFunc);
- void walkDirFiles(const char *directory, FileWalkCallbackFunc callbackFunc);
- void walkDirFilesRecursive(const char *directory, FileWalkCallbackFunc callbackFunc);
- Result<StringView> getFileContent(const char *filepath);
- Result<bool> fileOverwrite(const char *filepath, StringView data);
- const char* getHomeDir();
- Result<std::string> getCwd();
+ FileType getFileType(const _tinydir_char_t *path);
+ void walkDir(const _tinydir_char_t *directory, FileWalkCallbackFunc callbackFunc);
+ void walkDirFiles(const _tinydir_char_t *directory, FileWalkCallbackFunc callbackFunc);
+ void walkDirFilesRecursive(const _tinydir_char_t *directory, FileWalkCallbackFunc callbackFunc);
+ Result<StringView> getFileContent(const _tinydir_char_t *filepath);
+ Result<bool> fileOverwrite(const _tinydir_char_t *filepath, StringView data);
+ Result<FileString> getHomeDir();
+ Result<FileString> getCwd();
// Note: Will not delete created directories if this operation fails for some reason
- Result<bool> createDirectoryRecursive(const char *path);
- Result<std::string> getRealPath(const char *path);
+ Result<bool> createDirectoryRecursive(const _tinydir_char_t *path);
+ Result<FileString> getRealPath(const _tinydir_char_t *path);
}
#endif //SIBS_FILEUTIL_HPP
diff --git a/include/GlobalLib.hpp b/include/GlobalLib.hpp
index c67027e..2f4b938 100644
--- a/include/GlobalLib.hpp
+++ b/include/GlobalLib.hpp
@@ -17,8 +17,8 @@ namespace sibs
DEPENDENCY_VERSION_NO_MATCH = 20
};
- static Result<bool> validatePackageExists(const std::string &globalLibRootDir, const std::string &name);
- static Result<std::string> getLibsLinkerFlags(const SibsConfig &parentConfig, const std::string &globalLibRootDir, const std::string &name, const std::string &version, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallbackFunc);
+ static Result<bool> validatePackageExists(const FileString &globalLibRootDir, const std::string &name);
+ static Result<std::string> getLibsLinkerFlags(const SibsConfig &parentConfig, const FileString &globalLibRootDir, const std::string &name, const std::string &version, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallbackFunc);
static Result<bool> downloadDependency(const Dependency &dependency);
};
}
diff --git a/include/PkgConfig.hpp b/include/PkgConfig.hpp
index 2af4ac9..da78b91 100644
--- a/include/PkgConfig.hpp
+++ b/include/PkgConfig.hpp
@@ -1,6 +1,8 @@
#ifndef SIBS_PKGCONFIG_HPP
#define SIBS_PKGCONFIG_HPP
+#include "env.hpp"
+#if OS_FAMILY == OS_FAMILY_POSIX
#include "Result.hpp"
#include "Dependency.hpp"
#include <string>
@@ -16,5 +18,6 @@ namespace sibs
static Result<std::string> getDynamicLibsLinkerFlags(const std::vector<Dependency> &libs);
};
}
+#endif // OS_FAMILY_POSIX
-#endif //SIBS_PKGCONFIG_HPP
+#endif // SIBS_PKGCONFIG_HPP
diff --git a/include/curl.hpp b/include/curl.hpp
index 7c0ddbe..16b3e52 100644
--- a/include/curl.hpp
+++ b/include/curl.hpp
@@ -2,6 +2,7 @@
#define SIBS_CURL_HPP
#include "Result.hpp"
+#include "FileUtil.hpp"
#include <string>
namespace sibs
@@ -17,7 +18,7 @@ namespace sibs
class curl
{
public:
- static sibs::Result<bool> downloadFile(const char *url, const char *filepath);
+ static sibs::Result<bool> downloadFile(const char *url, const _tinydir_char_t *filepath);
static HttpResult get(const char *url);
};
}
diff --git a/include/env.hpp b/include/env.hpp
index f5b1213..51ee2bd 100644
--- a/include/env.hpp
+++ b/include/env.hpp
@@ -4,6 +4,9 @@
#define OS_FAMILY_WINDOWS 0
#define OS_FAMILY_POSIX 1
+#define OS_TYPE_WINDOWS 0
+#define OS_TYPE_LINUX 1
+
#if defined(_WIN32) || defined(_WIN64)
#if defined(_WIN64)
#define CISB_ENV_64BIT
@@ -11,12 +14,31 @@
#define CISB_ENV_32BIT
#endif
#define OS_FAMILY OS_FAMILY_WINDOWS
+ #define OS_TYPE OS_TYPE_WINDOWS
+
+ #ifndef UNICODE
+ #define UNICODE
+ #endif
+
+ #ifndef _UNICODE
+ #define _UNICODE
+ #endif
+
+ #ifndef WIN32_LEAN_AND_MEAN
+ #define WIN32_LEAN_AND_MEAN
+ #endif
+
+ #include <Windows.h>
#endif
#if defined(__linux__) || defined(__unix__) || defined(__APPLE__) || defined(_POSIX_VERSION)
#define OS_FAMILY OS_FAMILY_POSIX
#endif
+#ifdef __linux__
+ #define OS_TYPE OS_TYPE_LINUX
+#endif
+
#if defined(__GNUC__)
#if defined(__x86_64__) || defined(__pc64__)
#define CISB_ENV_64BIT
@@ -30,7 +52,11 @@
#endif
#if !defined(OS_FAMILY)
- #error "System not support. Only Windows and Posix systems support"
+ #error "System not supported. Only Windows and Posix systems supported right now"
+#endif
+
+#if !defined(OS_TYPE)
+ #error "System not supported. Only Windows and linux systems supported right now"
#endif
#if !defined(DEBUG) && !defined(NDEBUG)
diff --git a/src/Archive.cpp b/src/Archive.cpp
index 08ab42b..506b020 100644
--- a/src/Archive.cpp
+++ b/src/Archive.cpp
@@ -6,6 +6,14 @@
using namespace std;
+#if OS_FAMILY == OS_FAMILY_POSIX
+#define archive_read_open_filename_native archive_read_open_filename
+#define archive_entry_pathname_native archive_entry_pathname
+#else
+#define archive_read_open_filename_native archive_read_open_filename_w
+#define archive_entry_pathname_native archive_entry_pathname_w
+#endif
+
class FileHandler
{
DISABLE_COPY(FileHandler)
@@ -53,7 +61,7 @@ namespace sibs
}
}
- Result<bool> Archive::extract(const char *source, const char *destination)
+ Result<bool> Archive::extract(const _tinydir_char_t *source, const _tinydir_char_t *destination)
{
struct archive *a;
struct archive *ext;
@@ -67,7 +75,7 @@ namespace sibs
flags |= ARCHIVE_EXTRACT_ACL;
flags |= ARCHIVE_EXTRACT_FFLAGS;
- string rootName;
+ FileString rootName;
a = archive_read_new();
archive_read_support_format_all(a);
@@ -77,10 +85,10 @@ namespace sibs
archive_write_disk_set_standard_lookup(ext);
- if ((r = archive_read_open_filename(a, source, 10240)))
+ if ((r = archive_read_open_filename_native(a, source, 10240)))
{
string errMsg = "Failed to extract archive: ";
- errMsg += source;
+ errMsg += toUtf8(source);
return Result<bool>::Err(errMsg);
}
@@ -92,7 +100,7 @@ namespace sibs
else if (r < ARCHIVE_OK)
{
string errMsg = "Failed to extract archive: ";
- errMsg += source;
+ errMsg += toUtf8(source);
errMsg += "; reason: ";
errMsg += archive_error_string(a);
return Result<bool>::Err(errMsg);
@@ -100,25 +108,27 @@ namespace sibs
else if (r < ARCHIVE_WARN)
{
string errMsg = "Failed to extract archive: ";
- errMsg += source;
+ errMsg += toUtf8(source);
errMsg += "; reason: ";
errMsg += archive_error_string(a);
return Result<bool>::Err(errMsg);
}
- const char* currentFile = archive_entry_pathname(entry);
+ const _tinydir_char_t* currentFile = archive_entry_pathname_native(entry);
if(rootName.empty())
rootName = currentFile;
- std::string fullOutputPath = destination;
+ FileString fullOutputPath = destination;
fullOutputPath += (currentFile + (rootName.empty() ? 0 : rootName.size() - 1));
- archive_entry_set_pathname(entry, fullOutputPath.c_str());
+ // TODO: Verify if this really works. Why doesn't libarchive have wide string version of archive_entry_set_pathname?
+ string fullOutputPathUtf8 = toUtf8(fullOutputPath);
+ archive_entry_set_pathname(entry, fullOutputPathUtf8.c_str());
r = archive_write_header(ext, entry);
if (r < ARCHIVE_OK)
{
string errMsg = "Failed to extract archive: ";
- errMsg += source;
+ errMsg += toUtf8(source);
errMsg += "; reason: ";
errMsg += archive_error_string(ext);
return Result<bool>::Err(errMsg);
@@ -128,7 +138,7 @@ namespace sibs
if (r < ARCHIVE_OK)
{
string errMsg = "Failed to extract archive: ";
- errMsg += source;
+ errMsg += toUtf8(source);
errMsg += "; reason: ";
errMsg += archive_error_string(ext);
return Result<bool>::Err(errMsg);
@@ -136,7 +146,7 @@ namespace sibs
else if (r < ARCHIVE_WARN)
{
string errMsg = "Failed to extract archive: ";
- errMsg += source;
+ errMsg += toUtf8(source);
errMsg += "; reason: ";
errMsg += archive_error_string(ext);
return Result<bool>::Err(errMsg);
@@ -147,7 +157,7 @@ namespace sibs
if (r < ARCHIVE_OK)
{
string errMsg = "Failed to extract archive: ";
- errMsg += source;
+ errMsg += toUtf8(source);
errMsg += "; reason: ";
errMsg += archive_error_string(ext);
return Result<bool>::Err(errMsg);
@@ -155,7 +165,7 @@ namespace sibs
else if (r < ARCHIVE_WARN)
{
string errMsg = "Failed to extract archive: ";
- errMsg += source;
+ errMsg += toUtf8(source);
errMsg += "; reason: ";
errMsg += archive_error_string(ext);
return Result<bool>::Err(errMsg);
diff --git a/src/Conf.cpp b/src/Conf.cpp
index 6d5834e..5282bb5 100644
--- a/src/Conf.cpp
+++ b/src/Conf.cpp
@@ -1,5 +1,5 @@
#include "../include/Conf.hpp"
-#include "../include/FileUtil.hpp"
+#include "../include/types.hpp"
#include "../external/utf8/unchecked.h"
using namespace std;
@@ -7,8 +7,6 @@ using u8string = utf8::unchecked::iterator<char*>;
namespace sibs
{
- u32 min(u32 a, u32 b) { return a < b ? a : b; }
-
class UnexpectedTokenException : public std::runtime_error
{
public:
@@ -316,7 +314,7 @@ namespace sibs
bool objectDefined;
};
- Result<bool> Config::readFromFile(const char *filepath, const ConfigCallback &callback)
+ Result<bool> Config::readFromFile(const _tinydir_char_t *filepath, const ConfigCallback &callback)
{
Result<StringView> fileContentResult = getFileContent(filepath);
if(fileContentResult.isErr())
@@ -430,9 +428,13 @@ namespace sibs
if (value.isSingle())
{
testPath = projectPath;
- testPath += "/";
- testPath += string(value.asSingle().data, value.asSingle().size);
- Result<string> testRealPathResult = getRealPath(testPath.c_str());
+ testPath += TINYDIR_STRING("/");
+#if OS_FAMILY == OS_FAMILY_POSIX
+ testPath += FileString(value.asSingle().data, value.asSingle().size);
+#else
+ testPath += utf8To16(value.asSingle());
+#endif
+ Result<FileString> testRealPathResult = getRealPath(testPath.c_str());
if(!testRealPathResult)
{
string errMsg = "Failed to resolve package.tests path: ";
diff --git a/src/Exec.cpp b/src/Exec.cpp
index 37ffef5..e0ae306 100644
--- a/src/Exec.cpp
+++ b/src/Exec.cpp
@@ -1,10 +1,12 @@
#include "../include/Exec.hpp"
+#include "../include/env.hpp"
using namespace std;
namespace sibs
{
- Result<ExecResult> exec(const char *cmd, bool print)
+#if OS_FAMILY == OS_FAMILY_POSIX
+ Result<ExecResult> exec(const _tinydir_char_t *cmd, bool print)
{
char buffer[128];
std::string result;
@@ -52,4 +54,49 @@ namespace sibs
return Result<ExecResult>::Err(errMsg);
}
}
+#else
+ // TODO(Windows): Redirect stdout (and stderr) to string
+ Result<ExecResult> exec(const _tinydir_char_t *cmd, bool print)
+ {
+ char buffer[128];
+ std::string result;
+
+ STARTUPINFO startupInfo;
+ ZeroMemory(&startupInfo, sizeof(startupInfo));
+ startupInfo.cb = sizeof(startupInfo);
+
+ PROCESS_INFORMATION processInfo;
+ ZeroMemory(&processInfo, sizeof(processInfo));
+
+ DWORD exitCode;
+
+ if (!CreateProcess(NULL, (LPWSTR)cmd, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo))
+ {
+ string errMsg = "exec unexpected error: ";
+ errMsg += toUtf8(getLastErrorAsString());
+ return Result<ExecResult>::Err(errMsg);
+ }
+
+ WaitForSingleObject(processInfo.hProcess, INFINITE);
+ GetExitCodeProcess(processInfo.hProcess, &exitCode);
+ CloseHandle(processInfo.hProcess);
+ CloseHandle(processInfo.hThread);
+
+ if (exitCode == 0)
+ {
+ ExecResult execResult;
+ execResult.execStdout = result;
+ execResult.exitCode = exitCode;
+ return Result<ExecResult>::Ok(execResult);
+ }
+ else
+ {
+ string errMsg = "Exited with non-zero exit code (";
+ errMsg += to_string(exitCode);
+ errMsg += "): ";
+ errMsg += toUtf8(getLastErrorAsString());
+ return Result<ExecResult>::Err(errMsg);
+ }
+ }
+#endif
} \ No newline at end of file
diff --git a/src/FileUtil.cpp b/src/FileUtil.cpp
index d075f2b..5cf8377 100644
--- a/src/FileUtil.cpp
+++ b/src/FileUtil.cpp
@@ -1,5 +1,4 @@
#include "../include/FileUtil.hpp"
-#include "../include/env.hpp"
#include <cstdio>
#if OS_FAMILY == OS_FAMILY_POSIX
@@ -7,27 +6,92 @@
#include <sys/types.h>
#include <pwd.h>
#include <fcntl.h>
+#else
+#include <UserEnv.h>
+// Copied from linux libc sys/stat.h:
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
using namespace std;
namespace sibs
{
- FileType getFileType(const char *path)
+#if OS_FAMILY == OS_FAMILY_POSIX
+#define toUtf8(input) input
+ FileString toFileString(const std::string &utf8Str)
{
- tinydir_file file;
- if(tinydir_file_open(&file, path) == 0)
- {
- return file.is_dir ? FileType::DIRECTORY : FileType::REGULAR;
- }
+ return utf8Str;
+ }
+#else
+ std::string toUtf8(const sibs::FileString &input)
+ {
+ std::string result;
+ utf8::utf16to8(input.data(), input.data() + input.size(), std::back_inserter(result));
+ return result;
+ }
+
+ std::string toUtf8(const TCHAR *input)
+ {
+ size_t inputSize = wcslen(input);
+ std::string result;
+ utf8::utf16to8(input, input + inputSize, std::back_inserter(result));
+ return result;
+ }
+
+ FileString utf8To16(const StringView &utf8Str)
+ {
+ FileString result;
+ utf8::utf8to16(utf8Str.data, utf8Str.data + utf8Str.size, std::back_inserter(result));
+ return result;
+ }
+
+ FileString utf8To16(const std::string &utf8Str)
+ {
+ FileString result;
+ utf8::utf8to16(utf8Str.data(), utf8Str.data() + utf8Str.size(), std::back_inserter(result));
+ return result;
+ }
+
+ FileString toFileString(const std::string &utf8Str)
+ {
+ return utf8To16(utf8Str);
+ }
+
+ FileString getLastErrorAsString()
+ {
+ DWORD errorMessageId = GetLastError();
+ if (errorMessageId == 0) return TINYDIR_STRING("");
+ LPWSTR messageBuffer = nullptr;
+ size_t size = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, errorMessageId, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, nullptr);
+ FileString message(messageBuffer, size);
+ LocalFree(messageBuffer);
+ return message;
+ }
+#endif
+
+#if OS_FAMILY == OS_FAMILY_POSIX
+ FileType getFileType(const _tinydir_char_t *path)
+ {
+ struct stat64 fileStat;
+ if (stat64(path, &fileStat) == 0)
+ return S_ISREG(fileStat.st_mode) ? FileType::REGULAR : FileType::DIRECTORY;
else
- {
return FileType::FILE_NOT_FOUND;
- }
}
+#else
+ FileType getFileType(const _tinydir_char_t *path)
+ {
+ struct _stat64i32 fileStat;
+ if (_wstat(path, &fileStat) == 0)
+ return S_ISREG(fileStat.st_mode) ? FileType::REGULAR : FileType::DIRECTORY;
+ else
+ return FileType::FILE_NOT_FOUND;
+ }
+#endif
// TODO: Handle failure (directory doesn't exist, no permission etc)
- void walkDir(const char *directory, FileWalkCallbackFunc callbackFunc)
+ void walkDir(const _tinydir_char_t *directory, FileWalkCallbackFunc callbackFunc)
{
tinydir_dir dir;
tinydir_open(&dir, directory);
@@ -36,7 +100,7 @@ namespace sibs
{
tinydir_file file;
tinydir_readfile(&dir, &file);
- if(_tinydir_strcmp(file.name, ".") != 0 && _tinydir_strcmp(file.name, "..") != 0)
+ if(_tinydir_strcmp(file.name, TINYDIR_STRING(".")) != 0 && _tinydir_strcmp(file.name, TINYDIR_STRING("..")) != 0)
callbackFunc(&file);
tinydir_next(&dir);
}
@@ -45,7 +109,7 @@ namespace sibs
}
// TODO: Handle failure (directory doesn't exist, no permission etc)
- void walkDirFiles(const char *directory, FileWalkCallbackFunc callbackFunc)
+ void walkDirFiles(const _tinydir_char_t *directory, FileWalkCallbackFunc callbackFunc)
{
tinydir_dir dir;
tinydir_open(&dir, directory);
@@ -63,7 +127,7 @@ namespace sibs
}
// TODO: Handle failure (directory doesn't exist, no permission etc)
- void walkDirFilesRecursive(const char *directory, FileWalkCallbackFunc callbackFunc)
+ void walkDirFilesRecursive(const _tinydir_char_t *directory, FileWalkCallbackFunc callbackFunc)
{
tinydir_dir dir;
tinydir_open(&dir, directory);
@@ -74,7 +138,7 @@ namespace sibs
tinydir_readfile(&dir, &file);
if(file.is_reg)
callbackFunc(&file);
- else if(_tinydir_strcmp(file.name, ".") != 0 && _tinydir_strcmp(file.name, "..") != 0)
+ else if(_tinydir_strcmp(file.name, TINYDIR_STRING(".")) != 0 && _tinydir_strcmp(file.name, TINYDIR_STRING("..")) != 0)
walkDirFilesRecursive(file.path, callbackFunc);
tinydir_next(&dir);
}
@@ -82,14 +146,18 @@ namespace sibs
tinydir_close(&dir);
}
- Result<StringView> getFileContent(const char *filepath)
+ Result<StringView> getFileContent(const _tinydir_char_t *filepath)
{
+#if OS_FAMILY == OS_FAMILY_POSIX
FILE *file = fopen(filepath, "rb");
+#else
+ FILE *file = _wfopen(filepath, TINYDIR_STRING("rb"));
+#endif
if(!file)
{
int error = errno;
string errMsg = "Failed to open file: ";
- errMsg += filepath;
+ errMsg += toUtf8(filepath);
errMsg += "; reason: ";
errMsg += strerror(error);
return Result<StringView>::Err(errMsg);
@@ -104,7 +172,7 @@ namespace sibs
if(!result)
{
std::string errMsg = "Failed to load file content from file: ";
- errMsg += filepath;
+ errMsg += toUtf8(filepath);
throw std::runtime_error(errMsg);
}
result[fileSize] = '\0';
@@ -113,14 +181,18 @@ namespace sibs
return Result<StringView>::Ok(StringView(result, fileSize));
}
- Result<bool> fileOverwrite(const char *filepath, StringView data)
+ Result<bool> fileOverwrite(const _tinydir_char_t *filepath, StringView data)
{
+#if OS_FAMILY == OS_FAMILY_POSIX
FILE *file = fopen(filepath, "wb");
+#else
+ FILE *file = _wfopen(filepath, TINYDIR_STRING("wb"));
+#endif
if(!file)
{
int error = errno;
string errMsg = "Failed to overwrite file: ";
- errMsg += filepath;
+ errMsg += toUtf8(filepath);
errMsg += "; reason: ";
errMsg += strerror(error);
return Result<bool>::Err(errMsg);
@@ -130,8 +202,8 @@ namespace sibs
fclose(file);
return Result<bool>::Ok(true);
}
-
- const char* getHomeDir()
+#if OS_FAMILY == OS_FAMILY_POSIX
+ Result<FileString> getHomeDir()
{
const char *homeDir = getenv("HOME");
if(!homeDir)
@@ -139,26 +211,25 @@ namespace sibs
passwd *pw = getpwuid(getuid());
homeDir = pw->pw_dir;
}
- return homeDir;
+ return Result<FileString>::Ok(homeDir);
}
- Result<string> getCwd()
+ Result<FileString> getCwd()
{
- string cwd;
- cwd.reserve(PATH_MAX);
- if(getcwd(&cwd[0], PATH_MAX) != 0)
+ FileString cwd;
+ cwd.resize(_TINYDIR_PATH_MAX);
+ if(getcwd(&cwd[0], _TINYDIR_PATH_MAX) != 0)
{
if(cwd.empty()) cwd = ".";
- return Result<string>::Ok(cwd);
+ cwd.resize(_tinydir_strlen(cwd.c_str()));
+ return Result<FileString>::Ok(cwd);
}
-
- return Result<string>::Err(strerror(errno));
+ return Result<FileString>::Err(strerror(errno));
}
-#if OS_FAMILY == OS_FAMILY_POSIX
- Result<bool> createDirectoryRecursive(const char *path)
+ Result<bool> createDirectoryRecursive(const _tinydir_char_t *path)
{
- char pathBuffer[PATH_MAX];
+ char pathBuffer[_TINYDIR_PATH_MAX];
size_t pathLength = strlen(path);
if(pathLength > sizeof(pathBuffer) - 1)
{
@@ -207,25 +278,126 @@ namespace sibs
return Result<bool>::Ok(true);
}
- Result<string> getRealPath(const char *path)
+ Result<FileString> getRealPath(const _tinydir_char_t *path)
{
// TODO: Verify NULL can be passed as 'resolved' argument with different compilers and operating systems (clang, freebsd etc)
char *resolved = realpath(path, nullptr);
if(!resolved)
{
int error = errno;
- string errMsg = "Failed to get real path for \"";
+ FileString errMsg = "Failed to get real path for \"";
errMsg += path;
errMsg += "\": ";
errMsg += strerror(error);
- return Result<string>::Err(errMsg, error);
+ return Result<FileString>::Err(errMsg, error);
}
string result = resolved;
free(resolved);
- return Result<string>::Ok(result);
+ return Result<FileString>::Ok(result);
}
#else
-#error "TODO: Implement createDirectoryRecursive and getRealPath on windows"
+
+#pragma comment(lib, "Userenv.lib")
+
+ Result<FileString> getHomeDir()
+ {
+ BOOL ret;
+ HANDLE hToken;
+ FileString homeDir;
+ DWORD homeDirLen = _TINYDIR_PATH_MAX;
+ homeDir.resize(homeDirLen);
+
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hToken))
+ return Result<FileString>::Err("Failed to open process token");
+
+ if (!GetUserProfileDirectory(hToken, &homeDir[0], &homeDirLen))
+ return Result<FileString>::Err("Failed to get home directory");
+
+ CloseHandle(hToken);
+ homeDir.resize(_tinydir_strlen(homeDir.c_str()));
+ return Result<FileString>::Ok(homeDir);
+ }
+
+ Result<FileString> getCwd()
+ {
+ FileString cwd;
+ cwd.resize(_TINYDIR_PATH_MAX);
+ if (GetCurrentDirectory(_TINYDIR_PATH_MAX, &cwd[0]) == 0)
+ {
+ FileString lastErrStr = getLastErrorAsString();
+ return Result<FileString>::Err(toUtf8(lastErrStr));
+ }
+ cwd.resize(_tinydir_strlen(cwd.c_str()));
+ return Result<FileString>::Ok(cwd);
+ }
+
+ Result<bool> createDirectoryRecursive(const _tinydir_char_t *path)
+ {
+ _tinydir_char_t pathBuffer[_TINYDIR_PATH_MAX];
+ size_t pathLength = _tinydir_strlen(path);
+ if (pathLength > sizeof(pathBuffer) - 1)
+ {
+ string errMsg = "Directory path too long: ";
+ errMsg += toUtf8(FileString(path, pathLength));
+ return Result<bool>::Err(errMsg, ENAMETOOLONG);
+ }
+ _tinydir_strcpy(pathBuffer, path);
+
+ _tinydir_char_t *p = pathBuffer;
+ for (size_t i = 0; i < pathLength; ++i)
+ {
+ if (i > 0 && *p == '/')
+ {
+ *p = '\0';
+ if (_wmkdir(pathBuffer) != 0)
+ {
+ int error = errno;
+ if (error != EEXIST)
+ {
+ string errMsg = "Failed to create directory: ";
+ errMsg += toUtf8(pathBuffer);
+ errMsg += "; reason: ";
+ errMsg += strerror(error);
+ return Result<bool>::Err(errMsg, error);
+ }
+ }
+ *p = '/';
+ }
+ ++p;
+ }
+
+ if (_wmkdir(pathBuffer) != 0)
+ {
+ int error = errno;
+ if (error != EEXIST)
+ {
+ string errMsg = "Failed to create directory: ";
+ errMsg += toUtf8(pathBuffer);
+ errMsg += "; reason: ";
+ errMsg += strerror(error);
+ return Result<bool>::Err(errMsg, error);
+ }
+ }
+
+ return Result<bool>::Ok(true);
+ }
+
+ Result<FileString> getRealPath(const _tinydir_char_t *path)
+ {
+ FileString fullPath;
+ fullPath.resize(_TINYDIR_PATH_MAX);
+ if (GetFullPathName(path, _TINYDIR_PATH_MAX, &fullPath[0], nullptr) == 0)
+ {
+ int error = GetLastError();
+ string errMsg = "Failed to get real path for \"";
+ errMsg += toUtf8(path);
+ errMsg += "\": ";
+ errMsg += toUtf8(getLastErrorAsString());
+ return Result<FileString>::Err(errMsg, error);
+ }
+ fullPath.resize(_tinydir_strlen(fullPath.c_str()));
+ return Result<FileString>::Ok(fullPath);
+ }
#endif
} \ No newline at end of file
diff --git a/src/GlobalLib.cpp b/src/GlobalLib.cpp
index cbc27bc..fde7797 100644
--- a/src/GlobalLib.cpp
+++ b/src/GlobalLib.cpp
@@ -9,23 +9,27 @@ using namespace std;
namespace sibs
{
- Result<bool> GlobalLib::validatePackageExists(const string &globalLibRootDir, const string &name)
+ Result<bool> GlobalLib::validatePackageExists(const FileString &globalLibRootDir, const std::string &name)
{
- string packageDir = globalLibRootDir + "/";
+ FileString packageDir = globalLibRootDir + TINYDIR_STRING("/");
+#if OS_FAMILY == OS_FAMILY_POSIX
packageDir += name;
+#else
+ packageDir += utf8To16(name);
+#endif
FileType packageDirFileType = getFileType(packageDir.c_str());
switch(packageDirFileType)
{
case FileType::FILE_NOT_FOUND:
{
string errMsg = "Global lib dependency not found: ";
- errMsg += name;
+ errMsg += toUtf8(packageDir);
return Result<bool>::Err(errMsg, DependencyError::DEPENDENCY_NOT_FOUND);
}
case FileType::REGULAR:
{
string errMsg = "Corrupt library directory. ";
- errMsg += packageDir;
+ errMsg += toUtf8(packageDir);
errMsg += " is a file, expected it to be a directory";
return Result<bool>::Err(errMsg);
}
@@ -40,13 +44,13 @@ namespace sibs
}
}
- const char *sourceFileExtensions[] = { "c", "cc", "cpp", "cxx" };
+ const _tinydir_char_t *sourceFileExtensions[] = { TINYDIR_STRING("c"),TINYDIR_STRING("cc"), TINYDIR_STRING("cpp"), TINYDIR_STRING("cxx") };
bool isSourceFile(tinydir_file *file)
{
if(!file->is_reg)
return false;
- for(const char *sourceFileExtension : sourceFileExtensions)
+ for(const _tinydir_char_t *sourceFileExtension : sourceFileExtensions)
{
if(_tinydir_strcmp(sourceFileExtension, file->extension) == 0)
return true;
@@ -55,29 +59,37 @@ namespace sibs
return false;
}
- bool isPathSubPathOf(const char *path, const string &subPathOf)
+ bool isPathSubPathOf(const _tinydir_char_t *path, const FileString &subPathOf)
{
return _tinydir_strncmp(path, subPathOf.c_str(), subPathOf.size()) == 0;
}
- Result<string> GlobalLib::getLibsLinkerFlags(const SibsConfig &parentConfig, const string &globalLibRootDir, const string &name, const string &version, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallbackFunc)
+ Result<string> GlobalLib::getLibsLinkerFlags(const SibsConfig &parentConfig, const FileString &globalLibRootDir, const std::string &name, const std::string &version, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallbackFunc)
{
Result<bool> packageExistsResult = validatePackageExists(globalLibRootDir, name);
if(packageExistsResult.isErr())
return Result<string>::Err(packageExistsResult);
- string packageDir = globalLibRootDir + "/";
- packageDir += name;
+#if OS_FAMILY == OS_FAMILY_POSIX
+ FileString namePlatformNative = name;
+ FileString versionPlatformNative = version;
+#else
+ FileString namePlatformNative = utf8To16(name);
+ FileString versionPlatformNative = utf8To16(version);
+#endif
+
+ FileString packageDir = globalLibRootDir + TINYDIR_STRING("/");
+ packageDir += namePlatformNative;
// TODO: Instead of checking if version is exact match, check if package has same major version
// and same or newer minor version
- string foundVersion;
- walkDir(packageDir.c_str(), [&foundVersion, &version](tinydir_file *file)
+ FileString foundVersion;
+ walkDir(packageDir.c_str(), [&foundVersion, &versionPlatformNative](tinydir_file *file)
{
if(file->is_dir)
{
//printf("version: %s\n", file->name);
- if(_tinydir_strcmp(version.c_str(), file->name) == 0)
+ if(_tinydir_strcmp(versionPlatformNative.c_str(), file->name) == 0)
foundVersion = file->name;
}
});
@@ -85,11 +97,11 @@ namespace sibs
if(foundVersion.empty())
return Result<string>::Err("Global lib dependency found, but version doesn't match dependency version", DependencyError::DEPENDENCY_VERSION_NO_MATCH);
- packageDir += "/";
- packageDir += version;
+ packageDir += TINYDIR_STRING("/");
+ packageDir += versionPlatformNative;
- string projectConfFilePath = packageDir;
- projectConfFilePath += "/project.conf";
+ FileString projectConfFilePath = packageDir;
+ projectConfFilePath += TINYDIR_STRING("/project.conf");
FileType projectConfFileType = getFileType(projectConfFilePath.c_str());
switch(projectConfFileType)
@@ -97,20 +109,20 @@ namespace sibs
case FileType::FILE_NOT_FOUND:
{
string errMsg = "Global lib dependency found: ";
- errMsg += packageDir;
+ errMsg += toUtf8(packageDir);
errMsg += ", but it's missing a project.conf file";
return Result<string>::Err(errMsg);
}
case FileType::DIRECTORY:
{
string errMsg = "Global lib dependency found: ";
- errMsg += packageDir;
+ errMsg += toUtf8(packageDir);
errMsg += ", but it's corrupt (Found directory instead of file)";
return Result<string>::Err(errMsg);
}
}
- SibsConfig sibsConfig(packageDir, parentConfig.getOptimizationLevel());
+ SibsConfig sibsConfig(parentConfig.getCompiler(), packageDir, parentConfig.getOptimizationLevel());
Result<bool> result = Config::readFromFile(projectConfFilePath.c_str(), sibsConfig);
if(result.isErr())
return Result<string>::Err(result.getErrMsg());
@@ -133,7 +145,8 @@ namespace sibs
{
if (isSourceFile(file))
{
- ninja.addSourceFile(file->path + sibsConfig.getProjectPath().size() + 1);
+ string fileNameNative = toUtf8(file->path + sibsConfig.getProjectPath().size() + 1);
+ ninja.addSourceFile(fileNameNative.c_str());
}
else
{
@@ -145,8 +158,11 @@ namespace sibs
// TODO: If compiling without "test" option, do not add test source dir to ninja. Ninja logic will then not build tests...
// OR I believe there is no reason to run tests in dependencies. The main projects tests should cover that?
// But you might want to know exactly which dependency is causing issue and which part of it...
- if(!sibsConfig.getTestPath().empty() && isPathSubPathOf(file->path, sibsConfig.getTestPath()))
- ninja.addTestSourceDir(file->path);
+ if (!sibsConfig.getTestPath().empty() && isPathSubPathOf(file->path, sibsConfig.getTestPath()))
+ {
+ string filePathUtf8 = toUtf8(file->path);
+ ninja.addTestSourceDir(filePathUtf8.c_str());
+ }
else
walkDir(file->path, collectSourceFiles);
}
@@ -160,36 +176,64 @@ namespace sibs
}
else
{
- string buildPath = packageDir + "/sibs-build/";
+ FileString buildPath = packageDir + TINYDIR_STRING("/sibs-build/");
switch(sibsConfig.getOptimizationLevel())
{
case OPT_LEV_DEBUG:
- buildPath += "debug";
+ buildPath += TINYDIR_STRING("debug");
break;
case OPT_LEV_RELEASE:
- buildPath += "release";
+ buildPath += TINYDIR_STRING("release");
break;
}
- string libPath = buildPath;
- libPath += "/lib";
- libPath += name;
- if(sibsConfig.getPackageType() == PackageType::STATIC)
- {
- libPath += ".a";
- string libPathCmd = "'";
- libPathCmd += libPath;
- libPathCmd += "'";
- staticLinkerFlagCallbackFunc(libPathCmd);
- libPath += ".a";
- }
- else
+ string libPath = toUtf8(buildPath);
+ switch (sibsConfig.getCompiler())
{
- libPath += ".so";
- string libPathCmd = "'";
- libPathCmd += libPath;
- libPathCmd += "'";
- dynamicLinkerFlagCallbackFunc(libPathCmd);
+ case Compiler::GCC:
+ {
+ libPath += "/lib";
+ libPath += name;
+ if (sibsConfig.getPackageType() == PackageType::STATIC)
+ {
+ libPath += ".a";
+ string libPathCmd = "'";
+ libPathCmd += libPath;
+ libPathCmd += "'";
+ staticLinkerFlagCallbackFunc(libPathCmd);
+ }
+ else
+ {
+ libPath += ".so";
+ string libPathCmd = "'";
+ libPathCmd += libPath;
+ libPathCmd += "'";
+ dynamicLinkerFlagCallbackFunc(libPathCmd);
+ }
+ break;
+ }
+ case Compiler::MSVC:
+ {
+ libPath += "/";
+ libPath += name;
+ if (sibsConfig.getPackageType() == PackageType::STATIC)
+ {
+ libPath += ".lib";
+ string libPathCmd = "\"";
+ libPathCmd += libPath;
+ libPathCmd += "\"";
+ staticLinkerFlagCallbackFunc(libPathCmd);
+ }
+ else
+ {
+ libPath += ".lib";
+ string libPathCmd = "\"";
+ libPathCmd += libPath;
+ libPathCmd += "\"";
+ dynamicLinkerFlagCallbackFunc(libPathCmd);
+ }
+ break;
+ }
}
// TODO: Use different directories depending on the project type, but .o build files should be in the same directory
@@ -214,21 +258,24 @@ namespace sibs
url += dependency.version;
url += ".tar.gz";
- string libPath = getHomeDir();
- libPath += "/.sibs/lib/";
- libPath += dependency.name;
- libPath += "/";
- libPath += dependency.version;
+ Result<FileString> libPathResult = getHomeDir();
+ if (!libPathResult)
+ return Result<bool>::Err(libPathResult);
+ FileString libPath = libPathResult.unwrap();
+ libPath += TINYDIR_STRING("/.sibs/lib/");
+ libPath += toFileString(dependency.name);
+ libPath += TINYDIR_STRING("/");
+ libPath += toFileString(dependency.version);
- string libArchivedFilePath = getHomeDir();
- libArchivedFilePath += "/.sibs/archive/";
- libArchivedFilePath += dependency.name;
+ FileString libArchivedFilePath = libPathResult.unwrap();
+ libArchivedFilePath += TINYDIR_STRING("/.sibs/archive/");
+ libArchivedFilePath += toFileString(dependency.name);
Result<bool> createArchiveDirResult = createDirectoryRecursive(libArchivedFilePath.c_str());
if(createArchiveDirResult.isErr())
return createArchiveDirResult;
- libArchivedFilePath += "/";
- libArchivedFilePath += dependency.version;
+ libArchivedFilePath += TINYDIR_STRING("/");
+ libArchivedFilePath += toFileString(dependency.version);
Result<bool> downloadResult = curl::downloadFile(url.c_str(), libArchivedFilePath.c_str());
if(downloadResult.isErr())
return downloadResult;
@@ -240,4 +287,4 @@ namespace sibs
return Archive::extract(libArchivedFilePath.c_str(), libPath.c_str());
}
-}
+} \ No newline at end of file
diff --git a/src/PkgConfig.cpp b/src/PkgConfig.cpp
index 620b1a7..a66d5b3 100644
--- a/src/PkgConfig.cpp
+++ b/src/PkgConfig.cpp
@@ -1,4 +1,5 @@
#include "../include/PkgConfig.hpp"
+#if OS_FAMILY == OS_FAMILY_POSIX
#include "../include/Exec.hpp"
using namespace std;
@@ -127,4 +128,5 @@ namespace sibs
return Result<string>::Err(errMsg);
}
}
-} \ No newline at end of file
+}
+#endif // OS_FAMILY_POSIX
diff --git a/src/curl.cpp b/src/curl.cpp
index 56c19ec..a3c5e28 100644
--- a/src/curl.cpp
+++ b/src/curl.cpp
@@ -5,6 +5,12 @@
using namespace std;
+#if OS_FAMILY == OS_FAMILY_WINDOWS
+#pragma comment(lib, "Ws2_32.lib")
+#pragma comment(lib, "Wldap32.lib")
+#pragma comment(lib, "Crypt32.lib")
+#endif
+
#ifdef DEBUG
#define CURL_DEBUG
#endif
@@ -44,7 +50,7 @@ namespace sibs
return size * nmemb;
}
- Result<bool> curl::downloadFile(const char *url, const char *filepath)
+ Result<bool> curl::downloadFile(const char *url, const _tinydir_char_t *filepath)
{
CURL *curl_handle = curl_easy_init();
curl_easy_setopt(curl_handle, CURLOPT_URL, url);
@@ -60,15 +66,19 @@ namespace sibs
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writeToFile);
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, true);
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "SIBS");
-
+ curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, FALSE);
+#if OS_FAMILY == OS_FAMILY_POSIX
FILE *file = fopen(filepath, "wb");
+#else
+ FILE *file = _wfopen(filepath, L"wb");
+#endif
if(!file)
{
int error = errno;
curl_easy_cleanup(curl_handle);
string errMsg = "Failed to open file for writing: ";
- errMsg += filepath;
+ errMsg += toUtf8(filepath);
if(error != 0)
{
errMsg += "; Reason: ";
@@ -131,8 +141,9 @@ namespace sibs
curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, noProgressMeter);
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, writeToString);
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, true);
- curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "Hacker");
-
+ curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "SIBS");
+ curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, FALSE);
+
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &result.str);
printf("Downloading from url: %s\n", url);
CURLcode curlResponse = curl_easy_perform(curl_handle);
diff --git a/src/main.cpp b/src/main.cpp
index 26cab5c..855b1dc 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -24,6 +24,12 @@ using namespace std::chrono;
// TODO: Remove install.sh when sibs supports installation of packages (so it can install itself)
+#if OS_FAMILY == OS_FAMILY_POSIX
+#define ferr std::cerr
+#else
+#define ferr std::wcerr
+#endif
+
void usage()
{
printf("Usage: sibs COMMAND\n\n");
@@ -63,47 +69,47 @@ void usageNew()
exit(1);
}
-void validateDirectoryPath(const char *projectPath)
+void validateDirectoryPath(const _tinydir_char_t *projectPath)
{
FileType projectPathFileType = getFileType(projectPath);
if(projectPathFileType == FileType::FILE_NOT_FOUND)
{
string errMsg = "Invalid project path: ";
- errMsg += projectPath;
+ errMsg += toUtf8(projectPath);
perror(errMsg.c_str());
exit(2);
}
else if(projectPathFileType == FileType::REGULAR)
{
- cerr <<"Expected project path (" << projectPath << ") to be a directory, was a file" << endl;
+ ferr <<"Expected project path (" << projectPath << ") to be a directory, was a file" << endl;
exit(3);
}
}
-void validateFilePath(const char *projectConfPath)
+void validateFilePath(const _tinydir_char_t *projectConfPath)
{
FileType projectConfFileType = getFileType(projectConfPath);
if(projectConfFileType == FileType::FILE_NOT_FOUND)
{
string errMsg = "Invalid project.conf path: ";
- errMsg += projectConfPath;
+ errMsg += toUtf8(projectConfPath);
perror(errMsg.c_str());
exit(4);
}
else if(projectConfFileType == FileType::DIRECTORY)
{
- cerr << "Expected project path (" << projectConfPath << ") to be a file, was a directory" << endl;
+ ferr << "Expected project path (" << projectConfPath << ") to be a file, was a directory" << endl;
exit(5);
}
}
-const char *sourceFileExtensions[] = { "c", "cc", "cpp", "cxx" };
+const _tinydir_char_t *sourceFileExtensions[] = { TINYDIR_STRING("c"), TINYDIR_STRING("cc"), TINYDIR_STRING("cpp"), TINYDIR_STRING("cxx") };
bool isSourceFile(tinydir_file *file)
{
if(!file->is_reg)
return false;
- for(const char *sourceFileExtension : sourceFileExtensions)
+ for(const _tinydir_char_t *sourceFileExtension : sourceFileExtensions)
{
if(_tinydir_strcmp(sourceFileExtension, file->extension) == 0)
return true;
@@ -112,36 +118,36 @@ bool isSourceFile(tinydir_file *file)
return false;
}
-bool isPathSubPathOf(const string &path, const string &subPathOf)
+bool isPathSubPathOf(const FileString &path, const FileString &subPathOf)
{
return _tinydir_strncmp(path.c_str(), subPathOf.c_str(), subPathOf.size()) == 0;
}
-int buildProject(int argc, const char **argv)
+int buildProject(int argc, const _tinydir_char_t **argv)
{
if(argc > 2)
usageBuild();
OptimizationLevel optimizationLevel = OPT_LEV_NONE;
- string projectPath;
+ FileString projectPath;
for(int i = 0; i < argc; ++i)
{
- const char *arg = argv[i];
- if(strcmp(arg, "--debug") == 0)
+ const _tinydir_char_t *arg = argv[i];
+ if(_tinydir_strcmp(arg, TINYDIR_STRING("--debug")) == 0)
{
if(optimizationLevel != OPT_LEV_NONE)
{
- fprintf(stderr, "Error: Optimization level defined more than once. First defined as %s then as %s\n", asString(optimizationLevel), "debug");
+ ferr << "Error: Optimization level defined more than once. First defined as " << asString(optimizationLevel) << " then as debug" << endl;
usageBuild();
}
optimizationLevel = OPT_LEV_DEBUG;
}
- else if(strcmp(arg, "--release") == 0)
+ else if(_tinydir_strcmp(arg, TINYDIR_STRING("--release")) == 0)
{
if(optimizationLevel != OPT_LEV_NONE)
{
- fprintf(stderr, "Error: Optimization level defined more than once. First defined as %s then as %s\n", asString(optimizationLevel), "debug");
+ ferr << "Error: Optimization level defined more than once. First defined as " << asString(optimizationLevel) << " then as release" << endl;
usageBuild();
}
optimizationLevel = OPT_LEV_RELEASE;
@@ -150,7 +156,7 @@ int buildProject(int argc, const char **argv)
{
if(!projectPath.empty())
{
- fprintf(stderr, "Error: Project path was defined more than once. First defined as %s then as %s\n", projectPath.c_str(), arg);
+ ferr << "Error: Project path was defined more than once. First defined as " << projectPath << " then as " << arg << endl;
usageBuild();
}
projectPath = arg;
@@ -162,35 +168,43 @@ int buildProject(int argc, const char **argv)
// TODO: If projectPath is not defined and working directory does not contain project.conf, then search every parent directory until one is found
if(projectPath.empty())
- projectPath = ".";
+ projectPath = TINYDIR_STRING(".");
validateDirectoryPath(projectPath.c_str());
if(projectPath.back() != '/')
- projectPath += "/";
+ projectPath += TINYDIR_STRING("/");
- Result<string> projectRealPathResult = getRealPath(projectPath.c_str());
+ Result<FileString> projectRealPathResult = getRealPath(projectPath.c_str());
if(!projectRealPathResult)
{
- cerr << "Failed to get real path for: '" << projectPath << "': " << projectRealPathResult.getErrMsg() << endl;
+ ferr << "Failed to get real path for: '" << projectPath.c_str() << "': " << toFileString(projectRealPathResult.getErrMsg()) << endl;
exit(40);
}
projectPath = projectRealPathResult.unwrap();
- string projectConfFilePath = projectPath;
- projectConfFilePath += "/project.conf";
+ FileString projectConfFilePath = projectPath;
+ projectConfFilePath += TINYDIR_STRING("/project.conf");
validateFilePath(projectConfFilePath.c_str());
- SibsConfig sibsConfig(projectPath, optimizationLevel);
+ // TODO: Detect compiler to use at runtime. Should also be configurable
+ // by passing argument to `sibs build`
+#if OS_FAMILY == OS_FAMILY_POSIX
+ Compiler compiler = Compiler::GCC;
+#else
+ Compiler compiler = Compiler::MSVC;
+#endif
+
+ SibsConfig sibsConfig(compiler, projectPath, optimizationLevel);
Result<bool> result = Config::readFromFile(projectConfFilePath.c_str(), sibsConfig);
if(result.isErr())
{
- cerr << "Failed to read config: " << result.getErrMsg() << endl;
+ ferr << "Failed to read config: " << toFileString(result.getErrMsg()) << endl;
exit(6);
}
if(sibsConfig.getPackageName().empty())
{
- cerr << "project.conf is missing required field package.name" << endl;
+ ferr << "project.conf is missing required field package.name" << endl;
exit(10);
}
@@ -204,7 +218,8 @@ int buildProject(int argc, const char **argv)
{
if (isSourceFile(file))
{
- ninja.addSourceFile(file->path + sibsConfig.getProjectPath().size());
+ string filePathUtf8 = toUtf8(file->path + sibsConfig.getProjectPath().size());
+ ninja.addSourceFile(filePathUtf8.c_str());
}
else
{
@@ -214,22 +229,25 @@ int buildProject(int argc, const char **argv)
else
{
// TODO: If compiling without "test" option, do not add test source dir to ninja. Ninja logic will then not build tests
- if(!sibsConfig.getTestPath().empty() && isPathSubPathOf(file->path, sibsConfig.getTestPath()))
- ninja.addTestSourceDir(file->path);
+ if (!sibsConfig.getTestPath().empty() && isPathSubPathOf(file->path, sibsConfig.getTestPath()))
+ {
+ string filePathUtf8 = toUtf8(file->path);
+ ninja.addTestSourceDir(filePathUtf8.c_str());
+ }
else
walkDir(file->path, collectSourceFiles);
}
};
walkDir(projectPath.c_str(), collectSourceFiles);
- string buildPath = projectPath + "/sibs-build/";
+ FileString buildPath = projectPath + TINYDIR_STRING("/sibs-build/");
switch(sibsConfig.getOptimizationLevel())
{
case OPT_LEV_DEBUG:
- buildPath += "debug";
+ buildPath += TINYDIR_STRING("debug");
break;
case OPT_LEV_RELEASE:
- buildPath += "release";
+ buildPath += TINYDIR_STRING("release");
break;
}
@@ -237,7 +255,7 @@ int buildProject(int argc, const char **argv)
Result<bool> buildFileResult = ninja.build(sibsConfig, buildPath.c_str());
if(buildFileResult.isErr())
{
- cerr << "Failed to build ninja file: " << buildFileResult.getErrMsg() << endl;
+ ferr << "Failed to build ninja file: " << toFileString(buildFileResult.getErrMsg()) << endl;
exit(7);
}
auto elapsedTime = duration_cast<duration<double>>(high_resolution_clock::now() - startTime);
@@ -246,37 +264,37 @@ int buildProject(int argc, const char **argv)
return 0;
}
-void newProjectCreateMainDir(const string &projectPath)
+void newProjectCreateMainDir(const FileString &projectPath)
{
Result<bool> createProjectDirResult = createDirectoryRecursive(projectPath.c_str());
if(createProjectDirResult.isErr())
{
- cerr << "Failed to create project main directory: " << createProjectDirResult.getErrMsg() << endl;
+ ferr << "Failed to create project main directory: " << toFileString(createProjectDirResult.getErrMsg()) << endl;
exit(20);
}
}
-void createProjectSubDir(const string &dir)
+void createProjectSubDir(const FileString &dir)
{
Result<bool> createProjectDirResult = createDirectoryRecursive(dir.c_str());
if(createProjectDirResult.isErr())
{
- cerr << "Failed to create directory in project: " << createProjectDirResult.getErrMsg() << endl;
+ ferr << "Failed to create directory in project: " << toFileString(createProjectDirResult.getErrMsg()) << endl;
exit(20);
}
}
-void createProjectFile(const string &projectFilePath, const string &fileContent)
+void createProjectFile(const FileString &projectFilePath, const string &fileContent)
{
Result<bool> fileOverwriteResult = fileOverwrite(projectFilePath.c_str(), fileContent.c_str());
if(fileOverwriteResult.isErr())
{
- cerr << "Failed to create project file: " << fileOverwriteResult.getErrMsg() << endl;
+ ferr << "Failed to create project file: " << toFileString(fileOverwriteResult.getErrMsg()) << endl;
exit(20);
}
}
-void newProjectCreateConf(const string &projectName, const string &projectType, const string &projectPath)
+void newProjectCreateConf(const string &projectName, const string &projectType, const FileString &projectPath)
{
string projectConfStr = "[package]\n";
projectConfStr += "name = \"" + projectName + "\"\n";
@@ -284,98 +302,102 @@ void newProjectCreateConf(const string &projectName, const string &projectType,
projectConfStr += "version = \"0.1.0\"\n\n";
projectConfStr += "[dependencies]\n";
- string projectConfPath = projectPath;
- projectConfPath += "/project.conf";
+ FileString projectConfPath = projectPath;
+ projectConfPath += TINYDIR_STRING("/project.conf");
Result<bool> fileOverwriteResult = fileOverwrite(projectConfPath.c_str(), projectConfStr.c_str());
if(fileOverwriteResult.isErr())
{
- cerr << "Failed to create project.conf: " << fileOverwriteResult.getErrMsg() << endl;
+ ferr << "Failed to create project.conf: " << toFileString(fileOverwriteResult.getErrMsg()) << endl;
exit(20);
}
}
// This can be replaced with createDirectory and fileOverwrite, but it's not important
// so there is no reason to do it (right now)
-Result<ExecResult> gitInitProject(const string &projectPath)
+Result<ExecResult> gitInitProject(const FileString &projectPath)
{
- string cmd = "git init '";
+ FileString cmd = TINYDIR_STRING("git init \"");
cmd += projectPath;
- cmd += "'";
+ cmd += TINYDIR_STRING("\"");
return exec(cmd.c_str());
}
-int newProject(int argc, const char **argv)
+int newProject(int argc, const _tinydir_char_t **argv)
{
if(argc != 2)
{
- cerr << "Expected 'new' command to be followed by two arguments - project name and type of project (--exec, --static or --dynamic)" << endl << endl;
+ ferr << "Expected 'new' command to be followed by two arguments - project name and type of project (--exec, --static or --dynamic)" << endl << endl;
usageNew();
}
- Result<string> cwdResult = getCwd();
+ Result<FileString> cwdResult = getCwd();
if(cwdResult.isErr())
{
- cerr << "Failed to get current working directory: " << cwdResult.getErrMsg() << endl;
+ ferr << "Failed to get current working directory: " << toFileString(cwdResult.getErrMsg()) << endl;
exit(20);
}
- string projectName = argv[0];
- string projectPath = cwdResult.unwrap();
- projectPath += "/";
- projectPath += projectName;
+ string projectName = toUtf8(argv[0]);
+ FileString projectPath = cwdResult.unwrap();
+ projectPath += TINYDIR_STRING("/");
+ projectPath += toFileString(projectName);
bool projectPathExists = getFileType(projectPath.c_str()) != FileType::FILE_NOT_FOUND;
if(projectPathExists)
{
- cerr << "Unable to create a new project at path '" << projectPath << "'. A file or directory already exists in the same location" << endl;
+ ferr << "Unable to create a new project at path '" << projectPath << "'. A file or directory already exists in the same location" << endl;
exit(20);
}
- const char *projectType = argv[1];
+ const _tinydir_char_t *projectType = argv[1];
string projectTypeConf;
- if(strcmp(projectType, "--exec") == 0)
+ if(_tinydir_strcmp(projectType, TINYDIR_STRING("--exec")) == 0)
projectTypeConf = "executable";
- else if(strcmp(projectType, "--static") == 0)
+ else if(_tinydir_strcmp(projectType, TINYDIR_STRING("--static")) == 0)
projectTypeConf = "static";
- else if(strcmp(projectType, "--dynamic") == 0)
+ else if(_tinydir_strcmp(projectType, TINYDIR_STRING("--dynamic")) == 0)
projectTypeConf = "dynamic";
else
{
- cerr << "Expected project type to be either --exec, --static or --dynamic; was: " << projectType << endl << endl;
+ ferr << "Expected project type to be either --exec, --static or --dynamic; was: " << projectType << endl << endl;
usageNew();
}
newProjectCreateMainDir(projectPath);
newProjectCreateConf(projectName, projectTypeConf, projectPath);
- createProjectSubDir(projectPath + "/src");
- createProjectSubDir(projectPath + "/include");
- createProjectFile(projectPath + "/src/main.cpp", "#include <cstdio>\n\nint main()\n{\n return 0;\n}\n");
+ createProjectSubDir(projectPath + TINYDIR_STRING("/src"));
+ createProjectSubDir(projectPath + TINYDIR_STRING("/include"));
+ createProjectFile(projectPath + TINYDIR_STRING("/src/main.cpp"), "#include <cstdio>\n\nint main()\n{\n return 0;\n}\n");
// We are ignoring git init result on purpose. If it fails, just ignore it; not important
gitInitProject(projectPath);
return 0;
}
-int main(int argc, const char **argv)
+#if OS_FAMILY == OS_FAMILY_POSIX
+int main(int argc, const _tinydir_char_t **argv)
+#else
+int wmain(int argc, const _tinydir_char_t **argv)
+#endif
{
unordered_map<string, string> param;
unordered_set<string> flags;
for(int i = 1; i < argc; ++i)
{
- const char *arg = argv[i];
+ const _tinydir_char_t *arg = argv[i];
int subCommandArgCount = argc - i - 1;
- const char **subCommandArgPtr = argv + i + 1;
- if(strcmp(arg, "build") == 0)
+ const _tinydir_char_t **subCommandArgPtr = argv + i + 1;
+ if(_tinydir_strcmp(arg, TINYDIR_STRING("build")) == 0)
{
return buildProject(subCommandArgCount, subCommandArgPtr);
}
- else if(strcmp(arg, "new") == 0)
+ else if(_tinydir_strcmp(arg, TINYDIR_STRING("new")) == 0)
{
return newProject(subCommandArgCount, subCommandArgPtr);
}
else
{
- cerr << "Expected command to be either 'build' or 'new', was: " << arg << endl << endl;
+ ferr << "Expected command to be either 'build' or 'new', was: " << arg << endl << endl;
usage();
}
}