aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp160
1 files changed, 91 insertions, 69 deletions
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();
}
}