diff --git a/.gitignore b/.gitignore index 58ed76c58b..9a40979cd9 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,12 @@ *.pyc *.pyo __pycache__ +*.pyd + +# MSVC files +*.pdb +*.dll +*.exe # workflow *.orig @@ -22,6 +28,8 @@ __pycache__ # build system /bin /.bin +/build +/deps # root dir run script /run diff --git a/CMakeLists.txt b/CMakeLists.txt index d35a78e756..4c45aabbe8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -115,7 +115,12 @@ add_subdirectory(libopenage/) # Python content (uses the C++ library) set(PYEXT_LINK_LIBRARY libopenage) -set(PYEXT_CXXFLAGS "${PYEXT_CXXFLAGS} -include \"${CMAKE_SOURCE_DIR}/libopenage/pyinterface/hacks.h\"") +if(MSVC) + set(FORCE_INCLUDE_CXXFLAG "/FI") +else() + set(FORCE_INCLUDE_CXXFLAG "-include ") +endif() +set(PYEXT_CXXFLAGS "${PYEXT_CXXFLAGS} ${FORCE_INCLUDE_CXXFLAG}\"${CMAKE_SOURCE_DIR}/libopenage/pyinterface/hacks.h\"") add_cython_modules(EMBED NOINSTALL run.py) add_py_modules(BININSTALL run.py AS openage) add_subdirectory(openage/) diff --git a/buildsystem/HandleCXXOptions.cmake b/buildsystem/HandleCXXOptions.cmake index 49acd19716..95455e5e03 100644 --- a/buildsystem/HandleCXXOptions.cmake +++ b/buildsystem/HandleCXXOptions.cmake @@ -59,7 +59,9 @@ endmacro() set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(EXTRA_FLAGS "${EXTRA_FLAGS} -Wall -Wextra -pedantic") +if(NOT MSVC) + set(EXTRA_FLAGS "${EXTRA_FLAGS} -Wall -Wextra -pedantic") +endif() # check for compiler versions if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") diff --git a/buildsystem/HandlePythonOptions.cmake b/buildsystem/HandlePythonOptions.cmake index e936ad3046..2b650378c0 100644 --- a/buildsystem/HandlePythonOptions.cmake +++ b/buildsystem/HandlePythonOptions.cmake @@ -22,8 +22,8 @@ if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set(PYEXT_CXXFLAGS "${PYEXT_CXXFLAGS} -Wno-#warnings") endif() -set(PYEXT_LIBRARY "${PYTHON_LIBRARY}") -set(PYEXT_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR};${NUMPY_INCLUDE_DIR}") +set(PYEXT_LIBRARY "${PYTHON_LIBRARIES}") +set(PYEXT_INCLUDE_DIRS "${PYTHON_INCLUDE_DIRS};${NUMPY_INCLUDE_DIR}") if(NOT CMAKE_PY_INSTALL_PREFIX) py_exec("import site, os; print(os.path.normpath(site.getsitepackages()[0]))" PREFIX) diff --git a/buildsystem/check_py_file_list.py b/buildsystem/check_py_file_list.py index 8a458d097f..5164091bc7 100644 --- a/buildsystem/check_py_file_list.py +++ b/buildsystem/check_py_file_list.py @@ -20,7 +20,7 @@ def main(): args = cli.parse_args() with open(args.py_file_list) as fileobj: - listed = set(fileobj.read().strip().split(';')) + listed = set(os.path.normpath(filepath) for filepath in fileobj.read().strip().split(';')) if listed == {''}: listed = set() diff --git a/buildsystem/cpp.cmake b/buildsystem/cpp.cmake index 53755b8362..30a6044cb1 100644 --- a/buildsystem/cpp.cmake +++ b/buildsystem/cpp.cmake @@ -29,6 +29,7 @@ function(add_sources binary_name) if(NOT IS_ABSOLUTE "${source}") set(source "${CMAKE_CURRENT_SOURCE_DIR}/${source}") endif() + file(TO_CMAKE_PATH "${source}" source) set_property( GLOBAL APPEND PROPERTY @@ -88,7 +89,7 @@ function(finalize_binary target_name output_name type) message(FATAL_ERROR "finalize_binary flag 'allow_no_undefined' is only valid for libraries!") endif() - if(NOT "${CMAKE_CXX_FLAGS}" MATCHES "-fsanitize") + if(NOT "${CMAKE_CXX_FLAGS}" MATCHES "-fsanitize" AND NOT MSVC) if(APPLE) set(link_flag "-undefined,error") else() diff --git a/buildsystem/cythonize.py b/buildsystem/cythonize.py index dae04c3add..11c8e54537 100755 --- a/buildsystem/cythonize.py +++ b/buildsystem/cythonize.py @@ -15,7 +15,7 @@ def read_list_from_file(filename): with open(filename) as fileobj: data = fileobj.read().strip() - data = data.split(';') + data = [os.path.normpath(filename) for filename in data.split(';')] if data == ['']: return [] diff --git a/buildsystem/inplacemodules.py b/buildsystem/inplacemodules.py index 155237b251..162ccaa187 100644 --- a/buildsystem/inplacemodules.py +++ b/buildsystem/inplacemodules.py @@ -1,4 +1,4 @@ -# Copyright 2015-2016 the openage authors. See copying.md for legal info. +# Copyright 2015-2017 the openage authors. See copying.md for legal info. """ Installs the Python extension modules that were created in the build directory @@ -21,6 +21,9 @@ def main(): cli.add_argument("binary_dir", help=( "the build directory where those files will be found." )) + cli.add_argument("configuration", help=( + "the build configuration like Debug or Release" + )) cli.add_argument("--clean", action="store_true", help=( "remove instead of creating" )) @@ -39,6 +42,9 @@ def main(): sourcefile = module targetfile = os.path.relpath(module, args.binary_dir) + # If `targetfile` has a configuration component, remove it. + targetfile = os.path.normpath(targetfile.replace(args.configuration, '.')) + if os.path.exists(targetfile): if args.clean: print(targetfile) diff --git a/buildsystem/modules/FindPython.cmake b/buildsystem/modules/FindPython.cmake index 9be9a84133..f7425208ae 100644 --- a/buildsystem/modules/FindPython.cmake +++ b/buildsystem/modules/FindPython.cmake @@ -12,8 +12,8 @@ # # PYTHON_FOUND - True when python was found. # PYTHON - The full path to the Python interpreter. -# PYTHON_INCLUDE_DIR - Include path for Python extensions. -# PYTHON_LIBRARY - Library and Linker options for Python extensions. +# PYTHON_INCLUDE_DIRS - Include path for Python extensions. +# PYTHON_LIBRARIES - Library and Linker options for Python extensions. # # Also defines py_exec and py_get_config_var. # @@ -54,21 +54,6 @@ function(py_get_config_var VAR RESULTVAR) set("${RESULTVAR}" "${RESULT}" PARENT_SCOPE) endfunction() -function(py_get_lib_name RESULTVAR) - # uses py_exec to compute Python's C/C++ library name, just like python-config does. - py_get_config_var(VERSION PYTHON_VERSION) - if(NOT "${PYTHON_VERSION}" VERSION_LESS "3.2") - py_exec( - "import sys; print(sys.abiflags)" - ABIFLAGS - ) - else() - set(ABIFLAGS, "") - endif() - - set("${RESULTVAR}" "python${PYTHON_VERSION}${ABIFLAGS}" PARENT_SCOPE) -endfunction() - function(find_python_interpreter_builtin) find_package(PythonInterp "${PYTHON_MIN_VERSION}" QUIET) if(PYTHONINTERP_FOUND) @@ -170,10 +155,21 @@ endforeach() # test all the found interpreters; break on success. foreach(PYTHON ${PYTHON_INTERPRETERS}) - # ask the interpreter for the essential extension-building flags - py_get_config_var(INCLUDEPY PYTHON_INCLUDE_DIR) - py_get_config_var(LIBDIR PYTHON_LIBRARY_DIR) - py_get_lib_name(PYTHON_LIBRARY_NAME) + # If the current python interpreter equals the one found at the very beginning with PythonInterp, + # we can use the PythonLibs find-module to find the matching libraries. + # Otherwise we ask that interpreter where its matching libraries are. + if (PYTHON STREQUAL PYTHON_EXECUTABLE) + find_package(PythonLibs REQUIRED) + else() + # ask the interpreter for the essential extension-building flags + py_get_config_var(INCLUDEPY PYTHON_INCLUDE_DIRS) + py_get_config_var(LIBDIR PYTHON_LIBRARY_DIR) + py_get_config_var(LIBPL PYTHON_LIBPL) + py_get_config_var(LDLIBRARY PYTHON_LIBRARY_NAME) + find_library(PYTHON_LIBRARIES ${PYTHON_LIBRARY_NAME} + PATHS "${PYTHON_LIBRARY_DIR}" "${PYTHON_LIBPL}" + ) + endif() # there's a static_assert that tests the Python version. # that way, we verify the interpreter and the library version. @@ -181,8 +177,8 @@ foreach(PYTHON ${PYTHON_INTERPRETERS}) try_compile(PYTHON_TEST_RESULT "${CMAKE_BINARY_DIR}" SOURCES "${CMAKE_CURRENT_LIST_DIR}/FindPython_test.cpp" - LINK_LIBRARIES "${PYTHON_LIBRARY_NAME}" - CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${PYTHON_INCLUDE_DIR}" "-DLINK_DIRECTORIES=${PYTHON_LIBRARY_DIR}" "-DCMAKE_CXX_STANDARD=14" + LINK_LIBRARIES ${PYTHON_LIBRARIES} + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${PYTHON_INCLUDE_DIRS}" "-DCMAKE_CXX_STANDARD=14" COMPILE_DEFINITIONS "-DTARGET_VERSION=${PYTHON_MIN_VERSION_HEX}" OUTPUT_VARIABLE PYTHON_TEST_OUTPUT ) @@ -191,7 +187,6 @@ foreach(PYTHON ${PYTHON_INTERPRETERS}) message("-- Using python interpreter: ${PYTHON}") set(PYTHON_INTERP "${PYTHON}") - set(PYTHON_LIBRARY "-l${PYTHON_LIBRARY_NAME} -L${PYTHON_LIBRARY_DIR}") break() else() set(PYTHON_TEST_ERRORS "${PYTHON_TEST_ERRORS}python candidate ${PYTHON}:\n${PYTHON_TEST_OUTPUT}\n\n") @@ -207,12 +202,12 @@ if(NOT PYTHON_INTERP) message("We need an interpreter that is shipped with libpython and header files.") message("Specify your own with -DPYTHON=/path/to/executable\n\n\n") set(PYTHON_INTERP "") - set(PYTHON_INCLUDE_DIR "") - set(PYTHON_LIBRARY "") + set(PYTHON_INCLUDE_DIRS "") + set(PYTHON_LIBRARIES "") unset(PYTHON CACHE) - unset(PYTHON_LIBRARY CACHE) - unset(PYTHON_INCLUDE_DIR CACHE) + unset(PYTHON_LIBRARIES CACHE) + unset(PYTHON_INCLUDE_DIRS CACHE) endif() if(NOT PYTHON) @@ -221,8 +216,8 @@ if(NOT PYTHON) endif() set(PYTHON "${PYTHON_INTERP}" CACHE FILEPATH "Location of the Python interpreter" ${LOL_FORCE}) -set(PYTHON_LIBRARY "${PYTHON_LIBRARY}" CACHE STRING "Linker invocation for the Python library" ${LOL_FORCE}) -set(PYTHON_INCLUDE_DIR "${PYTHON_INCLUDE_DIR}" CACHE PATH "Location of the Python include dir" ${LOL_FORCE}) +set(PYTHON_LIBRARIES "${PYTHON_LIBRARIES}" CACHE STRING "Linker invocation for the Python library" ${LOL_FORCE}) +set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIRS}" CACHE PATH "Location of the Python include dir" ${LOL_FORCE}) unset(LOL_FORCE) @@ -233,4 +228,4 @@ mark_as_advanced(PYTHON_TEST_ERRORS) mark_as_advanced(PYTHON_INTERPRETERS) include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Python REQUIRED_VARS PYTHON PYTHON_INCLUDE_DIR PYTHON_LIBRARY) +find_package_handle_standard_args(Python REQUIRED_VARS PYTHON PYTHON_INCLUDE_DIRS PYTHON_LIBRARIES) diff --git a/buildsystem/modules/FindSDL2Image.cmake b/buildsystem/modules/FindSDL2Image.cmake index 60faf09944..74b36be8ba 100644 --- a/buildsystem/modules/FindSDL2Image.cmake +++ b/buildsystem/modules/FindSDL2Image.cmake @@ -1,4 +1,4 @@ -# Copyright 2014-2015 the openage authors. See copying.md for legal info. +# Copyright 2014-2017 the openage authors. See copying.md for legal info. find_package(PackageHandleStandardArgs) @@ -24,6 +24,6 @@ else() find_path(SDL2IMAGE_INCLUDE_DIRS SDL2/SDL_image.h DOC "Include directory for SDL2_image") endif() -# handle the QUIETLY and REQUIRED arguments and set OPENGL_FOUND to TRUE if +# handle the QUIETLY and REQUIRED arguments and set SDL2Image_FOUND to TRUE if # all listed variables are TRUE find_package_handle_standard_args(SDL2Image DEFAULT_MSG SDL2IMAGE_LIBRARIES) diff --git a/buildsystem/pxdgen.py b/buildsystem/pxdgen.py index d862bfc6bf..a8a4bb21e6 100644 --- a/buildsystem/pxdgen.py +++ b/buildsystem/pxdgen.py @@ -272,7 +272,7 @@ def get_pxd_lines(self): if namespace != previous_namespace: yield ( "cdef extern " - "from \"" + self.filename + "\" " + "from r\"" + self.filename + "\" " "namespace \"" + namespace + "\" " "nogil" ":" @@ -403,7 +403,7 @@ def parse_args(): def main(): """ CLI entry point """ args = parse_args() - cppdir = CWD + "/libopenage" + cppdir = os.path.join(CWD, "libopenage") if args.verbose: hdr_count = len(args.all_files) diff --git a/buildsystem/python.cmake b/buildsystem/python.cmake index cf98b142d0..315c2ecf81 100644 --- a/buildsystem/python.cmake +++ b/buildsystem/python.cmake @@ -104,7 +104,7 @@ function(add_cython_modules) add_executable("${TARGETNAME}" "${CPPNAME}") # TODO: use full ldflags and cflags provided by python${VERSION}-config - target_link_libraries("${TARGETNAME}" "${PYEXT_LIBRARY}") + target_link_libraries("${TARGETNAME}" ${PYEXT_LIBRARY}) else() set_property(GLOBAL APPEND PROPERTY SFT_CYTHON_MODULES "${source}") add_library("${TARGETNAME}" MODULE "${CPPNAME}") @@ -113,6 +113,9 @@ function(add_cython_modules) PREFIX "" SUFFIX "${PYEXT_SUFFIX}" ) + if(MSVC) + target_link_libraries("${TARGETNAME}" ${PYEXT_LIBRARY}) + endif() endif() if(NOINSTALL_NEXT) @@ -410,16 +413,16 @@ function(python_finalize) list(APPEND cython_module_files_expr "$") endforeach() file(GENERATE - OUTPUT "${CMAKE_BINARY_DIR}/py/inplace_module_list" + OUTPUT "${CMAKE_BINARY_DIR}/py/inplace_module_list$" CONTENT "${cython_module_files_expr}" ) set(INPLACEMODULES_TIMEFILE "${CMAKE_BINARY_DIR}/py/inplacemodules_timefile") add_custom_command(OUTPUT "${INPLACEMODULES_TIMEFILE}" COMMAND "${PYTHON}" -m buildsystem.inplacemodules - "${CMAKE_BINARY_DIR}/py/inplace_module_list" - "${CMAKE_BINARY_DIR}" + "${CMAKE_BINARY_DIR}/py/inplace_module_list$" + "${CMAKE_BINARY_DIR}" "$" DEPENDS - "${CMAKE_BINARY_DIR}/py/inplace_module_list" + "${CMAKE_BINARY_DIR}/py/inplace_module_list$" ${cython_module_targets} COMMAND "${CMAKE_COMMAND}" -E touch "${INPLACEMODULES_TIMEFILE}" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" @@ -432,8 +435,8 @@ function(python_finalize) add_custom_target(cleancython COMMAND "${PYTHON}" -m buildsystem.inplacemodules --clean - "${CMAKE_BINARY_DIR}/py/inplace_module_list" - "${CMAKE_BINARY_DIR}" + "${CMAKE_BINARY_DIR}/py/inplace_module_list$" + "${CMAKE_BINARY_DIR}" "$" COMMAND "${PYTHON}" -m buildsystem.cythonize --clean "${CMAKE_BINARY_DIR}/py/cython_modules" "${CMAKE_BINARY_DIR}/py/cython_modules_embed" diff --git a/copying.md b/copying.md index 34c7f86576..502ff92a44 100644 --- a/copying.md +++ b/copying.md @@ -103,6 +103,7 @@ _the openage authors_ are: | Folkert van Verseveld | methos, medicijnman | folkert dawt van dawt verseveld à gmail dawt com | | Neel Patel | ohn0 | silverskinx à gmail dawt com | | David Carlier | devnexen | devnexen à gmail dawt com | +| Tushar Maheshwari | tusharpm | tushar27192 à gmail dawt com | If you're a first-time committer, add yourself to the above list. This is not just for legal reasons, but also to keep an overview of all those nicknames. diff --git a/doc/build_instructions/windows_msvc.md b/doc/build_instructions/windows_msvc.md new file mode 100644 index 0000000000..2da8230d5e --- /dev/null +++ b/doc/build_instructions/windows_msvc.md @@ -0,0 +1,89 @@ +# Prerequisite steps for Microsoft Windows users (Windows 10) + + Since Windows doesn't offer a native package manager, we use a mixture of manual and automated steps to get the dependencies for openage. *Please remember to replace the directories referenced below (written in <...>) with the appropriate values.* + +## Setting up the build environment + You will need to download and install the following manually. Those who already have the latest stable versions of these softwares can skip this: + - [Visual Studio 2017 Community edition](https://www.visualstudio.com/downloads/) + - With the "Desktop development with C++" workload. + - With the "Windows 10 SDK". Choose the latest version listed. + - [Python 3](https://www.python.org/downloads/windows/) + - With the "pip" option enabled. We use `pip` to install other dependencies. + - With the "Precompile standard library" option enabled. + - If in doubt, run the installer again and choose "Modify". + - [CMake](https://cmake.org/download/) + +### Python Modules + Open a command prompt at `/Scripts` + + pip install numpy pillow pygments cython + +### vcpkg packages + Set up [vcpkg](https://github.com/Microsoft/vcpkg#quick-start). Open a command prompt at `` + + vcpkg install libepoxy fontconfig freetype harfbuzz opus qt5 sdl2 sdl2-image + +### The "other missing" dependencies + Create a `deps` directory in the ``. + Create the following directories in `deps`: + - `include` + - `lib` + + **dirent.h** + + Visual Studio doesn't provide a `dirent.h`, which is why we need to use a different one. + `FontConfig` (installed above using vcpkg) depends on `dirent.h` also, which is why there should be one downloaded and saved as `/downloads/fontconfig-dirent.h`. + Copy this file (and rename) to `/deps/include/dirent.h`. + + **opus-tools (for `opusenc`)** + + There are two options for getting opus-tools: + + [Get the prebuilt binaries](https://archive.mozilla.org/pub/opus/win32/). + + OR + + Build it yourself. + You can get the source from [the Github page](https://github.com/xiph/opus-tools). + Refer their AppVeyor config for the steps to build. + You will need `opusenc.exe` from the build output directory available from the `PATH`. + + **opusfile** + + Even though prebuilt binaries are available, you would need to build this one yourself because the required static library (`opusfile.lib`) is absent in the zip file. + + The source can be fetched from [the Github page](https://github.com/xiph/opusfile). + Refer their AppVeyor config for the steps to build, using the `Release-NoHTTP` configuration. + Copy: + - `opusfile.lib` from the build output directory to `/deps/lib/`. + - directory `/installed//include/opus` to `/deps/include/`. This is needed because `opusfile.h` refers the `opus` headers as if they are in the same directory. + - `/include/opusfile.h` to `/deps/include/opus/`. + +## Building openage + Note that openage doesn't support completely out-of-source-tree builds yet. + We will, however, use a separate `build` directory to build the binaries. + + Open a command prompt at ``: + + mkdir build + cd build + cmake -DCMAKE_TOOLCHAIN_FILE=/scripts/buildsystems/vcpkg.cmake -DCMAKE_PREFIX_PATH=/deps -DCMAKE_BUILD_TYPE=RelWithDebInfo .. + cmake --build . --config RelWithDebInfo -- /nologo /m /v:m + +## Running openage + While this is straightforward on other platforms, there is still stuff to do to run openage on Windows: + - Install the [DejaVu Book Font](https://dejavu-fonts.github.io/Download.html). + - Set the `FONTCONFIG_PATH` environment variable to `\installed\\tools\fontconfig\fonts\conf.d`. + - Copy `fontconfig/57-dejavu-serif.conf` to the same. + - [Optional] Set the `AGE2DIR` environment variable to the AoE 2 installation directory. + - Copy the binaries from the `build` subdirectories to the required locations: + + set ConfigToUse=RelWithDebInfo + + copy libopenage\%ConfigToUse%\openage.dll ..\ + copy libopenage\%ConfigToUse%\openage.pdb ..\ + - Append the following to the environment `PATH`: + - `\installed\\bin` + - Path to `opusenc.exe` +--- + Now, execute `/run.exe` and enjoy! diff --git a/doc/code/pyinterface.md b/doc/code/pyinterface.md index 323f43cc45..25c2a66b1b 100644 --- a/doc/code/pyinterface.md +++ b/doc/code/pyinterface.md @@ -132,6 +132,7 @@ int foo(int arg0, std::string arg1) { ``` cpp // pxd: from libcpp.string cimport string #include +#include "util/compiler.h" namespace openage { @@ -142,7 +143,7 @@ namespace openage { * * int foo(int arg0, string arg1) except + */ -int foo(int arg0, std::string arg1); +OAAPI int foo(int arg0, std::string arg1); } ``` @@ -214,7 +215,7 @@ This works in the way that you create C++ objects in Cython and then * PyObj obj * string text */ -struct demo_struct { +struct OAAPI demo_struct { py::PyObj obj; std::string text; }; @@ -307,7 +308,7 @@ PyIfFunc bar; #include "pyinterface/functional.h" // pxd: PyIfFunc2[float, int, string] bar -extern PyIfFunc bar; +extern OAAPI PyIfFunc bar; ``` Wrap the python function in a `cdef` function, and define a method `setup()`, @@ -385,3 +386,11 @@ this ensures that the GIL is always re-acquired when jumping into Cython code. __Never__ use raw function pointers in the interface; always use the `PyIfFunc` or `Func` objects; otherwise, you'll lose all safety guarantees. + +The `OAAPI` macro +----------------- + +`OAAPI` marks the DLL entry-points which is necessary for the Windows build. +All pxd interface functions, classes, and `extern` objects must be declared with `OAAPI` in the header file. +See the samples above to understand the exact position of insertion for each of those. +This can be ignored for functions defined inline in the header. diff --git a/libopenage/CMakeLists.txt b/libopenage/CMakeLists.txt index b5ae7d58c9..7d01389667 100644 --- a/libopenage/CMakeLists.txt +++ b/libopenage/CMakeLists.txt @@ -74,12 +74,21 @@ endif() # windows does not have libm if(NOT WIN32) find_library(MATH_LIB m) + find_library(UTIL_LIB util) +endif() +if(MSVC) + find_library(OGG_LIB ogg) +else() + find_library(DL_LIB dl) +endif() +if(NOT APPLE AND NOT MSVC) + find_library(RT_LIB rt) + if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") + find_library(EXECINFO_LIB execinfo) + endif() endif() find_library(FONTCONFIG_LIB fontconfig) -if(NOT WIN32) - find_library(UTIL_LIB util) -endif() find_package(Freetype REQUIRED) find_package(OpenGL REQUIRED) @@ -89,11 +98,6 @@ find_package(Opusfile REQUIRED) find_package(Epoxy REQUIRED) find_package(HarfBuzz 1.0.0 REQUIRED) -set(DLOPEN "") -if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") - set(DLOPEN dl) -endif() - set(QT_VERSION_REQ "5.5") find_package(Qt5Core ${QT_VERSION_REQ} REQUIRED) find_package(Qt5Quick ${QT_VERSION_REQ} REQUIRED) @@ -166,7 +170,7 @@ include_directories( # link the executable to those libraries target_link_libraries(libopenage PUBLIC - ${DLOPEN} + ${DL_LIB} ${FONTCONFIG_LIB} ${FREETYPE_LIBRARIES} ${EPOXY_LIBRARIES} @@ -177,6 +181,9 @@ target_link_libraries(libopenage ${SDL2_LIBRARY} ${UTIL_LIB} ${HarfBuzz_LIBRARIES} + ${RT_LIB} + ${OGG_LIB} + ${EXECINFO_LIB} # TODO: change to PUBLIC (or, alternatively, remove all keywords # of this type) when qt cmake scripts change declarations of the # IMPORTED libraries to GLOBAL. @@ -185,18 +192,4 @@ target_link_libraries(libopenage Qt5::Quick ) -if(NOT APPLE) - if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") - target_link_libraries(libopenage - PUBLIC - execinfo - util - ) - endif() - target_link_libraries(libopenage - PUBLIC - rt - ) -endif() - install(TARGETS libopenage DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY) diff --git a/libopenage/console/buf.h b/libopenage/console/buf.h index 48ee08f7f9..dfef607fe0 100644 --- a/libopenage/console/buf.h +++ b/libopenage/console/buf.h @@ -1,4 +1,4 @@ -// Copyright 2014-2016 the openage authors. See copying.md for legal info. +// Copyright 2014-2017 the openage authors. See copying.md for legal info. #pragma once @@ -9,6 +9,7 @@ #include #include "../coord/term.h" +#include "../util/compiler.h" #include "../util/unicode.h" namespace openage { diff --git a/libopenage/console/draw.cpp b/libopenage/console/draw.cpp index 8ed7c29816..8dfbdb5731 100644 --- a/libopenage/console/draw.cpp +++ b/libopenage/console/draw.cpp @@ -1,4 +1,4 @@ -// Copyright 2014-2016 the openage authors. See copying.md for legal info. +// Copyright 2014-2017 the openage authors. See copying.md for legal info. #include "draw.h" @@ -10,8 +10,6 @@ #include "../util/fds.h" #include "../util/timing.h" -#include - #include "buf.h" #include "console.h" #include "../engine.h" diff --git a/libopenage/console/tests.cpp b/libopenage/console/tests.cpp index ecfc7e7af1..8903b479e8 100644 --- a/libopenage/console/tests.cpp +++ b/libopenage/console/tests.cpp @@ -3,7 +3,11 @@ #include #include +#ifdef _MSC_VER +#define STDOUT_FILENO 1 +#else #include +#endif #include "../util/fds.h" #include "../util/pty.h" #include @@ -43,7 +47,7 @@ void render() { buf.write("rofl\n"); } buf.scroll(100); - util::FD outfd; + util::FD outfd{STDOUT_FILENO}; console::draw::to_terminal(&buf, &outfd, true); } diff --git a/libopenage/coord/tests.cpp b/libopenage/coord/tests.cpp index 531e48abf1..ed99ae2710 100644 --- a/libopenage/coord/tests.cpp +++ b/libopenage/coord/tests.cpp @@ -1,6 +1,4 @@ -// Copyright 2015-2016 the openage authors. See copying.md for legal info. - -#include +// Copyright 2015-2017 the openage authors. See copying.md for legal info. #include "../log/log.h" #include "../util/file.h" diff --git a/libopenage/cvar/cvar.h b/libopenage/cvar/cvar.h index 6b803b7c5e..d391c7874f 100644 --- a/libopenage/cvar/cvar.h +++ b/libopenage/cvar/cvar.h @@ -39,7 +39,7 @@ using set_func = std::function; * void set(string name, string value) except + * void load_config(Path path) except + */ -class CVarManager { +class OAAPI CVarManager { public: CVarManager(const util::Path &path); @@ -100,6 +100,6 @@ class CVarManager { * ctypedef CVarManager * CVarManagerPtr * PyIfFunc2[void, CVarManagerPtr, const Path&] pyx_load_config_file */ -extern pyinterface::PyIfFunc pyx_load_config_file; +extern OAAPI pyinterface::PyIfFunc pyx_load_config_file; }} // openage::cvar diff --git a/libopenage/datastructure/tests.cpp b/libopenage/datastructure/tests.cpp index af5719a541..c95b792dd7 100644 --- a/libopenage/datastructure/tests.cpp +++ b/libopenage/datastructure/tests.cpp @@ -140,14 +140,14 @@ void constexpr_map() { static_assert(not create_const_map(std::make_pair(42, 0), std::make_pair(13, 37)).contains(9001), "uncontained element seems to be contained."); - +#ifndef _MSC_VER // HACK: MSVC doesn't have full C++14 constexpr support static_assert(create_const_map(std::make_pair(42, 9001), std::make_pair(13, 37)).get(42) == 9001, "fetched wrong value"); static_assert(create_const_map(std::make_pair(42, 9001), std::make_pair(13, 37)).get(13) == 37, "fetched wrong value"); - +#endif constexpr auto cmap = create_const_map( std::make_pair(0, 0), std::make_pair(13, 37), diff --git a/libopenage/engine.h b/libopenage/engine.h index 945e6a3207..5656b63ab8 100644 --- a/libopenage/engine.h +++ b/libopenage/engine.h @@ -30,6 +30,7 @@ #include "util/path.h" #include "util/profiler.h" #include "unit/selection.h" +#include "util/strings.h" #include "screenshot.h" namespace openage { @@ -279,7 +280,7 @@ class Engine : public ResizeHandler, public options::OptionNode { /** * render text with the at a position with specified font size */ - void render_text(coord::window position, size_t size, const char *format, ...) __attribute__((format (printf, 4, 5))); + void render_text(coord::window position, size_t size, const char *format, ...) ATTRIBUTE_FORMAT(4, 5); /** * move the phys3 camera incorporated in the engine diff --git a/libopenage/error/error.h b/libopenage/error/error.h index a4c8c0c464..a5b77fc317 100644 --- a/libopenage/error/error.h +++ b/libopenage/error/error.h @@ -48,7 +48,7 @@ namespace error { * * Backtrace *backtrace */ -class Error : public std::runtime_error { +class OAAPI Error : public std::runtime_error { public: /** * @param msg @@ -156,26 +156,29 @@ inline std::string no_ensuring_message() /* * expands to the first argument + * Modified for MSVC using the technique by Jeff Walden + * https://stackoverflow.com/a/9338429 */ -#define OPENAGE_ENS_FIRST(...) OPENAGE_ENS_FIRST_HELPER(__VA_ARGS__, throwaway) +#define OPENAGE_PP_GLUE(macro, args) macro args +#define OPENAGE_ENS_FIRST(...) OPENAGE_PP_GLUE(OPENAGE_ENS_FIRST_HELPER,(__VA_ARGS__, throwaway)) #define OPENAGE_ENS_FIRST_HELPER(first, ...) (first) /* * Standard alternative to GCC's ##__VA_ARGS__ trick (Richard Hansen) * http://stackoverflow.com/a/11172679/4742108 * - * If there's only one argument, expands to nothing. If there is more - * than one argument, expands to a '<<' followed by everything but - * the first argument. Only supports up to 2 arguments but can be - * trivially expanded. + * If there's only one argument, expands to << ::openage::error::no_ensuring_message() + * If there is more than one argument, expands to a '<<' followed by everything but + * the first argument. Only supports up to 2 arguments but can be trivially expanded. */ -#define OPENAGE_ENS_REST(...) OPENAGE_ENS_REST_HELPER(OPENAGE_ENS_NUM(__VA_ARGS__), __VA_ARGS__) -#define OPENAGE_ENS_REST_HELPER(qty, ...) OPENAGE_ENS_REST_HELPER2(qty, __VA_ARGS__) -#define OPENAGE_ENS_REST_HELPER2(qty, ...) OPENAGE_ENS_REST_HELPER_##qty(__VA_ARGS__) +#define OPENAGE_ENS_REST(...) OPENAGE_PP_GLUE(OPENAGE_ENS_REST_HELPER(OPENAGE_ENS_NUM(__VA_ARGS__)), (__VA_ARGS__)) +#define OPENAGE_ENS_REST_HELPER(qty) OPENAGE_ENS_REST_HELPER1(qty) +#define OPENAGE_ENS_REST_HELPER1(qty) OPENAGE_ENS_REST_HELPER2(qty) +#define OPENAGE_ENS_REST_HELPER2(qty) OPENAGE_ENS_REST_HELPER_##qty #define OPENAGE_ENS_REST_HELPER_ONE(first) << ::openage::error::no_ensuring_message() #define OPENAGE_ENS_REST_HELPER_TWOORMORE(first, ...) << __VA_ARGS__ -#define OPENAGE_ENS_NUM(...) \ - OPENAGE_ENS_SELECT_2ND(__VA_ARGS__, TWOORMORE, ONE, throwaway) +#define OPENAGE_ENS_NUM(...) OPENAGE_ENS_NUM_IMPL((__VA_ARGS__, TWOORMORE, ONE, throwaway)) +#define OPENAGE_ENS_NUM_IMPL(args) OPENAGE_ENS_SELECT_2ND args #define OPENAGE_ENS_SELECT_2ND(a1, a2, a3, ...) a3 } // error diff --git a/libopenage/error/gl_debug.cpp b/libopenage/error/gl_debug.cpp index 8eb4cd9f00..bad32aede4 100644 --- a/libopenage/error/gl_debug.cpp +++ b/libopenage/error/gl_debug.cpp @@ -1,4 +1,4 @@ -// Copyright 2016-2016 the openage authors. See copying.md for legal info. +// Copyright 2016-2017 the openage authors. See copying.md for legal info. #include "gl_debug.h" @@ -10,7 +10,7 @@ namespace openage { namespace error { namespace { -void callback(GLenum source, GLenum, GLuint, GLenum, GLsizei, const GLchar *message, const void*) { +void APIENTRY callback(GLenum source, GLenum, GLuint, GLenum, GLsizei, const GLchar *message, const void*) { const char *source_name; switch (source) { diff --git a/libopenage/error/handlers.cpp b/libopenage/error/handlers.cpp index 3c221fc973..40816d7fd6 100644 --- a/libopenage/error/handlers.cpp +++ b/libopenage/error/handlers.cpp @@ -15,7 +15,11 @@ #include #include +#ifdef _MSC_VER +#include +#else #include +#endif #include "../util/signal.h" #include "../util/init.h" diff --git a/libopenage/error/stackanalyzer.cpp b/libopenage/error/stackanalyzer.cpp index c59dd8e4b2..a3f44a2220 100644 --- a/libopenage/error/stackanalyzer.cpp +++ b/libopenage/error/stackanalyzer.cpp @@ -192,6 +192,26 @@ void StackAnalyzer::get_symbols(std::function c #else // WITHOUT_BACKTRACE +#ifdef _MSC_VER +#include + +namespace openage { +namespace error { + + +void StackAnalyzer::analyze() { + std::vector buffer{64}; + auto count = RtlCaptureStackBackTrace(base_skip_frames, buffer.size(), buffer.data(), NULL); + if (count < buffer.size()) { + buffer.resize(count); + } + this->stack_addrs = std::move(buffer); +} + +}} // openage::error + +#else // not _MSC_VER + // use GNU's #include @@ -237,6 +257,13 @@ void StackAnalyzer::analyze() { } } +}} // openage::error + +#endif // for _MSC_VER or GNU execinfo + +namespace openage { +namespace error { + void StackAnalyzer::get_symbols(std::function cb, bool reversed) const { @@ -245,7 +272,8 @@ void StackAnalyzer::get_symbols(std::function c symbol.lineno = 0; if (reversed) { - for (size_t idx = this->stack_addrs.size(); idx > 0; idx--) { + // `for (auto pc : this->stack_addrs | ::view::reverse)` after Ranges-TS + for (size_t idx = this->stack_addrs.size(); idx-- > 0;) { void *pc = this->stack_addrs[idx]; symbol.functionname = util::symbol_name(pc, false, true); diff --git a/libopenage/game_renderer.cpp b/libopenage/game_renderer.cpp index 8b7ed49d4f..c07e408c5b 100644 --- a/libopenage/game_renderer.cpp +++ b/libopenage/game_renderer.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include "coord/vec2f.h" diff --git a/libopenage/gui/guisys/CMakeLists.txt b/libopenage/gui/guisys/CMakeLists.txt index 1cb654b3e5..3b1091ce47 100644 --- a/libopenage/gui/guisys/CMakeLists.txt +++ b/libopenage/gui/guisys/CMakeLists.txt @@ -44,6 +44,10 @@ if(APPLE AND UNIX) list(APPEND QT_SDL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/private/platforms/context_extraction_cocoa.mm ) +elseif(WIN32) + list(APPEND QT_SDL_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/private/platforms/context_extraction_win32.cpp + ) else(APPLE AND UNIX) list(APPEND QT_SDL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/private/platforms/context_extraction_x11.cpp diff --git a/libopenage/gui/guisys/private/gui_subtree_impl.cpp b/libopenage/gui/guisys/private/gui_subtree_impl.cpp index 40c11f5253..d025a09d54 100644 --- a/libopenage/gui/guisys/private/gui_subtree_impl.cpp +++ b/libopenage/gui/guisys/private/gui_subtree_impl.cpp @@ -1,8 +1,10 @@ // Copyright 2015-2017 the openage authors. See copying.md for legal info. #include "gui_subtree_impl.h" +#include "gui_renderer_impl.h" #include +#include #include #include @@ -12,7 +14,6 @@ #include #include -#include "gui_renderer_impl.h" #include "gui_engine_impl.h" #include "../link/gui_item.h" #include "../public/gui_subtree.h" @@ -61,10 +62,9 @@ GuiSubtreeImpl::GuiSubtreeImpl(GuiRenderer *renderer, // Need to queue the loading because some underlying game logic elements // require the loop to be running (maybe some things that are created after // the gui). - // TODO maybe it's better to use QUrl::fromLocalFile QMetaObject::invokeMethod(this->root_component.get(), "loadUrl", Qt::QueuedConnection, - Q_ARG(QUrl, source)); + Q_ARG(QUrl, QUrl::fromLocalFile(source))); } GuiSubtreeImpl::~GuiSubtreeImpl() { diff --git a/libopenage/gui/guisys/private/platforms/context_extraction_win32.cpp b/libopenage/gui/guisys/private/platforms/context_extraction_win32.cpp new file mode 100644 index 0000000000..86aba09703 --- /dev/null +++ b/libopenage/gui/guisys/private/platforms/context_extraction_win32.cpp @@ -0,0 +1,47 @@ +// Copyright 2015-2017 the openage authors. See copying.md for legal info. + +#include + +#include +#include "context_extraction.h" + +#include +#include +#include + +namespace qtsdl { + +std::tuple extract_native_context(SDL_Window *window) { + assert(window); + + HGLRC current_context; + SDL_SysWMinfo wm_info; + SDL_VERSION(&wm_info.version); + if (SDL_GetWindowWMInfo(window, &wm_info)) { + current_context = wglGetCurrentContext(); + assert(current_context); + } + QWGLNativeContext nativeContext(current_context, wm_info.info.win.window); + return {QVariant::fromValue(nativeContext), reinterpret_cast(wm_info.info.win.window)}; +} + +std::tuple> extract_native_context_and_switchback_func(SDL_Window *window) { + assert(window); + + HGLRC current_context; + SDL_SysWMinfo wm_info; + SDL_VERSION(&wm_info.version); + if (SDL_GetWindowWMInfo(window, &wm_info)) { + current_context = wglGetCurrentContext(); + assert(current_context); + + return std::make_tuple(QVariant::fromValue(QWGLNativeContext(current_context, wm_info.info.win.window)), [wm_info, current_context] { + wglMakeCurrent(wm_info.info.win.hdc, current_context); + }); + } + + return std::tuple>{}; +} + + +} // namespace qtsdl diff --git a/libopenage/gui/guisys/public/gui_renderer.h b/libopenage/gui/guisys/public/gui_renderer.h index fc36bf487a..7139dee405 100644 --- a/libopenage/gui/guisys/public/gui_renderer.h +++ b/libopenage/gui/guisys/public/gui_renderer.h @@ -5,8 +5,12 @@ #include #ifndef __APPLE__ +#ifdef _MSC_VER +#define NOMINMAX +#include +#endif //_MSC_VER #include -#else +#else // __APPLE__ #include #endif diff --git a/libopenage/gui/integration/private/gui_log.cpp b/libopenage/gui/integration/private/gui_log.cpp index b8013139c1..4425910acb 100644 --- a/libopenage/gui/integration/private/gui_log.cpp +++ b/libopenage/gui/integration/private/gui_log.cpp @@ -10,7 +10,10 @@ namespace openage { namespace gui { void gui_log(QtMsgType type, const QMessageLogContext &context, const QString &msg) { - log::MessageBuilder builder{context.file, static_cast(context.line), context.function, [=] { + log::MessageBuilder builder{context.file != nullptr ? context.file : "", + static_cast(context.line), + context.function != nullptr ? context.function : "", + [=] { switch (type) { case QtDebugMsg: return log::lvl::dbg; diff --git a/libopenage/log/level.h b/libopenage/log/level.h index 68e81618a4..e6eef71cc8 100644 --- a/libopenage/log/level.h +++ b/libopenage/log/level.h @@ -1,4 +1,4 @@ -// Copyright 2015-2016 the openage authors. See copying.md for legal info. +// Copyright 2015-2017 the openage authors. See copying.md for legal info. #pragma once @@ -53,14 +53,14 @@ namespace lvl { // pxd: level crit // pxd: level MAX -extern level MIN; // not designed for use in messages -extern level spam; -extern level dbg; -extern level info; -extern level warn; -extern level err; -extern level crit; -extern level MAX; // not designed for use in messages +extern OAAPI level MIN; // not designed for use in messages +extern OAAPI level spam; +extern OAAPI level dbg; +extern OAAPI level info; +extern OAAPI level warn; +extern OAAPI level err; +extern OAAPI level crit; +extern OAAPI level MAX; // not designed for use in messages } // lvl diff --git a/libopenage/log/log.h b/libopenage/log/log.h index 382f4ccee6..936a7735ab 100644 --- a/libopenage/log/log.h +++ b/libopenage/log/log.h @@ -24,7 +24,7 @@ void log(const message &msg); * * pxd: void set_level(level lvl) except + */ -void set_level(level lvl); +OAAPI void set_level(level lvl); }} // openage::log diff --git a/libopenage/log/logsource.h b/libopenage/log/logsource.h index 74a87939e4..21d793bdd0 100644 --- a/libopenage/log/logsource.h +++ b/libopenage/log/logsource.h @@ -1,4 +1,4 @@ -// Copyright 2015-2016 the openage authors. See copying.md for legal info. +// Copyright 2015-2017 the openage authors. See copying.md for legal info. #pragma once @@ -24,7 +24,7 @@ namespace log { * const size_t logger_id * string logsource_name() except + */ -class LogSource { +class OAAPI LogSource { public: LogSource(); diff --git a/libopenage/log/message.h b/libopenage/log/message.h index 920007f31a..007c963da5 100644 --- a/libopenage/log/message.h +++ b/libopenage/log/message.h @@ -1,4 +1,4 @@ -// Copyright 2015-2016 the openage authors. See copying.md for legal info. +// Copyright 2015-2017 the openage authors. See copying.md for legal info. #pragma once @@ -14,6 +14,14 @@ // pxd: from libopenage.log.level cimport level #include "level.h" +#if defined(__GNUC__) +#define OPENAGE_FUNC_NAME __PRETTY_FUNCTION__ +#elif defined(_MSC_VER) +#define OPENAGE_FUNC_NAME __FUNCSIG__ +#else +#define OPENAGE_FUNC_NAME __FUNCTION__ +#endif + namespace openage { @@ -45,7 +53,7 @@ namespace log { * void init() except + * void init_with_metadata_copy(string filename, string functionname) except + */ -struct message { +struct OAAPI message { std::string text; /** @@ -107,14 +115,14 @@ std::ostream &operator <<(std::ostream &os, const message &msg); * Auto-converts to message; via the MSG macro, this is the preferred way of creating * log and exc messages. */ -class MessageBuilder : public util::StringFormatter { +class OAAPI MessageBuilder : public util::StringFormatter { public: /** * Don't use this constructor directly; instead use the MSG macro. * * * @param filename, lineno source file name and line number (__FILE__, __LINE__). - * @param functionname (fully qualified) function name (__PRETTY_FUNCTION__). + * @param functionname (fully qualified) function name (OPENAGE_FUNC_NAME). * @param lvl loglevel of the message. Also required for exception messages. */ MessageBuilder(const char *filename, unsigned lineno, const char *functionname, @@ -138,7 +146,7 @@ class MessageBuilder : public util::StringFormatter { // MSG is resolved to a MessageBuilder constructor invocation; -// it fills in information such as __FILE__, __LINE__ and __PRETTY_FUNCTION_. +// it fills in information such as __FILE__, __LINE__ and OPENAGE_FUNC_NAME. // // Unfortunately, macros are the only way to achieve that. @@ -150,7 +158,7 @@ class MessageBuilder : public util::StringFormatter { __FILE__, \ ::openage::config::buildsystem_sourcefile_dir), \ __LINE__, \ - __PRETTY_FUNCTION__, \ + OPENAGE_FUNC_NAME, \ LVLOBJ) diff --git a/libopenage/log/named_logsource.h b/libopenage/log/named_logsource.h index 77118d7a32..e64dc0420f 100644 --- a/libopenage/log/named_logsource.h +++ b/libopenage/log/named_logsource.h @@ -20,7 +20,7 @@ namespace log { * cppclass NamedLogSource(LogSource): * NamedLogSource(string name) except + */ -class NamedLogSource : public LogSource { +class OAAPI NamedLogSource : public LogSource { public: NamedLogSource(const std::string &name); diff --git a/libopenage/main.h b/libopenage/main.h index 2728316fd0..daaa324959 100644 --- a/libopenage/main.h +++ b/libopenage/main.h @@ -36,6 +36,6 @@ struct main_arguments { * * pxd: int run_game(const main_arguments &args) except + */ -int run_game(const main_arguments &args); +OAAPI int run_game(const main_arguments &args); } // openage diff --git a/libopenage/pyinterface/exctranslate.h b/libopenage/pyinterface/exctranslate.h index 56ab14b068..82a7020e69 100644 --- a/libopenage/pyinterface/exctranslate.h +++ b/libopenage/pyinterface/exctranslate.h @@ -37,7 +37,7 @@ class PyException; * Designed to be called by auto-generated Cython code; * Do not use in any other way. */ -void translate_exc_cpp_to_py(); +OAAPI void translate_exc_cpp_to_py(); /** @@ -47,7 +47,7 @@ void translate_exc_cpp_to_py(); * Works, and is designed to be used in, situations where * there is no current Python exception (it's a no-op then). */ -void translate_exc_py_to_cpp(); +OAAPI void translate_exc_py_to_cpp(); /** @@ -57,7 +57,7 @@ void translate_exc_py_to_cpp(); * * pxd: void init_exc_message(message *msg, string filename, unsigned int lineno, string functionname) noexcept */ -void init_exc_message(log::message *msg, const std::string &filename, unsigned int lineno, const std::string &functionname) noexcept; +OAAPI void init_exc_message(log::message *msg, const std::string &filename, unsigned int lineno, const std::string &functionname) noexcept; /* @@ -139,7 +139,7 @@ void init_exc_message(log::message *msg, const std::string &filename, unsigned i * void (*)(PyException *) except * with gil * ) noexcept */ -void set_exc_translation_funcs( +OAAPI void set_exc_translation_funcs( void (*raise_cpp_error)(Error *), void (*raise_cpp_pyexception)(PyException *), bool (*check_for_py_exception)(), diff --git a/libopenage/pyinterface/exctranslate_tests.h b/libopenage/pyinterface/exctranslate_tests.h index ae23deb1ef..49a2be4037 100644 --- a/libopenage/pyinterface/exctranslate_tests.h +++ b/libopenage/pyinterface/exctranslate_tests.h @@ -1,4 +1,4 @@ -// Copyright 2015-2016 the openage authors. See copying.md for legal info. +// Copyright 2015-2017 the openage authors. See copying.md for legal info. #pragma once @@ -16,7 +16,7 @@ namespace tests { * * pxd: void err_cpp_to_py_helper() except + */ -void err_cpp_to_py_helper(); +OAAPI void err_cpp_to_py_helper(); /** @@ -25,7 +25,7 @@ void err_cpp_to_py_helper(); * * pxd: PyIfFunc0[void] err_py_to_cpp_helper */ -extern PyIfFunc err_py_to_cpp_helper; +extern OAAPI PyIfFunc err_py_to_cpp_helper; /** @@ -33,7 +33,7 @@ extern PyIfFunc err_py_to_cpp_helper; * * pxd: void bounce_call(Func0[void], int) except + */ -void bounce_call(Func func, int times); +OAAPI void bounce_call(Func func, int times); /** @@ -41,7 +41,7 @@ void bounce_call(Func func, int times); * * pxd: PyIfFunc2[void, Func0[void], int] bounce_call_py */ -extern PyIfFunc, int> bounce_call_py; +extern OAAPI PyIfFunc, int> bounce_call_py; }}} // openage::pyinterface::tests diff --git a/libopenage/pyinterface/pyexception.h b/libopenage/pyinterface/pyexception.h index 20a5b823ac..2cdb7260c2 100644 --- a/libopenage/pyinterface/pyexception.h +++ b/libopenage/pyinterface/pyexception.h @@ -57,7 +57,7 @@ class PyExceptionBacktrace : public error::Backtrace { * PyObjectRef py_obj * void init_backtrace() except + */ -class PyException : public error::Error { +class OAAPI PyException : public error::Error { public: /** * Returns the type name of py_obj. @@ -80,7 +80,7 @@ class PyException : public error::Error { // pxd: PyIfFunc2[void, PyObjectPtr, Func1[void, backtrace_symbol_constptr]] pyexception_bt_get_symbols -extern PyIfFunc> pyexception_bt_get_symbols; +extern OAAPI PyIfFunc> pyexception_bt_get_symbols; }} // openage::pyinterface diff --git a/libopenage/pyinterface/pyobject.h b/libopenage/pyinterface/pyobject.h index f1b8c87bc8..bc464d95df 100644 --- a/libopenage/pyinterface/pyobject.h +++ b/libopenage/pyinterface/pyobject.h @@ -55,7 +55,7 @@ struct to_pyobj; * ctypedef PyObjectRef *PyObjectRefPtr * ctypedef PyObject *PyObjectPtr */ -class PyObjectRef { +class OAAPI PyObjectRef { public: /** * Initializes reference with nullptr. @@ -328,71 +328,71 @@ std::ostream &operator <<(std::ostream &os, const PyObjectRef &ref); // for use by the reference-counting constructors // pxd: PyIfFunc1[void, PyObjectPtr] py_xincref -extern PyIfFunc py_xincref; +extern OAAPI PyIfFunc py_xincref; // pxd: PyIfFunc1[void, PyObjectPtr] py_xdecref -extern PyIfFunc py_xdecref; +extern OAAPI PyIfFunc py_xdecref; // for all of those member functions // pxd: PyIfFunc1[string, PyObjectPtr] py_str -extern PyIfFunc py_str; +extern OAAPI PyIfFunc py_str; // pxd: PyIfFunc1[string, PyObjectPtr] py_repr -extern PyIfFunc py_repr; +extern OAAPI PyIfFunc py_repr; // pxd: PyIfFunc1[string, PyObjectPtr] py_bytes -extern PyIfFunc py_bytes; +extern OAAPI PyIfFunc py_bytes; // pxd: PyIfFunc1[int, PyObjectPtr] py_len -extern PyIfFunc py_len; +extern OAAPI PyIfFunc py_len; // pxd: PyIfFunc1[cppbool, PyObjectPtr] py_callable -extern PyIfFunc py_callable; +extern OAAPI PyIfFunc py_callable; // pxd: PyIfFunc2[void, PyObjectRefPtr, PyObjectPtr] py_call0 -extern PyIfFunc py_call0; +extern OAAPI PyIfFunc py_call0; // pxd: PyIfFunc3[void, PyObjectRefPtr, PyObjectPtr, vector[PyObjectPtr]] py_calln -extern PyIfFunc&> py_calln; +extern OAAPI PyIfFunc&> py_calln; // pxd: PyIfFunc2[cppbool, PyObjectPtr, string] py_hasattr -extern PyIfFunc py_hasattr; +extern OAAPI PyIfFunc py_hasattr; // pxd: PyIfFunc3[void, PyObjectRefPtr, PyObjectPtr, string] py_getattr -extern PyIfFunc py_getattr; +extern OAAPI PyIfFunc py_getattr; // pxd: PyIfFunc3[void, PyObjectPtr, string, PyObjectPtr] py_setattr -extern PyIfFunc py_setattr; +extern OAAPI PyIfFunc py_setattr; // pxd: PyIfFunc2[cppbool, PyObjectPtr, PyObjectPtr] py_isinstance -extern PyIfFunc py_isinstance; +extern OAAPI PyIfFunc py_isinstance; // pxd: PyIfFunc1[cppbool, PyObjectPtr] py_to_bool -extern PyIfFunc py_to_bool; +extern OAAPI PyIfFunc py_to_bool; // pxd: PyIfFunc1[int64_t, PyObjectPtr] py_to_int -extern PyIfFunc py_to_int; +extern OAAPI PyIfFunc py_to_int; // pxd: PyIfFunc2[void, PyObjectPtr, Func1[void, string]] py_dir -extern PyIfFunc> py_dir; +extern OAAPI PyIfFunc> py_dir; // pxd: PyIfFunc2[cppbool, PyObjectPtr, PyObjectPtr] py_equals -extern PyIfFunc py_equals; +extern OAAPI PyIfFunc py_equals; // pxd: PyIfFunc2[void, PyObjectPtr, string] py_exec -extern PyIfFunc py_exec; +extern OAAPI PyIfFunc py_exec; // pxd: PyIfFunc3[void, PyObjectPtr, PyObjectRefPtr, string] py_eval -extern PyIfFunc py_eval; +extern OAAPI PyIfFunc py_eval; // pxd: PyIfFunc3[void, PyObjectPtr, PyObjectRefPtr, PyObjectPtr] py_get -extern PyIfFunc py_get; +extern OAAPI PyIfFunc py_get; // pxd: PyIfFunc2[cppbool, PyObjectPtr, PyObjectPtr] py_in -extern PyIfFunc py_in; +extern OAAPI PyIfFunc py_in; // pxd: PyIfFunc2[void, PyObjectPtr, PyObjectRefPtr] py_type -extern PyIfFunc py_type; +extern OAAPI PyIfFunc py_type; // pxd: PyIfFunc1[string, PyObjectPtr] py_modulename -extern PyIfFunc py_modulename; +extern OAAPI PyIfFunc py_modulename; // pxd: PyIfFunc1[string, PyObjectPtr] py_classname -extern PyIfFunc py_classname; +extern OAAPI PyIfFunc py_classname; // pxd: PyIfFunc2[void, PyObjectRefPtr, const string] py_builtin -extern PyIfFunc py_builtin; +extern OAAPI PyIfFunc py_builtin; // pxd: PyIfFunc2[void, PyObjectRefPtr, const string] py_import -extern PyIfFunc py_import; +extern OAAPI PyIfFunc py_import; // pxd: PyIfFunc2[void, PyObjectRefPtr, const string] py_createstr -extern PyIfFunc py_createstr; +extern OAAPI PyIfFunc py_createstr; // pxd: PyIfFunc2[void, PyObjectRefPtr, const string] py_createbytes -extern PyIfFunc py_createbytes; +extern OAAPI PyIfFunc py_createbytes; // pxd: PyIfFunc2[void, PyObjectRefPtr, int] py_createint -extern PyIfFunc py_createint; +extern OAAPI PyIfFunc py_createint; // pxd: PyIfFunc1[void, PyObjectRefPtr] py_createdict -extern PyIfFunc py_createdict; +extern OAAPI PyIfFunc py_createdict; // pxd: PyIfFunc1[void, PyObjectRefPtr] py_createlist -extern PyIfFunc py_createlist; +extern OAAPI PyIfFunc py_createlist; } // pyinterface @@ -455,7 +455,7 @@ Obj list(); * * pxd: PyObjectRef None */ -extern Obj None; +extern OAAPI Obj None; /** @@ -463,7 +463,7 @@ extern Obj None; * * pxd: PyObjectRef True */ -extern Obj True; +extern OAAPI Obj True; /** @@ -471,7 +471,7 @@ extern Obj True; * * pxd: PyObjectRef False */ -extern Obj False; +extern OAAPI Obj False; } // py diff --git a/libopenage/pyinterface/setup.h b/libopenage/pyinterface/setup.h index 41a6aa1984..2aa387c8d9 100644 --- a/libopenage/pyinterface/setup.h +++ b/libopenage/pyinterface/setup.h @@ -1,9 +1,11 @@ -// Copyright 2015-2016 the openage authors. See copying.md for legal info. +// Copyright 2015-2017 the openage authors. See copying.md for legal info. #include #pragma once +#include "../util/compiler.h" + /* * Code for verifying that all components of the Python interface have been * properly initialized. @@ -51,7 +53,7 @@ void destroy_py_if_component(void *thisptr); * * pxd: void check() except + */ -void check(); +OAAPI void check(); }} // openage::pyinterface diff --git a/libopenage/rng/rng_tests.cpp b/libopenage/rng/rng_tests.cpp index 24349ad184..01f4a56169 100644 --- a/libopenage/rng/rng_tests.cpp +++ b/libopenage/rng/rng_tests.cpp @@ -1,4 +1,4 @@ -// Copyright 2015-2016 the openage authors. See copying.md for legal info. +// Copyright 2015-2017 the openage authors. See copying.md for legal info. #include "rng.h" @@ -71,7 +71,7 @@ void freq_dist() { } // test if each bucket was selected the amount we expected. - for (ssize_t count : buckets) { + for (auto count : buckets) { std::abs(mean - count) > max_diff and TESTFAIL; } } diff --git a/libopenage/shader/program.cpp b/libopenage/shader/program.cpp index b9a5d81c0d..5e13a8c749 100644 --- a/libopenage/shader/program.cpp +++ b/libopenage/shader/program.cpp @@ -1,8 +1,7 @@ -// Copyright 2013-2016 the openage authors. See copying.md for legal info. +// Copyright 2013-2017 the openage authors. See copying.md for legal info. #include "program.h" -#include #include #include #include diff --git a/libopenage/shader/shader.cpp b/libopenage/shader/shader.cpp index 787f6a63fd..20fdbb5ec2 100644 --- a/libopenage/shader/shader.cpp +++ b/libopenage/shader/shader.cpp @@ -1,8 +1,7 @@ -// Copyright 2013-2015 the openage authors. See copying.md for legal info. +// Copyright 2013-2017 the openage authors. See copying.md for legal info. #include "shader.h" -#include #include #include diff --git a/libopenage/testing/benchmark_test.cpp b/libopenage/testing/benchmark_test.cpp index bc82c15997..3c255f29ee 100644 --- a/libopenage/testing/benchmark_test.cpp +++ b/libopenage/testing/benchmark_test.cpp @@ -1,12 +1,14 @@ // Copyright 2017-2017 the openage authors. See copying.md for legal info. -#include +#include +#include namespace openage { namespace test { void benchmark() { - usleep(1000); + using namespace std::chrono_literals; + std::this_thread::sleep_for(1ms); } }} // openage::test diff --git a/libopenage/testing/testlist.h b/libopenage/testing/testlist.h index e5efeb6da8..d3da00e128 100644 --- a/libopenage/testing/testlist.h +++ b/libopenage/testing/testlist.h @@ -18,7 +18,7 @@ namespace testing { * * pxd: void run_method(string name) except + */ -void run_method(const std::string &name); +OAAPI void run_method(const std::string &name); }} // openage::testing diff --git a/libopenage/util/compiler.cpp b/libopenage/util/compiler.cpp index c7602814b2..a9dc9f308d 100644 --- a/libopenage/util/compiler.cpp +++ b/libopenage/util/compiler.cpp @@ -1,9 +1,11 @@ -// Copyright 2015-2016 the openage authors. See copying.md for legal info. +// Copyright 2015-2017 the openage authors. See copying.md for legal info. #include "compiler.h" +#ifndef _MSC_VER #include #include +#endif #include "strings.h" @@ -14,6 +16,11 @@ namespace util { std::string demangle(const char *symbol) { +#ifdef _MSC_VER + // TODO: demangle names for MSVC; Possibly using UnDecorateSymbolName + // https://msdn.microsoft.com/en-us/library/windows/desktop/ms681400(v=vs.85).aspx + return symbol; +#else int status; char *buf = abi::__cxa_demangle(symbol, nullptr, nullptr, &status); @@ -24,6 +31,7 @@ std::string demangle(const char *symbol) { free(buf); return result; } +#endif } @@ -33,6 +41,11 @@ std::string addr_to_string(const void *addr) { std::string symbol_name(const void *addr, bool require_exact_addr, bool no_pure_addrs) { +#ifdef _MSC_VER + // TODO: implement symbol_name for MSVC; Possibly using SymFromAddr + // https://msdn.microsoft.com/en-us/library/windows/desktop/ms681323(v=vs.85).aspx + return no_pure_addrs ? "" : addr_to_string(addr); +#else Dl_info addr_info; if (dladdr(addr, &addr_info) == 0) { @@ -54,10 +67,15 @@ std::string symbol_name(const void *addr, bool require_exact_addr, bool no_pure_ symbol_offset); } } +#endif } bool is_symbol(const void *addr) { +#ifdef _MSC_VER + // TODO: Get dladdr equivalent for MSVC. + return true; +#else Dl_info addr_info; if (dladdr(addr, &addr_info) == 0) { @@ -65,6 +83,7 @@ bool is_symbol(const void *addr) { } return (addr_info.dli_saddr == addr); +#endif } diff --git a/libopenage/util/compiler.h b/libopenage/util/compiler.h index fa33ea5bd4..802d1c6552 100644 --- a/libopenage/util/compiler.h +++ b/libopenage/util/compiler.h @@ -8,25 +8,61 @@ * * May contain some platform-dependent code. */ + #include // pxd: from libcpp.string cimport string #include +/** + * DLL entry-point decorations. + */ +#if defined(_WIN32) + #if defined(libopenage_EXPORTS) + #define OAAPI __declspec(dllexport) + #else + #define OAAPI __declspec(dllimport) + #endif /* libopenage_EXPORTS */ +#else + #define OAAPI +#endif + +#if defined(_MSC_VER) + #ifndef HAVE_SSIZE_T + // ssize_t is defined the same as Python's definition it in pyconfig.h. + // This is necessary to facilitate the build and link procedure using MSVC. + #ifdef _WIN64 + typedef __int64 ssize_t; + #else + typedef int ssize_t; + #endif + #define HAVE_SSIZE_T 1 + #endif // HAVE_SSIZE_T +#endif // _MSC_VER + /* * Branch prediction tuning. * the expression is expected to be true (=likely) or false (=unlikely). * * btw, this implementation was taken from the Linux kernel. */ +#if defined(__GNUC__) #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) +#else +#define likely(x) (x) +#define unlikely(x) (x) +#endif /** * Software breakpoint if you're too lazy * to add it in gdb but instead wanna add it into the code directly. */ +#ifdef _MSC_VER +#define BREAKPOINT __debugbreak() +#else #define BREAKPOINT asm("int $3;") +#endif /** @@ -64,7 +100,7 @@ std::string demangle(const char *symbol); * * pxd: string symbol_name(const void *addr) except + */ -std::string symbol_name(const void *addr, bool require_exact_addr=true, bool no_pure_addrs=false); +OAAPI std::string symbol_name(const void *addr, bool require_exact_addr=true, bool no_pure_addrs=false); /** diff --git a/libopenage/util/compress/lzxd.cpp b/libopenage/util/compress/lzxd.cpp index 0ef7124949..778d8abaad 100644 --- a/libopenage/util/compress/lzxd.cpp +++ b/libopenage/util/compress/lzxd.cpp @@ -12,6 +12,7 @@ #include "lzxd.h" +#include #include #include #include @@ -21,8 +22,6 @@ #include #include -#include - #include "../../error/error.h" #include "../compiler.h" @@ -33,11 +32,6 @@ namespace util { namespace compress { -ssize_t min(ssize_t a, ssize_t b) { - return (a < b) ? a : b; -} - - // LZX specification constants constexpr unsigned LZX_MIN_MATCH = 2; //constexpr unsigned LZX_MAX_MATCH = 257; // seems to be unused. I'm scared. @@ -809,7 +803,7 @@ unsigned LZXDStream::decompress_next_frame(unsigned char *output_buf) { symbol_size = this->decode_symbol_from_aligned_block(); break; case LZX_BLOCKTYPE_UNCOMPRESSED: - symbol_size = this->read_data_from_uncompressed_block(min(this->block_remaining, LZX_FRAME_SIZE - frame_size)); + symbol_size = this->read_data_from_uncompressed_block(std::min(this->block_remaining, LZX_FRAME_SIZE - frame_size)); break; default: throw Error(MSG(err) << "this->blocktype neither verbatim nor aligned"); diff --git a/libopenage/util/compress/lzxd.h b/libopenage/util/compress/lzxd.h index b7b0edf942..23b2254bee 100644 --- a/libopenage/util/compress/lzxd.h +++ b/libopenage/util/compress/lzxd.h @@ -1,4 +1,4 @@ -// Copyright 2015-2016 the openage authors. See copying.md for legal info. +// Copyright 2015-2017 the openage authors. See copying.md for legal info. #pragma once @@ -32,7 +32,7 @@ constexpr unsigned LZX_FRAME_SIZE = 32768; * * unsigned decompress_next_frame(unsigned char *out_buf) except + */ -class LZXDecompressor { +class OAAPI LZXDecompressor { public: /* * Initialises LZX decompression state for decoding an LZX stream. diff --git a/libopenage/util/enum.h b/libopenage/util/enum.h index 00f5a63e5a..82e7e8e37d 100644 --- a/libopenage/util/enum.h +++ b/libopenage/util/enum.h @@ -1,4 +1,4 @@ -// Copyright 2015-2016 the openage authors. See copying.md for legal info. +// Copyright 2015-2017 the openage authors. See copying.md for legal info. #pragma once @@ -41,7 +41,7 @@ namespace util { * cppbool operator !=(Enum[T] arg) except + */ template -class Enum { +class OAAPI Enum { public: /** * Adds a new value to the enum. diff --git a/libopenage/util/enum_test.h b/libopenage/util/enum_test.h index 7bf2019508..ae4c469cce 100644 --- a/libopenage/util/enum_test.h +++ b/libopenage/util/enum_test.h @@ -1,4 +1,4 @@ -// Copyright 2015-2016 the openage authors. See copying.md for legal info. +// Copyright 2015-2017 the openage authors. See copying.md for legal info. #pragma once @@ -19,7 +19,7 @@ namespace tests { * cppclass testtype_data: * string stuff */ -struct testtype_data { +struct OAAPI testtype_data { std::string stuff; }; @@ -37,8 +37,8 @@ namespace testtypes { // pxd: testtype foo // pxd: testtype bar -extern testtype foo; -extern testtype bar; +extern OAAPI testtype foo; +extern OAAPI testtype bar; } // testtypes diff --git a/libopenage/util/externalsstream.h b/libopenage/util/externalsstream.h index 8e0b2e3e03..8f30c3d3dd 100644 --- a/libopenage/util/externalsstream.h +++ b/libopenage/util/externalsstream.h @@ -1,4 +1,4 @@ -// Copyright 2015-2016 the openage authors. See copying.md for legal info. +// Copyright 2015-2017 the openage authors. See copying.md for legal info. #include #include @@ -26,7 +26,7 @@ class ExternalStringBuf : public std::streambuf { } std::streamsize xsputn(const char *s, std::streamsize count) override { - output->append(s, count); + output->append(s, static_cast(count)); return count; } }; diff --git a/libopenage/util/fds.cpp b/libopenage/util/fds.cpp index 9dae977c14..4ad0b17258 100644 --- a/libopenage/util/fds.cpp +++ b/libopenage/util/fds.cpp @@ -9,7 +9,11 @@ #include #include "pty.h" +#ifdef _WIN32 +#include +#else #include +#endif #include "unicode.h" diff --git a/libopenage/util/fds.h b/libopenage/util/fds.h index 5805b5c27e..aaea41fd5b 100644 --- a/libopenage/util/fds.h +++ b/libopenage/util/fds.h @@ -1,9 +1,8 @@ -// Copyright 2014-2016 the openage authors. See copying.md for legal info. +// Copyright 2014-2017 the openage authors. See copying.md for legal info. #pragma once #include -#include #ifndef _WIN32 #include @@ -20,7 +19,7 @@ class FD { /** * wraps an existing FD */ - FD(int fd=STDOUT_FILENO); + FD(int fd); /** * duplicates an existing FD, and optionally diff --git a/libopenage/util/file.cpp b/libopenage/util/file.cpp index a8fe14bf0d..98204add54 100644 --- a/libopenage/util/file.cpp +++ b/libopenage/util/file.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include "path.h" #include "filelike/native.h" diff --git a/libopenage/util/file.h b/libopenage/util/file.h index ea14ccb1c2..fc5ecbdc66 100644 --- a/libopenage/util/file.h +++ b/libopenage/util/file.h @@ -36,7 +36,7 @@ class Path; * * shared_ptr[FileLike] get_fileobj() except + */ -class File { +class OAAPI File { public: using seek_t = filelike::FileLike::seek_t; using mode_t = filelike::FileLike::mode_t; diff --git a/libopenage/util/filelike/filelike.h b/libopenage/util/filelike/filelike.h index 3ac89ac40c..e99382c6a6 100644 --- a/libopenage/util/filelike/filelike.h +++ b/libopenage/util/filelike/filelike.h @@ -8,6 +8,7 @@ // pxd: from libcpp.string cimport string #include +#include "../compiler.h" namespace openage { namespace util { @@ -37,7 +38,7 @@ namespace filelike { * * bool is_python_native() noexcept */ -class FileLike { +class OAAPI FileLike { public: /** * Seek reference point. diff --git a/libopenage/util/filelike/python.h b/libopenage/util/filelike/python.h index c59664d462..0421bd7b59 100644 --- a/libopenage/util/filelike/python.h +++ b/libopenage/util/filelike/python.h @@ -49,7 +49,7 @@ class Python : public FileLike { ssize_t get_size() override; bool is_python_native() const noexcept override; - py::Obj &get_py_fileobj() const; + OAAPI py::Obj &get_py_fileobj() const; std::ostream &repr(std::ostream &) override; @@ -62,37 +62,37 @@ class Python : public FileLike { // used to call to python // pxd: PyIfFunc2[string, PyObjectPtr, ssize_t] pyx_file_read -extern pyinterface::PyIfFunc pyx_file_read; +extern OAAPI pyinterface::PyIfFunc pyx_file_read; // pxd: PyIfFunc3[size_t, PyObjectPtr, void *, ssize_t] pyx_file_read_to -extern pyinterface::PyIfFunc pyx_file_read_to; +extern OAAPI pyinterface::PyIfFunc pyx_file_read_to; // pxd: PyIfFunc1[bool, PyObjectPtr] pyx_file_readable -extern pyinterface::PyIfFunc pyx_file_readable; +extern OAAPI pyinterface::PyIfFunc pyx_file_readable; // pxd: PyIfFunc2[void, PyObjectPtr, const string&] pyx_file_write -extern pyinterface::PyIfFunc pyx_file_write; +extern OAAPI pyinterface::PyIfFunc pyx_file_write; // pxd: PyIfFunc1[bool, PyObjectPtr] pyx_file_writable -extern pyinterface::PyIfFunc pyx_file_writable; +extern OAAPI pyinterface::PyIfFunc pyx_file_writable; // pxd: PyIfFunc3[void, PyObjectPtr, ssize_t, int] pyx_file_seek -extern pyinterface::PyIfFunc pyx_file_seek; +extern OAAPI pyinterface::PyIfFunc pyx_file_seek; // pxd: PyIfFunc1[bool, PyObjectPtr] pyx_file_seekable -extern pyinterface::PyIfFunc pyx_file_seekable; +extern OAAPI pyinterface::PyIfFunc pyx_file_seekable; // pxd: PyIfFunc1[size_t, PyObjectPtr] pyx_file_tell -extern pyinterface::PyIfFunc pyx_file_tell; +extern OAAPI pyinterface::PyIfFunc pyx_file_tell; // pxd: PyIfFunc1[void, PyObjectPtr] pyx_file_close -extern pyinterface::PyIfFunc pyx_file_close; +extern OAAPI pyinterface::PyIfFunc pyx_file_close; // pxd: PyIfFunc1[void, PyObjectPtr] pyx_file_flush -extern pyinterface::PyIfFunc pyx_file_flush; +extern OAAPI pyinterface::PyIfFunc pyx_file_flush; // pxd: PyIfFunc1[ssize_t, PyObjectPtr] pyx_file_size -extern pyinterface::PyIfFunc pyx_file_size; +extern OAAPI pyinterface::PyIfFunc pyx_file_size; }}} // openage::util::filelike diff --git a/libopenage/util/fslike/directory.cpp b/libopenage/util/fslike/directory.cpp index 416555ecc1..9acffa3868 100644 --- a/libopenage/util/fslike/directory.cpp +++ b/libopenage/util/fslike/directory.cpp @@ -2,17 +2,33 @@ #include "directory.h" +// HACK: windows.h defines max and min as macros. This results in compile errors. +#ifdef _MSC_VER +// defining `NOMINMAX` disables the definition of those macros. +#define NOMINMAX +#endif + #include #include #include #include #include #include -#include #ifdef __APPLE__ #include #endif +#ifdef _MSC_VER +#include +#include +#include +// HACK: What the heck? I want the std::filesystem library! +#define O_NOCTTY 0 +#define O_NONBLOCK 0 +#define W_OK 2 +#else // ! _MSC_VER +#include +#endif #include "./native.h" #include "../file.h" @@ -146,7 +162,11 @@ bool Directory::mkdirs(const Path::parts_t &parts) { } // create the folder, umask will turn it to 755. +#ifdef _MSC_VER + bool dir_created = _mkdir(dirpath.c_str()) == 0; +#else bool dir_created = mkdir(dirpath.c_str(), 0777) == 0; +#endif if (not dir_created) { return false; @@ -209,6 +229,8 @@ bool Directory::touch(const Path::parts_t &parts) { // update the timestamp #ifdef __APPLE__ int result = utimes(path.c_str(), nullptr) == 0; +#elif defined _MSC_VER + int result = _utime(path.c_str(), nullptr) == 0; #else int result = utimensat(AT_FDCWD, path.c_str(), nullptr, 0) == 0; #endif @@ -229,6 +251,8 @@ int Directory::get_mtime(const Path::parts_t &parts) { if (std::get<1>(stat_result) == 0) { #ifdef __APPLE__ return std::get<0>(stat_result).st_mtimespec.tv_sec; +#elif defined _MSC_VER + return std::get<0>(stat_result).st_mtime; #else return std::get<0>(stat_result).st_mtim.tv_sec; #endif diff --git a/libopenage/util/fslike/fslike.h b/libopenage/util/fslike/fslike.h index 448b7be46d..d254708712 100644 --- a/libopenage/util/fslike/fslike.h +++ b/libopenage/util/fslike/fslike.h @@ -63,7 +63,7 @@ namespace fslike { * bool is_python_native() noexcept * shared_ptr[FSLike] shared_from_this() except + */ -class FSLike : public std::enable_shared_from_this { +class OAAPI FSLike : public std::enable_shared_from_this { public: FSLike(); diff --git a/libopenage/util/fslike/python.h b/libopenage/util/fslike/python.h index 0b47eb64a5..9a12cd5749 100644 --- a/libopenage/util/fslike/python.h +++ b/libopenage/util/fslike/python.h @@ -62,7 +62,7 @@ class Python : public FSLike { uint64_t get_filesize(const Path::parts_t &parts) override; bool is_python_native() const noexcept override; - py::Obj &get_py_fsobj() const; + OAAPI py::Obj &get_py_fsobj() const; std::ostream &repr(std::ostream &) override; @@ -72,56 +72,56 @@ class Python : public FSLike { // pxd: PyIfFunc2[bool, PyObjectPtr, const vector[string]] pyx_fs_is_file -extern pyinterface::PyIfFunc&> pyx_fs_is_file; +extern OAAPI pyinterface::PyIfFunc&> pyx_fs_is_file; // pxd: PyIfFunc2[bool, PyObjectPtr, const vector[string]] pyx_fs_is_dir -extern pyinterface::PyIfFunc&> pyx_fs_is_dir; +extern OAAPI pyinterface::PyIfFunc&> pyx_fs_is_dir; // pxd: PyIfFunc2[bool, PyObjectPtr, const vector[string]] pyx_fs_writable -extern pyinterface::PyIfFunc&> pyx_fs_writable; +extern OAAPI pyinterface::PyIfFunc&> pyx_fs_writable; // pxd: PyIfFunc2[vector[string], PyObjectPtr, const vector[string]] pyx_fs_list -extern pyinterface::PyIfFunc, PyObject *, const std::vector&> pyx_fs_list; +extern OAAPI pyinterface::PyIfFunc, PyObject *, const std::vector&> pyx_fs_list; // pxd: PyIfFunc2[bool, PyObjectPtr, const vector[string]] pyx_fs_mkdirs -extern pyinterface::PyIfFunc&> pyx_fs_mkdirs; +extern OAAPI pyinterface::PyIfFunc&> pyx_fs_mkdirs; // pxd: PyIfFunc2[File, PyObjectPtr, const vector[string]] pyx_fs_open_r -extern pyinterface::PyIfFunc&> pyx_fs_open_r; +extern OAAPI pyinterface::PyIfFunc&> pyx_fs_open_r; // pxd: PyIfFunc2[File, PyObjectPtr, const vector[string]] pyx_fs_open_w -extern pyinterface::PyIfFunc&> pyx_fs_open_w; +extern OAAPI pyinterface::PyIfFunc&> pyx_fs_open_w; // pxd: PyIfFunc2[Path, PyObjectPtr, const vector[string]] pyx_fs_resolve_r -extern pyinterface::PyIfFunc&> pyx_fs_resolve_r; +extern OAAPI pyinterface::PyIfFunc&> pyx_fs_resolve_r; // pxd: PyIfFunc2[Path, PyObjectPtr, const vector[string]] pyx_fs_resolve_w -extern pyinterface::PyIfFunc&> pyx_fs_resolve_w; +extern OAAPI pyinterface::PyIfFunc&> pyx_fs_resolve_w; // pxd: PyIfFunc2[PyObjectRef, PyObjectPtr, const vector[string]] pyx_fs_get_native_path -extern pyinterface::PyIfFunc&> pyx_fs_get_native_path; +extern OAAPI pyinterface::PyIfFunc&> pyx_fs_get_native_path; // pxd: PyIfFunc3[bool, PyObjectPtr, const vector[string], const vector[string]] pyx_fs_rename -extern pyinterface::PyIfFunc&, const std::vector&> pyx_fs_rename; +extern OAAPI pyinterface::PyIfFunc&, const std::vector&> pyx_fs_rename; // pxd: PyIfFunc2[bool, PyObjectPtr, const vector[string]] pyx_fs_rmdir -extern pyinterface::PyIfFunc&> pyx_fs_rmdir; +extern OAAPI pyinterface::PyIfFunc&> pyx_fs_rmdir; // pxd: PyIfFunc2[bool, PyObjectPtr, const vector[string]] pyx_fs_touch -extern pyinterface::PyIfFunc&> pyx_fs_touch; +extern OAAPI pyinterface::PyIfFunc&> pyx_fs_touch; // pxd: PyIfFunc2[bool, PyObjectPtr, const vector[string]] pyx_fs_unlink -extern pyinterface::PyIfFunc&> pyx_fs_unlink; +extern OAAPI pyinterface::PyIfFunc&> pyx_fs_unlink; // pxd: PyIfFunc2[int, PyObjectPtr, const vector[string]] pyx_fs_get_mtime -extern pyinterface::PyIfFunc&> pyx_fs_get_mtime; +extern OAAPI pyinterface::PyIfFunc&> pyx_fs_get_mtime; // pxd: PyIfFunc2[uint64_t, PyObjectPtr, const vector[string]] pyx_fs_get_filesize -extern pyinterface::PyIfFunc&> pyx_fs_get_filesize; +extern OAAPI pyinterface::PyIfFunc&> pyx_fs_get_filesize; // pxd: PyIfFunc1[bool, PyObjectPtr] pyx_fs_is_fslike_directory -extern pyinterface::PyIfFunc pyx_fs_is_fslike_directory; +extern OAAPI pyinterface::PyIfFunc pyx_fs_is_fslike_directory; }}} // openage::util::fslike diff --git a/libopenage/util/macro/concat.h b/libopenage/util/macro/concat.h index 5995a820f1..90c069b3d2 100644 --- a/libopenage/util/macro/concat.h +++ b/libopenage/util/macro/concat.h @@ -1,14 +1,23 @@ -// Copyright 2013-2016 the openage authors. See copying.md for legal info. +// Copyright 2013-2017 the openage authors. See copying.md for legal info. #pragma once -#define CONCAT_1(OP, X) (X) -#define CONCAT_2(OP, X, ...) (X) OP CONCAT_1(OP, __VA_ARGS__) -#define CONCAT_3(OP, X, ...) (X) OP CONCAT_2(OP, __VA_ARGS__) -#define CONCAT_4(OP, X, ...) (X) OP CONCAT_3(OP, __VA_ARGS__) -#define CONCAT_5(OP, X, ...) (X) OP CONCAT_4(OP, __VA_ARGS__) +#define CONCAT_1(OP, X) (X) +#define CONCAT_2(OP, X, Y) (X) OP (Y) +#define CONCAT_3(OP, X, Y, Z) (X) OP (Y) OP (Z) -#define CONCAT_N(_1, _2, _3, _4, _5, NAME, ...) NAME +#define CONCAT_N(_1, _2, _3, NAME, ...) NAME + +#ifdef _MSC_VER +#define CONCAT_COUNT_ARGS_IMPL(args) CONCAT_N args +#define CONCAT_COUNT_ARGS(...) CONCAT_COUNT_ARGS_IMPL((__VA_ARGS__, 3, 2, 1)) +#define CONCAT_HELPER2(count) CONCAT_##count +#define CONCAT_HELPER1(count) CONCAT_HELPER2(count) +#define CONCAT_HELPER(count) CONCAT_HELPER1(count) +#define CONCAT_GLUE(x, y) x y +#define CONCAT(OP, ...) CONCAT_GLUE(CONCAT_HELPER(CONCAT_COUNT_ARGS(__VA_ARGS__)), (OP, __VA_ARGS__)) +#else #define CONCAT(OP, ...) CONCAT_N(__VA_ARGS__, \ - CONCAT_5, CONCAT_4, CONCAT_3, CONCAT_2, CONCAT_1 \ + CONCAT_3, CONCAT_2, CONCAT_1 \ ) (OP, __VA_ARGS__) +#endif diff --git a/libopenage/util/macro/loop.h b/libopenage/util/macro/loop.h index fed84b25c8..0678afb960 100644 --- a/libopenage/util/macro/loop.h +++ b/libopenage/util/macro/loop.h @@ -1,14 +1,23 @@ -// Copyright 2013-2016 the openage authors. See copying.md for legal info. +// Copyright 2013-2017 the openage authors. See copying.md for legal info. #pragma once -#define LOOP_1(MACRO, X) MACRO(X) -#define LOOP_2(MACRO, X, ...) MACRO(X), LOOP_1(MACRO, __VA_ARGS__) -#define LOOP_3(MACRO, X, ...) MACRO(X), LOOP_2(MACRO, __VA_ARGS__) -#define LOOP_4(MACRO, X, ...) MACRO(X), LOOP_3(MACRO, __VA_ARGS__) -#define LOOP_5(MACRO, X, ...) MACRO(X), LOOP_4(MACRO, __VA_ARGS__) +#define LOOP_1(MACRO, X) MACRO(X) +#define LOOP_2(MACRO, X, Y) MACRO(X), MACRO(Y) +#define LOOP_3(MACRO, X, Y, Z) MACRO(X), MACRO(Y), MACRO(Z) -#define LOOP_N(_1, _2, _3, _4, _5, NAME, ...) NAME +#define LOOP_N(_1, _2, _3, NAME, ...) NAME + +#ifdef _MSC_VER +#define LOOP_COUNT_ARGS_IMPL(args) LOOP_N args +#define LOOP_COUNT_ARGS(...) LOOP_COUNT_ARGS_IMPL((__VA_ARGS__, 3, 2, 1)) +#define LOOP_HELPER2(count) LOOP_##count +#define LOOP_HELPER1(count) LOOP_HELPER2(count) +#define LOOP_HELPER(count) LOOP_HELPER1(count) +#define LOOP_GLUE(x, y) x y +#define LOOP(MACRO, ...) LOOP_GLUE(LOOP_HELPER(LOOP_COUNT_ARGS(__VA_ARGS__)), (MACRO, __VA_ARGS__)) +#else #define LOOP(MACRO, ...) LOOP_N(__VA_ARGS__, \ - LOOP_5, LOOP_4, LOOP_3, LOOP_2, LOOP_1 \ + LOOP_3, LOOP_2, LOOP_1 \ ) (MACRO, __VA_ARGS__) +#endif diff --git a/libopenage/util/path.h b/libopenage/util/path.h index b410344f04..64b71aaaff 100644 --- a/libopenage/util/path.h +++ b/libopenage/util/path.h @@ -43,7 +43,7 @@ class FSLike; * FSLike *get_fsobj() except + * const vector[string] &get_parts() except + */ -class Path { +class OAAPI Path { public: /** diff --git a/libopenage/util/profiler.h b/libopenage/util/profiler.h index 220301eeb9..d46e765a8c 100644 --- a/libopenage/util/profiler.h +++ b/libopenage/util/profiler.h @@ -1,4 +1,4 @@ -// Copyright 2015-2016 the openage authors. See copying.md for legal info. +// Copyright 2015-2017 the openage authors. See copying.md for legal info. #pragma once @@ -13,7 +13,7 @@ constexpr int PROFILER_CANVAS_WIDTH = 250; constexpr int PROFILER_CANVAS_HEIGHT = 120; constexpr int PROFILER_CANVAS_POSITION_X = 0; constexpr int PROFILER_CANVAS_POSITION_Y = 300; -constexpr float PROFILER_CANVAS_ALPHA = 0.6; +constexpr float PROFILER_CANVAS_ALPHA = 0.6f; constexpr int PROFILER_COM_BOX_WIDTH = 30; constexpr int PROFILER_COM_BOX_HEIGHT = 15; diff --git a/libopenage/util/quaternion_test.cpp b/libopenage/util/quaternion_test.cpp index b9b3744e8e..669cbedf46 100644 --- a/libopenage/util/quaternion_test.cpp +++ b/libopenage/util/quaternion_test.cpp @@ -62,10 +62,10 @@ void quaternion() { q2conj_exp.equals(q2.conjugated()) or TESTFAIL; Quaternion<> q2inv_exp{ - 0.0058823529411764705, - -0.023529411764705882, - -0.011764705882352941, - -0.047058823529411764 + 0.0058823529411764705f, + -0.023529411764705882f, + -0.011764705882352941f, + -0.047058823529411764f }; Quaternion<> q2inv = q2.inversed(); @@ -73,7 +73,7 @@ void quaternion() { q2.normalize(); Quaternion<> q2norm_exp{ - 0.10846522, 0.433860915, 0.216930457, 0.8677218312 + 0.10846522f, 0.433860915f, 0.216930457f, 0.8677218312f }; q2norm_exp.equals(q2) or TESTFAIL; } diff --git a/libopenage/util/stringformatter.h b/libopenage/util/stringformatter.h index c07c55f743..99f9f753e9 100644 --- a/libopenage/util/stringformatter.h +++ b/libopenage/util/stringformatter.h @@ -1,4 +1,4 @@ -// Copyright 2015-2016 the openage authors. See copying.md for legal info. +// Copyright 2015-2017 the openage authors. See copying.md for legal info. #pragma once @@ -61,7 +61,7 @@ class CachableOSStream { * * no-op if cs is nullptr. */ - static void release(CachableOSStream *cs); + static OAAPI void release(CachableOSStream *cs); private: /** @@ -124,6 +124,7 @@ class StringFormatter { this->stream_ptr = other.stream_ptr; other.stream_ptr = nullptr; + return *this; } // no copy construction! @@ -168,7 +169,7 @@ class StringFormatter { // Printf-style formatting - ChildType &fmt(const char *fmt, ...) __attribute__((format(printf, 2, 3))) { + ChildType &fmt(const char *fmt, ...) ATTRIBUTE_FORMAT(2, 3) { va_list ap; va_start(ap, fmt); util::vsformat(fmt, ap, *this->output); diff --git a/libopenage/util/strings.h b/libopenage/util/strings.h index 5dfea967ed..91bbe27c31 100644 --- a/libopenage/util/strings.h +++ b/libopenage/util/strings.h @@ -10,6 +10,11 @@ #include #include +#if defined(__GNUC__) +#define ATTRIBUTE_FORMAT(i, j) __attribute__ ((format (printf, i, j))) +#else +#define ATTRIBUTE_FORMAT(i, j) +#endif namespace openage { namespace util { @@ -60,7 +65,7 @@ std::ostream &operator <<(std::ostream &os, FixedPoint f) /** * printf-style to-string formatting. */ -std::string sformat(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +std::string sformat(const char *fmt, ...) ATTRIBUTE_FORMAT(1, 2); /** diff --git a/libopenage/util/timer.cpp b/libopenage/util/timer.cpp index 66faa04867..26355dd2e5 100644 --- a/libopenage/util/timer.cpp +++ b/libopenage/util/timer.cpp @@ -2,7 +2,7 @@ #include "timer.h" -#include "timing.h" +#include namespace openage { namespace util { diff --git a/openage/convert/dataformat/data_definition.py b/openage/convert/dataformat/data_definition.py index cef746579f..25c5494cf5 100644 --- a/openage/convert/dataformat/data_definition.py +++ b/openage/convert/dataformat/data_definition.py @@ -93,7 +93,7 @@ def generate_csv(self, genfile): entry = os.path.relpath( entry, os.path.dirname(self.name_data_file) - ) + ).replace(os.path.sep, '/') # HACK: Change to better path handling # encode each data field, to escape newlines and commas row_entries.append(encode_value(entry))