Initial MSVC build working

This commit is contained in:
Bartek Kryza
2023-01-06 23:39:56 +00:00
parent 476a7873f9
commit f5bcbeec0b
16 changed files with 106 additions and 42 deletions

View File

@@ -49,6 +49,11 @@ message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
message(STATUS "LLVM library dir: ${LLVM_LIBRARY_DIR}") message(STATUS "LLVM library dir: ${LLVM_LIBRARY_DIR}")
if(MSVC)
# LLVM_BUILD_LLVM_DYLIB is not available on Windows
set(LINK_LLVM_SHARED NO)
endif(MSVC)
if(LINK_LLVM_SHARED) if(LINK_LLVM_SHARED)
set(LIBTOOLING_LIBS clang-cpp LLVM) set(LIBTOOLING_LIBS clang-cpp LLVM)
else(LINK_LLVM_SHARED) else(LINK_LLVM_SHARED)
@@ -59,6 +64,7 @@ else(LINK_LLVM_SHARED)
clangDriver clangDriver
clangParse clangParse
clangSema clangSema
clangSupport
clangAnalysis clangAnalysis
clangAST clangAST
clangBasic clangBasic
@@ -78,8 +84,19 @@ else(LINK_LLVM_SHARED)
LLVMBitReader LLVMBitReader
LLVMCore LLVMCore
LLVMSupport) LLVMSupport)
if(MSVC)
list(APPEND LIBTOOLING_LIBS
LLVMWindowsDriver
LLVMWindowsManifest)
endif(MSVC)
endif(LINK_LLVM_SHARED) endif(LINK_LLVM_SHARED)
if("${LIBTOOLING_LIBS}" STREQUAL "")
message(FATAL_ERROR "Failed to find LibTooling libraries!")
else()
message(STATUS "Found LibTooling libraries: ${LIBTOOLING_LIBS}")
endif()
# #
# Setup threads library # Setup threads library
# #
@@ -90,22 +107,28 @@ find_package(Threads REQUIRED)
# #
message(STATUS "Checking for yaml-cpp...") message(STATUS "Checking for yaml-cpp...")
if(APPLE) if(APPLE)
find_package(PkgConfig) find_package(PkgConfig)
if(PKG_CONFIG_FOUND) if(PKG_CONFIG_FOUND)
pkg_check_modules(YAML_CPP yaml-cpp) pkg_check_modules(YAML_CPP yaml-cpp)
find_path(YAML_CPP_INCLUDE_DIR find_path(YAML_CPP_INCLUDE_DIR
NAMES yaml.h NAMES yaml.h
PATHS ${YAML_CPP_INCLUDE_DIR} /usr/local/include/yaml-cpp) PATHS ${YAML_CPP_INCLUDE_DIR} /usr/local/include/yaml-cpp)
find_library(YAML_CPP_LIBRARY find_library(YAML_CPP_LIBRARY
NAMES yaml-cpp NAMES yaml-cpp
PATHS ${YAML_CPP_LIBRARIES} /usr/local/lib) PATHS ${YAML_CPP_LIBRARIES} /usr/local/lib)
set(YAML_CPP_LIBRARY_DIR /usr/local/lib) set(YAML_CPP_LIBRARY_DIR /usr/local/lib)
endif() endif(PKG_CONFIG_FOUND)
else(APPLE) elseif(MSVC)
set(YAML_CPP_LIBRARIES "yaml-cpp")
else()
find_package(yaml-cpp REQUIRED) find_package(yaml-cpp REQUIRED)
endif(APPLE) endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -std=c++17 -Wno-unused-parameter -Wno-unused-private-field") if("${YAML_CPP_LIBRARIES}" STREQUAL "")
message(FATAL_ERROR "Failed to find yaml-cpp library!")
else()
message(STATUS "Found yaml-cpp libraries: ${YAML_CPP_LIBRARIES}")
endif()
link_directories(${LLVM_LIBRARY_DIR} ${YAML_CPP_LIBRARY_DIR}) link_directories(${LLVM_LIBRARY_DIR} ${YAML_CPP_LIBRARY_DIR})
@@ -129,7 +152,13 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
OUTPUT_VARIABLE GCC_STDDEF_INCLUDE) OUTPUT_VARIABLE GCC_STDDEF_INCLUDE)
message(STATUS "FOUND GCC STDDEF INCLUDE ${GCC_STDDEF_INCLUDE}") message(STATUS "FOUND GCC STDDEF INCLUDE ${GCC_STDDEF_INCLUDE}")
include_directories(${GCC_STDDEF_INCLUDE}) include_directories(${GCC_STDDEF_INCLUDE})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -std=c++17 -Wno-unused-parameter -Wno-unused-private-field")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${GCC_STDDEF_INCLUDE}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${GCC_STDDEF_INCLUDE}")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -std=c++17 -Wno-unused-parameter -Wno-unused-private-field")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DLLVM_FORCE_USE_OLD_TOOLCHAIN /W1 /std:c++17 /bigobj /wd4291 /wd4624 /wd4244")
set(LINK_OPTIONS "${LINK_OPTIONS} /NODEFAULTLIB:MSVCRT /NODEFAULTLIB:MSVCRTD")
endif() endif()
message(STATUS "Using CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}") message(STATUS "Using CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
@@ -145,7 +174,6 @@ include_directories(${THIRDPARTY_HEADERS_DIR})
include_directories(${PROJECT_SOURCE_DIR}/src/) include_directories(${PROJECT_SOURCE_DIR}/src/)
include_directories(${PROJECT_BINARY_DIR}/src/version) include_directories(${PROJECT_BINARY_DIR}/src/version)
# #
# Generate source list dynamically # Generate source list dynamically
# #
@@ -153,19 +181,25 @@ file(GLOB_RECURSE SOURCES src/*.cc include/*.h)
set(MAIN_SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc) set(MAIN_SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc)
list(REMOVE_ITEM SOURCES ${MAIN_SOURCE_FILE}) list(REMOVE_ITEM SOURCES ${MAIN_SOURCE_FILE})
# #
# Define library target for linking with test cases and output executable # Define library target for linking with test cases and output executable
# #
add_library(clang-umllib OBJECT ${SOURCES}) if(MSVC)
add_library(clang-umllib STATIC ${SOURCES})
set(MSVC_LIBRARIES "version")
else(MSVC)
add_library(clang-umllib OBJECT ${SOURCES})
endif(MSVC)
# #
# Define the target executable clang-uml # Define the target executable clang-uml
# #
add_executable(clang-uml ${MAIN_SOURCE_FILE}) add_executable(clang-uml ${MAIN_SOURCE_FILE})
target_link_libraries(clang-uml target_link_libraries(clang-uml
${YAML_CPP_LIBRARIES} ${YAML_CPP_LIBRARIES}
${LIBTOOLING_LIBS} ${LIBTOOLING_LIBS}
${MSVC_LIBRARIES}
clang-umllib clang-umllib
Threads::Threads) Threads::Threads)

View File

@@ -32,8 +32,6 @@ public:
clanguml::common::id_t id() const noexcept { return id_; } clanguml::common::id_t id() const noexcept { return id_; }
void set_id(clanguml::common::id_t id) { id_ = id; } void set_id(clanguml::common::id_t id) { id_ = id; }
void set_id(id_t id);
void is_virtual(bool is_virtual); void is_virtual(bool is_virtual);
bool is_virtual() const; bool is_virtual() const;

View File

@@ -763,6 +763,7 @@ void translation_unit_visitor::process_class_children(
// Static fields have to be processed by iterating over variable // Static fields have to be processed by iterating over variable
// declarations // declarations
#ifndef _MSC_VER
for (const auto *decl : cls->decls()) { for (const auto *decl : cls->decls()) {
if (decl->getKind() == clang::Decl::Var) { if (decl->getKind() == clang::Decl::Var) {
const clang::VarDecl *variable_declaration{ const clang::VarDecl *variable_declaration{
@@ -788,7 +789,7 @@ void translation_unit_visitor::process_class_children(
} }
} }
} }
#endif
if (cls->isCompleteDefinition()) if (cls->isCompleteDefinition())
for (const auto *friend_declaration : cls->friends()) { for (const auto *friend_declaration : cls->friends()) {
if (friend_declaration != nullptr) if (friend_declaration != nullptr)
@@ -1429,7 +1430,7 @@ std::unique_ptr<class_> translation_unit_visitor::
template_instantiation.set_name(template_decl->getNameAsString()); template_instantiation.set_name(template_decl->getNameAsString());
template_instantiation.set_namespace(ns); template_instantiation.set_namespace(ns);
template_instantiation.set_id(template_decl->getID() + template_instantiation.set_id(template_decl->getID() +
static_cast<id_t>( static_cast<common::id_t>(
std::hash<std::string>{}(full_template_specialization_name) >> 4U)); std::hash<std::string>{}(full_template_specialization_name) >> 4U));
build_template_instantiation_process_template_arguments(parent, build_template_instantiation_process_template_arguments(parent,

View File

@@ -191,14 +191,17 @@ inja::json generator<C, D>::element_context(const E &e) const
if (!e.file().empty()) { if (!e.file().empty()) {
std::filesystem::path file{e.file()}; std::filesystem::path file{e.file()};
std::string relative_path = file.string(); std::string relative_path = file.string();
#if _MSC_VER
if (file.is_absolute() && ctx.contains("git"))
#else
if (file.is_absolute() && ctx.template contains("git")) if (file.is_absolute() && ctx.template contains("git"))
#endif
relative_path = relative_path =
std::filesystem::relative(file, ctx["git"]["toplevel"]); std::filesystem::relative(file, ctx["git"]["toplevel"]).string();
ctx["element"]["source"]["path"] = relative_path; ctx["element"]["source"]["path"] = relative_path;
ctx["element"]["source"]["full_path"] = file.string(); ctx["element"]["source"]["full_path"] = file.string();
ctx["element"]["source"]["name"] = file.filename(); ctx["element"]["source"]["name"] = file.filename().string();
ctx["element"]["source"]["line"] = e.line(); ctx["element"]["source"]["line"] = e.line();
} }

View File

@@ -184,12 +184,12 @@ tvl::value_t namespace_filter::match(
auto namespace_starts_with_element_qualified_name = auto namespace_starts_with_element_qualified_name =
nsit.starts_with(e.get_namespace()); nsit.starts_with(e.get_namespace());
auto result = element_full_name_starts_with_namespace | auto result = element_full_name_starts_with_namespace ||
element_full_name_equals_pattern; element_full_name_equals_pattern;
if (is_inclusive) if (is_inclusive)
result = result =
result | namespace_starts_with_element_qualified_name; result || namespace_starts_with_element_qualified_name;
return result; return result;
}); });

View File

@@ -53,7 +53,7 @@ public:
explicit source_file(const std::filesystem::path &p) explicit source_file(const std::filesystem::path &p)
{ {
set_path({p.parent_path().string()}); set_path({p.parent_path().string()});
set_name(p.filename()); set_name(p.filename().string());
is_absolute_ = p.is_absolute(); is_absolute_ = p.is_absolute();
set_id(common::to_id(p)); set_id(common::to_id(p));
} }

View File

@@ -103,7 +103,7 @@ protected:
private: private:
clang::SourceManager &source_manager_; clang::SourceManager &source_manager_;
const clanguml::config::diagram &config_; [[maybe_unused]] const clanguml::config::diagram &config_;
std::unique_ptr<comment::comment_visitor> comment_visitor_; std::unique_ptr<comment::comment_visitor> comment_visitor_;
}; };

View File

@@ -62,7 +62,7 @@ decorator_toks decorator::tokenize(const std::string &label, std::string_view c)
decorator_toks res; decorator_toks res;
res.label = label; res.label = label;
size_t pos{}; size_t pos{};
const auto *it = c.begin(); auto it = c.begin();
std::advance(it, label.size()); std::advance(it, label.size());
if (*it == ':') { if (*it == ':') {

View File

@@ -104,7 +104,7 @@ public:
void finalize() { } void finalize() { }
private: private:
clang::SourceManager &source_manager_; [[maybe_unused]] clang::SourceManager &source_manager_;
// Reference to the output diagram model // Reference to the output diagram model
clanguml::include_diagram::model::diagram &diagram_; clanguml::include_diagram::model::diagram &diagram_;

View File

@@ -551,7 +551,7 @@ int add_config_diagram(clanguml::common::model::diagram_t type,
return 1; return 1;
} }
YAML::Node doc = YAML::LoadFile(config_file); YAML::Node doc = YAML::LoadFile(config_file.string());
for (YAML::const_iterator it = doc["diagrams"].begin(); for (YAML::const_iterator it = doc["diagrams"].begin();
it != doc["diagrams"].end(); ++it) { it != doc["diagrams"].end(); ++it) {

View File

@@ -220,6 +220,7 @@ void translation_unit_visitor::process_class_children(
// Static fields have to be processed by iterating over variable // Static fields have to be processed by iterating over variable
// declarations // declarations
#ifndef _MSC_VER
for (const auto *decl : cls.decls()) { for (const auto *decl : cls.decls()) {
if (decl->getKind() == clang::Decl::Var) { if (decl->getKind() == clang::Decl::Var) {
const clang::VarDecl *variable_declaration{ const clang::VarDecl *variable_declaration{
@@ -230,6 +231,7 @@ void translation_unit_visitor::process_class_children(
} }
} }
} }
#endif
if (cls.isCompleteDefinition()) if (cls.isCompleteDefinition())
for (const auto *friend_declaration : cls.friends()) { for (const auto *friend_declaration : cls.friends()) {

View File

@@ -49,12 +49,16 @@ void setup_logging(int verbose)
std::string get_process_output(const std::string &command) std::string get_process_output(const std::string &command)
{ {
constexpr size_t kBufferSize{1024}; constexpr size_t kBufferSize{1024};
std::array<char, kBufferSize> buffer{}; std::array<char, kBufferSize> buffer{};
std::string result; std::string result;
#if defined(__linux) || defined(__unix)
std::unique_ptr<FILE, decltype(&pclose)> pipe( std::unique_ptr<FILE, decltype(&pclose)> pipe(
popen(command.c_str(), "r"), pclose); popen(command.c_str(), "r"), pclose);
#elif defined(WINDOWS) || defined(_WIN32) || defined(WIN32)
std::unique_ptr<FILE, decltype(&_pclose)> pipe(
_popen(command.c_str(), "r"), _pclose);
#endif
if (!pipe) { if (!pipe) {
throw std::runtime_error("popen() failed!"); throw std::runtime_error("popen() failed!");
} }
@@ -68,12 +72,25 @@ std::string get_process_output(const std::string &command)
std::string get_env(const std::string &name) std::string get_env(const std::string &name)
{ {
#if defined(__linux) || defined(__unix)
const char *value = std::getenv(name.c_str()); // NOLINT const char *value = std::getenv(name.c_str()); // NOLINT
if (value == nullptr) if (value == nullptr)
return {}; return {};
return std::string{value}; return std::string{value};
#elif defined(WINDOWS) || defined(_WIN32) || defined(WIN32)
static constexpr auto kMaxEnvLength = 2096U;
static char value[kMaxEnvLength];
const DWORD ret =
GetEnvironmentVariableA(name.c_str(), value, kMaxEnvLength);
if (ret == 0 || ret > kMaxEnvLength)
return {};
else
return value;
#else
return {};
#endif
} }
bool is_git_repository() bool is_git_repository()
@@ -83,13 +100,9 @@ bool is_git_repository()
if (!env.empty()) if (!env.empty())
return true; return true;
#if defined(_WIN32) || defined(_WIN64)
return false;
#else
return contains( return contains(
trim(get_process_output("git rev-parse --git-dir 2> /dev/null")), trim(get_process_output("git rev-parse --git-dir")),
".git"); ".git");
#endif
} }
std::string get_git_branch() std::string get_git_branch()

View File

@@ -4,9 +4,15 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(TEST_DISABLE_WARNINGS_DEBUG "-Wno-unused-parameter -Wno-unused-private-field -Wno-unused-variable -Wno-attributes -Wno-nonnull") if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(TEST_DISABLE_WARNINGS_RELEASE "${TEST_DISABLE_WARNINGS} -Wno-aggressive-loop-optimizations") set(TEST_DISABLE_WARNINGS_DEBUG "-Wno-unused-parameter -Wno-unused-private-field -Wno-unused-variable -Wno-attributes -Wno-nonnull")
set(TEST_DISABLE_WARNINGS_RELEASE "${TEST_DISABLE_WARNINGS} -Wno-aggressive-loop-optimizations")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(TEST_DISABLE_WARNINGS_DEBUG "-Wno-unused-parameter -Wno-unused-private-field -Wno-unused-variable -Wno-attributes -Wno-nonnull")
set(TEST_DISABLE_WARNINGS_RELEASE "${TEST_DISABLE_WARNINGS} -Wno-aggressive-loop-optimizations")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W1 /std:c++17 /bigobj /wd4624")
endif()
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} ${LIBCLANG_CXXFLAGS} ${TEST_DISABLE_WARNINGS_RELEASE}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} ${LIBCLANG_CXXFLAGS} ${TEST_DISABLE_WARNINGS_RELEASE}")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} ${LIBCLANG_CXXFLAGS} ${TEST_DISABLE_WARNINGS_DEBUG}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} ${LIBCLANG_CXXFLAGS} ${TEST_DISABLE_WARNINGS_DEBUG}")
@@ -28,6 +34,10 @@ set(CLANG_UML_TEST_LIBRARIES
${LIBTOOLING_LIBS} ${LIBTOOLING_LIBS}
Threads::Threads) Threads::Threads)
if(MSVC)
list(APPEND CLANG_UML_TEST_LIBRARIES "Version.lib")
endif(MSVC)
set(CLANG_UML_TEST_UTIL_SRC test_util.cc ${TEST_UTIL_SOURCES}) set(CLANG_UML_TEST_UTIL_SRC test_util.cc ${TEST_UTIL_SOURCES})
set(CLANG_UML_TEST_UTIL_HEADER catch.h) set(CLANG_UML_TEST_UTIL_HEADER catch.h)

View File

@@ -1,6 +1,8 @@
#pragma once #pragma once
#ifndef _MSC_VER
#include <experimental/propagate_const> #include <experimental/propagate_const>
#endif
#include <iostream> #include <iostream>
#include <memory> #include <memory>

View File

@@ -2,6 +2,7 @@
#include <map> #include <map>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <string>
namespace clanguml { namespace clanguml {
namespace t30002 { namespace t30002 {

View File

@@ -177,7 +177,7 @@ static inline fs::path expand_tilde(fs::path path)
#ifdef _WIN32 #ifdef _WIN32
char *home; char *home;
size_t sz; size_t sz;
errno_t err = _dupenv_s(&home, &sz, "USERPROFILE"); [[maybe_unused]] errno_t err = _dupenv_s(&home, &sz, "USERPROFILE");
#else #else
const char *home = std::getenv("HOME"); const char *home = std::getenv("HOME");
#endif #endif