From c4d1491af938a12a0167dae4fd3ea8f1810c752a Mon Sep 17 00:00:00 2001 From: dec05eba Date: Tue, 25 Sep 2018 20:47:40 +0200 Subject: Fix build for windows --- src/main.cpp | 126 +++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 96 insertions(+), 30 deletions(-) (limited to 'src/main.cpp') 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 <--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 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 = 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 newProjectCreateConf(const string &projectName, const string &projectType, const FileString &projectPath) +static Result newProjectCreateConf(const string &projectName, const string &projectType, const FileString &projectPath) { string projectConfStr = "[package]\n"; projectConfStr += "name = \"" + projectName + "\"\n"; @@ -574,12 +638,12 @@ Result newProjectCreateConf(const string &projectName, const string &proje return fileWrite(projectConfPath.c_str(), projectConfStr.c_str()); } -Result createDirectoryRecursive(const FileString &dir) +static Result 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 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 gitInitProject(const FileString &projectPath) +static Result gitInitProject(const FileString &projectPath) { FileString cmd = TINYDIR_STRING("git init \""); cmd += projectPath; @@ -599,7 +663,7 @@ Result gitInitProject(const FileString &projectPath) return exec(cmd.c_str()); } -bool gitIgnoreContainsSibs(const FileString &gitIgnoreFilePath) +static bool gitIgnoreContainsSibs(const FileString &gitIgnoreFilePath) { Result 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 fileContentResult = getFileContent(gitIgnoreFilePath.c_str()); string fileContentNew; @@ -627,10 +691,10 @@ void gitIgnoreAppendSibs(const FileString &gitIgnoreFilePath) fileContentNew += SIBS_GITIGNORE_FILES; Result 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 createProjectDirResult = createDirectoryRecursive(projectPath.c_str()); if(createProjectDirResult.isErr()) @@ -840,7 +904,7 @@ void newProjectCreateMainDir(const FileString &projectPath) } } -void checkFailCreateSubDir(Result createSubDirResult) +static void checkFailCreateSubDir(Result createSubDirResult) { if(!createSubDirResult) { @@ -849,7 +913,7 @@ void checkFailCreateSubDir(Result 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) -- cgit v1.2.3