aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp126
1 files changed, 96 insertions, 30 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 38e68f0..cb1c611 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -112,7 +112,7 @@ static string SIBS_GITIGNORE_FILES =
"tests/sibs-build/\n"
"tests/compile_commands.json\n";
-void usage()
+static void usage()
{
printf("Usage: sibs COMMAND\n\n");
printf("Simple Build System for Native Languages\n\n");
@@ -124,7 +124,7 @@ void usage()
exit(1);
}
-void usageBuild()
+static void usageBuild()
{
printf("Usage: sibs build [project_path] [--debug|--release] [--sanitize]\n\n");
printf("Build a sibs project\n\n");
@@ -141,7 +141,7 @@ void usageBuild()
exit(1);
}
-void usageNew()
+static void usageNew()
{
printf("Usage: sibs new <project_name> <--exec|--static|--dynamic> [--lang c|c++|zig]\n\n");
printf("Create a new sibs project\n\n");
@@ -156,7 +156,7 @@ void usageNew()
exit(1);
}
-void usageTest()
+static void usageTest()
{
printf("Usage: sibs test [project_path] [--no-sanitize] [--file filepath...|--all-files]\n\n");
printf("Build and run tests for a sibs project\n\n");
@@ -171,7 +171,7 @@ void usageTest()
exit(1);
}
-void usageInit()
+static void usageInit()
{
printf("Usage: sibs init [project_path] <--exec|--static|--dynamic> [--lang c|c++|zig]\n\n");
printf("Create sibs project structure in an existing directory\n\n");
@@ -187,7 +187,7 @@ void usageInit()
exit(1);
}
-void validateDirectoryPath(const _tinydir_char_t *projectPath)
+static void validateDirectoryPath(const _tinydir_char_t *projectPath)
{
FileType projectPathFileType = getFileType(projectPath);
if(projectPathFileType == FileType::FILE_NOT_FOUND)
@@ -204,7 +204,7 @@ void validateDirectoryPath(const _tinydir_char_t *projectPath)
}
}
-void validateFilePath(const _tinydir_char_t *projectConfPath)
+static void validateFilePath(const _tinydir_char_t *projectConfPath)
{
FileType projectConfFileType = getFileType(projectConfPath);
if(projectConfFileType == FileType::FILE_NOT_FOUND)
@@ -221,20 +221,84 @@ void validateFilePath(const _tinydir_char_t *projectConfPath)
}
}
-bool isPathSubPathOf(const FileString &path, const FileString &subPathOf)
+static bool isPathSubPathOf(const FileString &path, const FileString &subPathOf)
{
return _tinydir_strncmp(path.c_str(), subPathOf.c_str(), subPathOf.size()) == 0;
}
-static bool doesProgramExist(const _tinydir_char_t *programName)
+#if OS_FAMILY == OS_FAMILY_WINDOWS
+static char* join(const char *str1, const char *str2, const char separator)
{
- FileString cmd = FileString(programName) + TINYDIR_STRING(" --version");
- Result<sibs::ExecResult> result = exec(cmd.c_str());
- bool programNotFound = !result && result.getErrorCode() == 127;
- return !programNotFound;
+ int str1len = strlen(str1);
+ int str2len = strlen(str2);
+ char *result = new char[str1len + 1 + str2len + 1];
+ memcpy(result, str1, str1len);
+ result[str1len] = separator;
+ memcpy(result + str1len + 1, str2, str2len);
+ result[str1len + 1 + str2len] = '\0';
+ return result;
}
-int buildProject(const FileString &projectPath, const FileString &projectConfFilePath, SibsConfig &sibsConfig)
+struct MicrosoftBuildTool
+{
+ // 0 if version not found
+ int version;
+ // empty if not found
+ char binPath[_TINYDIR_PATH_MAX];
+ // empty if not found
+ char umLibPath[_TINYDIR_PATH_MAX];
+ // empty if not found
+ char ucrtLibPath[_TINYDIR_PATH_MAX];
+
+ bool found()
+ {
+ return version != 0;
+ }
+};
+
+static MicrosoftBuildTool locateLatestMicrosoftBuildTool()
+{
+ MicrosoftBuildTool result = { 0 };
+ Result<ExecResult> execResult = exec(TINYDIR_STRING("locate_windows_sdk"));
+ if (execResult && execResult.unwrap().exitCode == 0)
+ {
+ auto &str = execResult.unwrap().execStdout;
+ sscanf(execResult.unwrap().execStdout.c_str(), "%d %[^\r\n] %[^\r\n] %[^\r\n]", &result.version, result.binPath, result.umLibPath, result.ucrtLibPath);
+ }
+ return result;
+}
+
+static void appendMicrosoftBuildToolToPathEnv()
+{
+ MicrosoftBuildTool msBuildTool = locateLatestMicrosoftBuildTool();
+ if (msBuildTool.found())
+ {
+ fprintf(stderr, "Located microsoft build tools at %s\n", msBuildTool.binPath);
+ fprintf(stderr, "Located microsoft build libraries at %s;%s\n", msBuildTool.umLibPath, msBuildTool.ucrtLibPath);
+
+ if (const char *pathEnv = getenv("PATH"))
+ {
+ // We do not free this because it needs to live as long as it's used as env (in _putenv)
+ if (_putenv_s("PATH", join(pathEnv, msBuildTool.binPath, ';')) != 0)
+ fprintf(stderr, "Warning: Failed to add microsoft build tools to PATH env\n");
+ }
+
+ // We do not free this because it needs to live as long as it's used as env (in _putenv)
+ if (_putenv_s("LIB", join(msBuildTool.umLibPath, msBuildTool.ucrtLibPath, ';')) != 0)
+ fprintf(stderr, "Warning: Failed to add microsoft build libraries to LIB env\n");
+ }
+}
+#endif
+
+static void appendBuildToolToPathEnv()
+{
+#if OS_FAMILY == OS_FAMILY_WINDOWS
+ // TODO: We shouldn't do this if user wants to compile with clang/mingw?
+ appendMicrosoftBuildToolToPathEnv();
+#endif
+}
+
+static int buildProject(const FileString &projectPath, const FileString &projectConfFilePath, SibsConfig &sibsConfig)
{
FileString buildPath;
readSibsConfig(projectPath, projectConfFilePath, sibsConfig, buildPath);
@@ -317,7 +381,7 @@ int buildProject(const FileString &projectPath, const FileString &projectConfFil
return 0;
}
-int buildProject(int argc, const _tinydir_char_t **argv)
+static int buildProject(int argc, const _tinydir_char_t **argv)
{
if(argc > 3)
usageBuild();
@@ -404,7 +468,7 @@ int buildProject(int argc, const _tinydir_char_t **argv)
return buildProject(projectPath, projectConfFilePath, sibsConfig);
}
-int testProject(int argc, const _tinydir_char_t **argv)
+static int testProject(int argc, const _tinydir_char_t **argv)
{
if(argc > 2)
usageTest();
@@ -546,7 +610,7 @@ int testProject(int argc, const _tinydir_char_t **argv)
}
// Returns nullptr if @charToFind is not found
-const _tinydir_char_t* findLastOf(const _tinydir_char_t *str, const int strSize, const char charToFind)
+static const _tinydir_char_t* findLastOf(const _tinydir_char_t *str, const int strSize, const char charToFind)
{
for(int i = strSize; i >= 0; --i)
{
@@ -556,7 +620,7 @@ const _tinydir_char_t* findLastOf(const _tinydir_char_t *str, const int strSize,
return nullptr;
}
-Result<bool> newProjectCreateConf(const string &projectName, const string &projectType, const FileString &projectPath)
+static Result<bool> newProjectCreateConf(const string &projectName, const string &projectType, const FileString &projectPath)
{
string projectConfStr = "[package]\n";
projectConfStr += "name = \"" + projectName + "\"\n";
@@ -574,12 +638,12 @@ Result<bool> newProjectCreateConf(const string &projectName, const string &proje
return fileWrite(projectConfPath.c_str(), projectConfStr.c_str());
}
-Result<bool> createDirectoryRecursive(const FileString &dir)
+static Result<bool> createDirectoryRecursive(const FileString &dir)
{
return createDirectoryRecursive(dir.c_str());
}
-void createProjectFile(const FileString &projectFilePath, const string &fileContent)
+static void createProjectFile(const FileString &projectFilePath, const string &fileContent)
{
Result<bool> fileOverwriteResult = fileOverwrite(projectFilePath.c_str(), fileContent.c_str());
if(fileOverwriteResult.isErr())
@@ -591,7 +655,7 @@ void createProjectFile(const FileString &projectFilePath, const string &fileCont
// 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 FileString &projectPath)
+static Result<ExecResult> gitInitProject(const FileString &projectPath)
{
FileString cmd = TINYDIR_STRING("git init \"");
cmd += projectPath;
@@ -599,7 +663,7 @@ Result<ExecResult> gitInitProject(const FileString &projectPath)
return exec(cmd.c_str());
}
-bool gitIgnoreContainsSibs(const FileString &gitIgnoreFilePath)
+static bool gitIgnoreContainsSibs(const FileString &gitIgnoreFilePath)
{
Result<StringView> fileContentResult = getFileContent(gitIgnoreFilePath.c_str());
if(!fileContentResult) return false;
@@ -611,7 +675,7 @@ bool gitIgnoreContainsSibs(const FileString &gitIgnoreFilePath)
return containsSibs;
}
-void gitIgnoreAppendSibs(const FileString &gitIgnoreFilePath)
+static void gitIgnoreAppendSibs(const FileString &gitIgnoreFilePath)
{
Result<StringView> fileContentResult = getFileContent(gitIgnoreFilePath.c_str());
string fileContentNew;
@@ -627,10 +691,10 @@ void gitIgnoreAppendSibs(const FileString &gitIgnoreFilePath)
fileContentNew += SIBS_GITIGNORE_FILES;
Result<bool> result = fileOverwrite(gitIgnoreFilePath.c_str(), { fileContentNew.data(), fileContentNew.size() });
if(!result)
- ferr << "Failed to add sibs to .gitignore, reason: " << result.getErrMsg() << endl;
+ ferr << "Failed to add sibs to .gitignore, reason: " << toFileString(result.getErrMsg()) << endl;
}
-int initProject(int argc, const _tinydir_char_t **argv)
+static int initProject(int argc, const _tinydir_char_t **argv)
{
FileString projectPath;
const _tinydir_char_t *projectType = nullptr;
@@ -785,7 +849,7 @@ int initProject(int argc, const _tinydir_char_t **argv)
auto createProjectConfResult = newProjectCreateConf(projectName, projectTypeConf, projectPath);
if(!createProjectConfResult)
{
- ferr << "A project already exists in the directory " << projectPath << ". Error: failed to create project.conf, reason: " << createProjectConfResult.getErrMsg() << endl;
+ ferr << "A project already exists in the directory " << projectPath << ". Error: failed to create project.conf, reason: " << toFileString(createProjectConfResult.getErrMsg()) << endl;
exit(20);
}
createDirectoryRecursive(projectPath + TINYDIR_STRING("/src"));
@@ -830,7 +894,7 @@ int initProject(int argc, const _tinydir_char_t **argv)
return 0;
}
-void newProjectCreateMainDir(const FileString &projectPath)
+static void newProjectCreateMainDir(const FileString &projectPath)
{
Result<bool> createProjectDirResult = createDirectoryRecursive(projectPath.c_str());
if(createProjectDirResult.isErr())
@@ -840,7 +904,7 @@ void newProjectCreateMainDir(const FileString &projectPath)
}
}
-void checkFailCreateSubDir(Result<bool> createSubDirResult)
+static void checkFailCreateSubDir(Result<bool> createSubDirResult)
{
if(!createSubDirResult)
{
@@ -849,7 +913,7 @@ void checkFailCreateSubDir(Result<bool> createSubDirResult)
}
}
-int newProject(int argc, const _tinydir_char_t **argv)
+static int newProject(int argc, const _tinydir_char_t **argv)
{
string projectName;
const _tinydir_char_t *projectType = nullptr;
@@ -918,7 +982,7 @@ int newProject(int argc, const _tinydir_char_t **argv)
{
if(!projectName.empty())
{
- ferr << "Error: Project name was defined more than once. First defined as " << projectName << " then as " << arg << endl;
+ ferr << "Error: Project name was defined more than once. First defined as " << toFileString(projectName) << " then as " << arg << endl;
usageNew();
}
projectName = toUtf8(arg);
@@ -1041,6 +1105,7 @@ int wmain(int argc, const _tinydir_char_t **argv)
const _tinydir_char_t **subCommandArgPtr = argv + i + 1;
if(_tinydir_strcmp(arg, TINYDIR_STRING("build")) == 0)
{
+ appendBuildToolToPathEnv();
return buildProject(subCommandArgCount, subCommandArgPtr);
}
else if(_tinydir_strcmp(arg, TINYDIR_STRING("new")) == 0)
@@ -1049,6 +1114,7 @@ int wmain(int argc, const _tinydir_char_t **argv)
}
else if(_tinydir_strcmp(arg, TINYDIR_STRING("test")) == 0)
{
+ appendBuildToolToPathEnv();
return testProject(subCommandArgCount, subCommandArgPtr);
}
else if(_tinydir_strcmp(arg, TINYDIR_STRING("init")) == 0)