From dbb06eac9bae1b8dbc50275b66c975da09b1d09a Mon Sep 17 00:00:00 2001 From: dec05eba Date: Tue, 25 Sep 2018 23:22:08 +0200 Subject: Fix build with msvc (windows) Fix freeze when sub process (exec) returns a lot of data (in stdout) --- src/Exec.cpp | 10 ++-- src/FileUtil.cpp | 154 ++++++++++++++++++++---------------------------------- src/PkgConfig.cpp | 28 +++++----- src/main.cpp | 64 +++++++++++++++++------ 4 files changed, 125 insertions(+), 131 deletions(-) (limited to 'src') diff --git a/src/Exec.cpp b/src/Exec.cpp index 6c1a72e..659d812 100644 --- a/src/Exec.cpp +++ b/src/Exec.cpp @@ -99,13 +99,8 @@ namespace sibs if (!CreateProcessW(nullptr, (LPWSTR)cmdNonConst.data(), nullptr, nullptr, TRUE, 0, nullptr, nullptr, &siStartInfo, &piProcInfo)) goto cleanupAndExit; - WaitForSingleObject(piProcInfo.hProcess, INFINITE); - GetExitCodeProcess(piProcInfo.hProcess, &exitCode); - CloseHandle(piProcInfo.hProcess); - CloseHandle(piProcInfo.hThread); CloseHandle(childStdoutHandle); childStdoutHandle = nullptr; - DWORD bytesRead; CHAR buffer[BUFSIZE]; while (true) @@ -119,6 +114,11 @@ namespace sibs printf("%.*s", bytesRead, buffer); } + WaitForSingleObject(piProcInfo.hProcess, INFINITE); + GetExitCodeProcess(piProcInfo.hProcess, &exitCode); + CloseHandle(piProcInfo.hProcess); + CloseHandle(piProcInfo.hThread); + { ExecResult execResult; execResult.execStdout = move(execStdout); diff --git a/src/FileUtil.cpp b/src/FileUtil.cpp index 77669e5..e29ed36 100644 --- a/src/FileUtil.cpp +++ b/src/FileUtil.cpp @@ -16,6 +16,19 @@ using namespace std; +#if OS_FAMILY == OS_FAMILY_POSIX +static int makedir(const _tinydir_char_t *dir) +{ + return mkdir(dir, S_IRWXU); +} +#elif OS_FAMILY == OS_FAMILY_WINDOWS + +static int makedir(const _tinydir_char_t *dir) +{ + return _wmkdir(dir); +} +#endif + namespace sibs { #if OS_FAMILY == OS_FAMILY_POSIX @@ -263,45 +276,21 @@ namespace sibs fclose(file); return Result::Ok(true); } -#if OS_FAMILY == OS_FAMILY_POSIX - Result getHomeDir() - { - const char *homeDir = getenv("HOME"); - if(!homeDir) - { - passwd *pw = getpwuid(getuid()); - homeDir = pw->pw_dir; - } - return Result::Ok(homeDir); - } - - Result getCwd() - { - FileString cwd; - cwd.resize(_TINYDIR_PATH_MAX); - if(getcwd(&cwd[0], _TINYDIR_PATH_MAX) != 0) - { - if(cwd.empty()) cwd = "."; - cwd.resize(_tinydir_strlen(cwd.c_str())); - return Result::Ok(cwd); - } - return Result::Err(strerror(errno)); - } Result createDirectory(const _tinydir_char_t *path) { - size_t pathLength = strlen(path); - if(pathLength > _TINYDIR_PATH_MAX - 1) + size_t pathLength = _tinydir_strlen(path); + if (pathLength > _TINYDIR_PATH_MAX - 1) { string errMsg = "Directory path too long: "; - errMsg += string(path, pathLength); + errMsg += toUtf8(FileString(path, pathLength)); return Result::Err(errMsg, ENAMETOOLONG); } - if(mkdir(path, S_IRWXU) != 0) + if (makedir(path) != 0) { int error = errno; - if(error != EEXIST) + if (error != EEXIST) { string errMsg = "Failed to create directory: "; errMsg += toUtf8(path); @@ -315,47 +304,46 @@ namespace sibs Result createDirectoryRecursive(const _tinydir_char_t *path) { - char pathBuffer[_TINYDIR_PATH_MAX]; - size_t pathLength = strlen(path); - if(pathLength > sizeof(pathBuffer) - 1) + _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 += string(path, pathLength); + errMsg += toUtf8(FileString(path, pathLength)); return Result::Err(errMsg, ENAMETOOLONG); } - strcpy(pathBuffer, path); + _tinydir_strcpy(pathBuffer, path); - char *p = pathBuffer; - for(size_t i = 0; i < pathLength; ++i) + _tinydir_char_t *p = pathBuffer; + for (size_t i = 0; i < pathLength; ++i) { - char c = *p; - if(i > 0 && (c == '/' || c == '\\')) + if (i > 0 && *p == '/') { *p = '\0'; - if(mkdir(pathBuffer, S_IRWXU) != 0) + if (makedir(pathBuffer) != 0) { int error = errno; - if(error != EEXIST) + if (error != EEXIST) { string errMsg = "Failed to create directory: "; - errMsg += pathBuffer; + errMsg += toUtf8(pathBuffer); errMsg += "; reason: "; errMsg += strerror(error); return Result::Err(errMsg, error); } } - *p = c; + *p = '/'; } ++p; } - if(mkdir(pathBuffer, S_IRWXU) != 0) + if (makedir(pathBuffer) != 0) { int error = errno; - if(error != EEXIST) + if (error != EEXIST) { string errMsg = "Failed to create directory: "; - errMsg += pathBuffer; + errMsg += toUtf8(pathBuffer); errMsg += "; reason: "; errMsg += strerror(error); return Result::Err(errMsg, error); @@ -365,6 +353,31 @@ namespace sibs return Result::Ok(true); } +#if OS_FAMILY == OS_FAMILY_POSIX + Result getHomeDir() + { + const char *homeDir = getenv("HOME"); + if(!homeDir) + { + passwd *pw = getpwuid(getuid()); + homeDir = pw->pw_dir; + } + return Result::Ok(homeDir); + } + + Result getCwd() + { + FileString cwd; + cwd.resize(_TINYDIR_PATH_MAX); + if(getcwd(&cwd[0], _TINYDIR_PATH_MAX) != 0) + { + if(cwd.empty()) cwd = "."; + cwd.resize(_tinydir_strlen(cwd.c_str())); + return Result::Ok(cwd); + } + return Result::Err(strerror(errno)); + } + Result getRealPath(const _tinydir_char_t *path) { // TODO: Verify NULL can be passed as 'resolved' argument with different compilers and operating systems (clang, freebsd etc) @@ -420,57 +433,6 @@ namespace sibs return Result::Ok(cwd); } - Result 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::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::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::Err(errMsg, error); - } - } - - return Result::Ok(true); - } - Result getRealPath(const _tinydir_char_t *path) { FileString fullPath; diff --git a/src/PkgConfig.cpp b/src/PkgConfig.cpp index 3a36f39..faed146 100644 --- a/src/PkgConfig.cpp +++ b/src/PkgConfig.cpp @@ -1,5 +1,4 @@ #include "../include/PkgConfig.hpp" -#if OS_FAMILY == OS_FAMILY_POSIX #include "../include/Exec.hpp" #include "../include/Dependency.hpp" @@ -35,9 +34,9 @@ namespace sibs Result PkgConfig::validatePackageExists(const string &name) { - string command = "pkg-config --exists '"; - command += name; - command += "'"; + FileString command = TINYDIR_STRING("pkg-config --exists '"); + command += toFileString(name); + command += TINYDIR_STRING("'"); Result execResult = exec(command.c_str()); if(execResult.isErr()) return Result::Err(execResult.getErrMsg()); @@ -69,11 +68,11 @@ namespace sibs // Use --modversion instead and check if the version returned is newer or equal to dependency version. // This way we can output installed version vs expected dependency version - string command = "pkg-config '--atleast-version="; - command += version; - command += "' '"; - command += name; - command += "'"; + FileString command = TINYDIR_STRING("pkg-config '--atleast-version="); + command += toFileString(version); + command += TINYDIR_STRING("' '"); + command += toFileString(name); + command += TINYDIR_STRING("'"); Result execResult = exec(command.c_str()); if(execResult.isErr()) return Result::Err(execResult.getErrMsg()); @@ -112,8 +111,8 @@ namespace sibs args += "'"; } - string command = "pkg-config --libs"; - command += args; + FileString command = TINYDIR_STRING("pkg-config --libs"); + command += toFileString(args); Result execResult = exec(command.c_str()); if(execResult.isErr()) return Result::Err(execResult.getErrMsg()); @@ -155,8 +154,8 @@ namespace sibs args += "'"; } - string command = "pkg-config --cflags"; - command += args; + FileString command = TINYDIR_STRING("pkg-config --cflags"); + command += toFileString(args); Result execResult = exec(command.c_str()); if(execResult.isErr()) return Result::Err(execResult.getErrMsg()); @@ -202,5 +201,4 @@ namespace sibs flags.cflags = move(cflagsResult.unwrap()); return Result::Ok(flags); } -} -#endif // OS_FAMILY_POSIX +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index cb1c611..1da5202 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -227,15 +227,32 @@ static bool isPathSubPathOf(const FileString &path, const FileString &subPathOf) } #if OS_FAMILY == OS_FAMILY_WINDOWS -static char* join(const char *str1, const char *str2, const char separator) +static char* join(const vector &strs, const char separator) { - 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'; + vector lengths; + lengths.reserve(strs.size()); + int totalLength = strs.size() - 1; + for (const char *str : strs) + { + int length = strlen(str); + totalLength += length; + lengths.push_back(length); + } + + char *result = new char[totalLength + 1]; + result[totalLength] = '\0'; + int offset = 0; + for (int i = 0; i < strs.size(); ++i) + { + if (i > 0) + { + result[offset] = separator; + ++offset; + } + memcpy(result + offset, strs[i], lengths[i]); + offset += lengths[i]; + } + return result; } @@ -246,9 +263,17 @@ struct MicrosoftBuildTool // empty if not found char binPath[_TINYDIR_PATH_MAX]; // empty if not found + char vsLibPath[_TINYDIR_PATH_MAX]; + // empty if not found char umLibPath[_TINYDIR_PATH_MAX]; // empty if not found char ucrtLibPath[_TINYDIR_PATH_MAX]; + // empty if not found + char vsIncludePath[_TINYDIR_PATH_MAX]; + // empty if not found + char umIncludePath[_TINYDIR_PATH_MAX]; + // empty if not found + char ucrtIncludePath[_TINYDIR_PATH_MAX]; bool found() { @@ -259,32 +284,41 @@ struct MicrosoftBuildTool static MicrosoftBuildTool locateLatestMicrosoftBuildTool() { MicrosoftBuildTool result = { 0 }; - Result execResult = exec(TINYDIR_STRING("locate_windows_sdk")); + Result execResult = exec(TINYDIR_STRING("locate_windows_sdk x64")); 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); + sscanf(execResult.unwrap().execStdout.c_str(), "%d %[^\r\n] %[^\r\n] %[^\r\n] %[^\r\n] %[^\r\n] %[^\r\n] %[^\r\n]", + &result.version, + result.binPath, + result.vsLibPath, + result.umLibPath, + result.ucrtLibPath, + result.vsIncludePath, + result.umIncludePath, + result.ucrtIncludePath); } return result; } +// We do not free allocated data here because they needs to live as long as they're used as env (in _putenv) 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) + 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) + if (_putenv_s("INCLUDE", join({ msBuildTool.vsIncludePath, msBuildTool.umIncludePath, msBuildTool.ucrtIncludePath }, ';')) != 0) + fprintf(stderr, "Warning: Failed to add microsoft build libraries to INCLUDE env\n"); + + if (_putenv_s("LIB", join({ msBuildTool.vsLibPath, msBuildTool.umLibPath, msBuildTool.ucrtLibPath }, ';')) != 0) fprintf(stderr, "Warning: Failed to add microsoft build libraries to LIB env\n"); } } -- cgit v1.2.3