Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows Build Support #116

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
.DS_Store
CMakeLists.txt.user

build/
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,12 +171,15 @@ int main() {

```

## Windows Support

We don’t have equivalent instructions for Windows.
[vcpkg](https://vcpkg.io/en/index.html) looks like a promising package manager
for Windows, but the cmake build system needs more massaging to work.\
Contributions welcome! :-)
## Windows Installation
Windows support add the extra dependecy of [vcpkg](https://vcpkg.io/en/index.html) to manage all dependencies. It uses a manifest file (vcpkg.json) located in the root directory of the source directory. Currently, the manifest file includes by default qt5-base library, which is required by the VRS player tool.
Installation was performed on Windows11 machine using both VS2019 and VS2022.

- Install [vcpkg](https://vcpkg.io/en/index.html) package manager to a directory of your choice on your local machine, following the instructions of the [site](https://vcpkg.io/en/getting-started.html).
- Use CMake to build the project (GUI or command line)
- GUI case: Choose appropriate compiler and choose _Specify toolchain file for cross-compiling_ option, press next that will require a path to the toolchain file, which is located at **\<VCPKG_INSTALLATION_PATH\>/scripts/buildsystems/vcpkg.cmake**. Then hit configure and generate and your project should be built. Configure will download and install all required libraries and will take some time.
- Command Line: Search for "Native Tools Command Prompt" in Start menu and choose the appropriate compiler (VS2019 or VS2022). Navigate to the VRS directory `cd <PATH_TO_VRS>` and run `cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=<VCPKG_INSTALLATION_PATH>/scripts/buildsystems/vcpkg.cmake` which will create a directory named **build** that containts the buiid files. This will download and install all required libraries and will take a while.
- Compile the project

## Container build & Usage

Expand Down
6 changes: 3 additions & 3 deletions tools/vrs/VrsCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,8 @@ VrsCommand::VrsCommand() {
}
}

bool VrsCommand::parseCommand(const std::string& appName, const char* cmdName) {
cmd = CommandConverter::toEnum(cmdName);
bool VrsCommand::parseCommand(const std::string& appName, const std::string cmdName) {
cmd = CommandConverter::toEnum(cmdName.c_str());
if (cmd != Command::None) {
return XR_VERIFY(getCommandSpec(cmd).cmd == cmd);
}
Expand All @@ -310,7 +310,7 @@ bool VrsCommand::parseArgument(
const string& appName,
int& argn,
int argc,
char** argv,
std::vector<std::string> argv,
int& outStatusCode) {
string arg = argv[argn];
if (arg == "-to" || arg == "--to") {
Expand Down
10 changes: 7 additions & 3 deletions tools/vrs/VrsCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ enum class Command {
struct VrsCommand {
VrsCommand();

bool parseCommand(const std::string& appName, const char* cmdName);
bool parseCommand(const std::string& appName, const std::string cmdName);

/// Parse a "logical" command line argument, which may have one or more parts.
/// @param appName: Name of the application binary for error messages
Expand All @@ -78,8 +78,12 @@ struct VrsCommand {
/// On the other hand, if the argument and possible sub-arguments were valid,
/// outStatusCode is unchanged (presumably, it's still set to EXIT_SUCCESS),
/// and the next argument parameter to parse is at argn + 1.
bool
parseArgument(const std::string& appName, int& argn, int argc, char** argv, int& outStatusCode);
bool parseArgument(
const std::string& appName,
int& argn,
int argc,
std::vector<std::string> argv,
int& outStatusCode);

/// Handle a parameter not recognized by parseArgument and potential additional parsing.
/// Unrecognized arguments are expected to be additional file paths for merge operations.
Expand Down
30 changes: 29 additions & 1 deletion tools/vrs/vrs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,39 @@

#include <iostream>

#include <Windows.h>
#include <vrs/os/Utils.h>

namespace {

inline std::vector<std::string> compute_win32_argv() {
std::vector<std::string> result;
int argc = 0;

auto deleter = [](wchar_t** ptr) { LocalFree(ptr); };
// NOLINTBEGIN(*-avoid-c-arrays)
auto wargv = std::unique_ptr<wchar_t*[], decltype(deleter)>(
CommandLineToArgvW(GetCommandLineW(), &argc), deleter);
// NOLINTEND(*-avoid-c-arrays)

if (wargv == nullptr) {
throw std::runtime_error(
"CommandLineToArgvW failed with code " + std::to_string(GetLastError()));
}

result.reserve(static_cast<size_t>(argc));
for (size_t i = 0; i < static_cast<size_t>(argc); ++i) {
result.push_back(vrs::os::osWstringtoUtf8(wargv[i]));
}

return result;
}
} // namespace

using namespace std;

int main(int argc, char** argv) {
int main(int argc, char** argv_old) {
auto argv = compute_win32_argv();
const string& appName = vrs::os::getFilename(argv[0]);
if (argc == 1) {
printHelp(appName);
Expand Down
24 changes: 24 additions & 0 deletions vcpkg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "vrs",
"version-string": "0.1.0",
"dependencies": [
"boost-filesystem",
"boost-chrono",
"boost-date-time",
"boost-thread",
"boost-uuid",
"boost-process",
"boost-interprocess",
"fmt",
"cereal",
"libpng",
"libjpeg-turbo",
"lz4",
"xxhash",
"glog",
"zstd",
"gtest",
"portaudio",
"qt5-base"
]
}
10 changes: 10 additions & 0 deletions vrs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ target_include_directories(vrslib
$<BUILD_INTERFACE:${VRS_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>
)

if(MSVC)
target_link_libraries(vrslib
PRIVATE
bcrypt
)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj")
endif(MSVC)

target_link_libraries(vrslib
PUBLIC
vrs_helpers
Expand Down
2 changes: 1 addition & 1 deletion vrs/MultiRecordFileReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ uint32_t MultiRecordFileReader::getRecordCount() const {
if (hasSingleFile()) {
return readers_.front()->getRecordCount();
}
return XR_DEV_PRECONDITION_NOTNULL(recordIndex_)->size();
return (uint32_t)XR_DEV_PRECONDITION_NOTNULL(recordIndex_)->size();
}

uint32_t MultiRecordFileReader::getRecordCount(UniqueStreamId uniqueStreamId) const {
Expand Down
23 changes: 22 additions & 1 deletion vrs/os/System.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,10 @@ string vrs::os::getOsFingerPrint() {
DWORD dwMajorVersion = 0;
DWORD dwMinorVersion = 0;
DWORD dwBuild = 0;
dwVersion = GetVersion();

#if _MSC_VER < 1900

dwVersion = GetVersion();
// Get the Windows version.
dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
Expand All @@ -99,6 +101,25 @@ string vrs::os::getOsFingerPrint() {
if (dwVersion < 0x80000000) {
dwBuild = (DWORD)(HIWORD(dwVersion));
}

#else

OSVERSIONINFOEX versionInfo;
DWORD dwMask = 0;
DWORDLONG dwlConditionMask = 0;
ZeroMemory(&versionInfo, sizeof(OSVERSIONINFOEX));
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
VerifyVersionInfo(
&versionInfo, VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER, dwlConditionMask);

dwMajorVersion = versionInfo.dwMajorVersion;
dwMinorVersion = versionInfo.dwMinorVersion;
dwBuild = versionInfo.dwBuildNumber;
#endif

string osFingerprintString;
osFingerprintString = "Windows ";
osFingerprintString += to_string(dwMajorVersion);
Expand Down
9 changes: 7 additions & 2 deletions vrs/os/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ namespace os {
std::wstring osUtf8ToWstring(const string& utf8String) {
return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().from_bytes(utf8String);
}

std::string osWstringtoUtf8(const std::wstring& wstring) {
return std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(wstring);
}
#endif // IS_WINDOWS_PLATFORM()

FILE* fileOpen(const string& path, const char* modes) {
Expand Down Expand Up @@ -211,6 +215,7 @@ bool getLinkedTarget(const string& sourcePath, string& outLinkedPath) {
if (fs::symlink_status(source).type() == fs::symlink_file) {
// Note: apply canonical() instead of readlink()
// so that relative paths in symlinks are resolved properly

outLinkedPath = fs::canonical(source).string();
return true;
}
Expand Down Expand Up @@ -328,7 +333,7 @@ bool isDir(const string& path) {

bool isFile(const string& path) {
fs_error_code ec;
auto type = fs::status(fs::path(path), ec).type(); // This will traverse symlinks
auto type = fs::status(fs::path(osUtf8ToWstring(path)), ec).type(); // This will traverse symlinks
if (ec) { // Underlying OS API error - we cannot access it.
return false;
}
Expand Down Expand Up @@ -356,7 +361,7 @@ bool pathExists(const string& path) {

int64_t getFileSize(const string& path) {
fs_error_code ec;
auto size = fs::file_size(fs::path(path), ec);
auto size = fs::file_size(fs::path(osUtf8ToWstring(path)), ec);
if (ec) {
return -1;
}
Expand Down
5 changes: 5 additions & 0 deletions vrs/os/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
namespace vrs {
namespace os {

#if IS_WINDOWS_PLATFORM()
std::wstring osUtf8ToWstring(const std::string& utf8String);
std::string osWstringtoUtf8(const std::wstring& wstring);
#endif // IS_WINDOWS_PLATFORM()

/// FILE helpers
std::FILE* fileOpen(const std::string& path, const char* modes);
int fileClose(std::FILE* file);
Expand Down
4 changes: 4 additions & 0 deletions vrs/oss/logging/Checks.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ void logAndAbort(const std::string& condition, const std::string& message = {});
#define XR_CHECK_FORMAT(condition, ...) \
(condition ? 0 : ((vrs::logging::logAndAbort(#condition, fmt::format(__VA_ARGS__))), 0))

#ifdef IS_WINDOWS_PLATFORM
#define XR_CHECK(condition, ...) XR_CHECK_FORMAT(condition, "", ##__VA_ARGS__)
#else
#define XR_CHECK(condition, ...) XR_CHECK_FORMAT(condition, ##__VA_ARGS__, "")
#endif

#define XR_CHECK_EQ(val1, val2, ...) XR_CHECK((val1) == (val2), ##__VA_ARGS__)

Expand Down
4 changes: 4 additions & 0 deletions vrs/oss/logging/Verify.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,8 @@
fmt::format(__VA_ARGS__)), \
0))

#ifdef IS_WINDOWS_PLATFORM
#define XR_VERIFY(cond, ...) XR_VERIFY_C(DEFAULT_LOG_CHANNEL, cond, "", ##__VA_ARGS__)
#else
#define XR_VERIFY(cond, ...) XR_VERIFY_C(DEFAULT_LOG_CHANNEL, cond, ##__VA_ARGS__, "")
#endif
10 changes: 5 additions & 5 deletions vrs/utils/cli/CliParsing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ bool parseCopyOptions(
const string& arg,
int& argn,
int argc,
char** argv,
std::vector<std::string> argv,
int& outStatusCode,
CopyOptions& copyOptions) {
if (arg == "--no-progress") {
Expand Down Expand Up @@ -116,7 +116,7 @@ bool parseTagOverrideOptions(
const string& arg,
int& argn,
int argc,
char** argv,
std::vector<std::string> argv,
int& outStatusCode,
CopyOptions& copyOptions) {
if (arg == "--file-tag") {
Expand Down Expand Up @@ -174,7 +174,7 @@ bool parseTimeAndStreamFilters(
const string& arg,
int& argn,
int argc,
char** argv,
std::vector<std::string> argv,
int& outStatusCode,
FilteredFileReader& filteredReader,
RecordFilterParams& outFilters) {
Expand Down Expand Up @@ -214,7 +214,7 @@ bool parseTimeAndStreamFilters(
if (argn + 2 < argc) {
try {
filteredReader.filter.minTime = stod(argv[++argn]);
filteredReader.filter.relativeMinTime = isSigned(argv[argn]);
filteredReader.filter.relativeMinTime = isSigned(argv[argn].c_str());
filteredReader.filter.maxTime = stod(argv[++argn]);
filteredReader.filter.aroundTime = true;
} catch (logic_error&) {
Expand Down Expand Up @@ -286,7 +286,7 @@ bool parseDecimationOptions(
const string& arg,
int& argn,
int argc,
char** argv,
std::vector<std::string> argv,
int& outStatusCode,
RecordFilterParams& outFilters) {
if (arg == "--decimate") {
Expand Down
8 changes: 4 additions & 4 deletions vrs/utils/cli/CliParsing.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ bool parseCopyOptions(
const string& arg,
int& argn,
int argc,
char** argv,
std::vector<std::string> argv,
int& outStatusCode,
CopyOptions& copyOptions);
/// Print copy options help
Expand All @@ -72,7 +72,7 @@ bool parseTagOverrideOptions(
const string& arg,
int& argn,
int argc,
char** argv,
std::vector<std::string> argv,
int& outStatusCode,
CopyOptions& copyOptions);
/// Print tag override help
Expand Down Expand Up @@ -101,7 +101,7 @@ bool parseTimeAndStreamFilters(
const string& arg,
int& argn,
int argc,
char** argv,
std::vector<std::string> argv,
int& outStatusCode,
FilteredFileReader& filteredReader,
RecordFilterParams& outFilters);
Expand Down Expand Up @@ -129,7 +129,7 @@ bool parseDecimationOptions(
const string& arg,
int& argn,
int argc,
char** argv,
std::vector<std::string> argv,
int& outStatusCode,
RecordFilterParams& outFilters);
/// Print decimation options help
Expand Down
4 changes: 4 additions & 0 deletions vrs/utils/test/JxlTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
* limitations under the License.
*/

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

#include <gtest/gtest.h>

#include <math.h>
Expand Down