diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 585f5f7f..26e65d78 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -82,3 +82,79 @@ jobs: with: name: macOS artifacts path: ${{runner.workspace}}/build/bin/ + + cmake_win32: + runs-on: windows-2019 + steps: + - name: Set environment + run: | + echo "release_arch=Win32" >> "${Env:GITHUB_ENV}" + echo "vcpkg_triplet=x86-windows-static" >> "${Env:GITHUB_ENV}" + echo "vcpkg_git_commit_id=a3db16a4475b963cacf0260068c497fb72c8f3c0" >> "${Env:GITHUB_ENV}" + - name: Restore from cache and install vcpkg + uses: lukka/run-vcpkg@v6 + with: + setupOnly: true + vcpkgTriplet: ${{env.vcpkg_triplet}} + vcpkgGitCommitId: ${{env.vcpkg_git_commit_id}} + #- name: Install packages + # run: | + # & "${Env:VCPKG_ROOT}/vcpkg" install "cairo:${Env:vcpkg_triplet}" + - uses: actions/checkout@v2 + with: + submodules: recursive + - name: Create Build Environment + working-directory: ${{runner.workspace}} + run: cmake -E make_directory build + - name: Configure CMake + working-directory: ${{runner.workspace}}/build + run: | + cmake "${Env:GITHUB_WORKSPACE}" -G"Visual Studio 16 2019" -A"${Env:release_arch}" -DCMAKE_BUILD_TYPE="${Env:BUILD_TYPE}" -DVCPKG_TARGET_TRIPLET="${Env:vcpkg_triplet}" -DCMAKE_TOOLCHAIN_FILE="${Env:VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" + - name: Build all + working-directory: ${{runner.workspace}}/build + run: cmake --build . --config "${Env:BUILD_TYPE}" -j 2 + - name: Show built files + working-directory: ${{runner.workspace}}/build/bin + run: tree + - uses: actions/upload-artifact@v2 + with: + name: Win32 artifacts + path: ${{runner.workspace}}/build/bin/ + + cmake_win64: + runs-on: windows-2019 + steps: + - name: Set environment + run: | + echo "release_arch=x64" >> "${Env:GITHUB_ENV}" + echo "vcpkg_triplet=x64-windows-static" >> "${Env:GITHUB_ENV}" + echo "vcpkg_git_commit_id=a3db16a4475b963cacf0260068c497fb72c8f3c0" >> "${Env:GITHUB_ENV}" + - name: Restore from cache and install vcpkg + uses: lukka/run-vcpkg@v6 + with: + setupOnly: true + vcpkgTriplet: ${{env.vcpkg_triplet}} + vcpkgGitCommitId: ${{env.vcpkg_git_commit_id}} + #- name: Install packages + # run: | + # & "${Env:VCPKG_ROOT}/vcpkg" install "cairo:${Env:vcpkg_triplet}" + - uses: actions/checkout@v2 + with: + submodules: recursive + - name: Create Build Environment + working-directory: ${{runner.workspace}} + run: cmake -E make_directory build + - name: Configure CMake + working-directory: ${{runner.workspace}}/build + run: | + cmake "${Env:GITHUB_WORKSPACE}" -G"Visual Studio 16 2019" -A"${Env:release_arch}" -DCMAKE_BUILD_TYPE="${Env:BUILD_TYPE}" -DVCPKG_TARGET_TRIPLET="${Env:vcpkg_triplet}" -DCMAKE_TOOLCHAIN_FILE="${Env:VCPKG_INSTALLATION_ROOT}/scripts/buildsystems/vcpkg.cmake" + - name: Build all + working-directory: ${{runner.workspace}}/build + run: cmake --build . --config "${Env:BUILD_TYPE}" -j 2 + - name: Show built files + working-directory: ${{runner.workspace}}/build/bin + run: tree + - uses: actions/upload-artifact@v2 + with: + name: Win64 artifacts + path: ${{runner.workspace}}/build/bin/ diff --git a/.gitignore b/.gitignore index 317c26b8..77927d98 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,8 @@ .kdev_include_paths .kdev4/ .DS_Store +.vs/ +CMakeSettings.json bin/ build/ diff --git a/cmake/DPF-plugin.cmake b/cmake/DPF-plugin.cmake index 779c4631..45ec5653 100644 --- a/cmake/DPF-plugin.cmake +++ b/cmake/DPF-plugin.cmake @@ -293,7 +293,8 @@ function(dpf__build_lv2 NAME DGL_LIBRARY MONOLITHIC) COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} "$" "$" - WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.lv2") + WORKING_DIRECTORY "${PROJECT_BINARY_DIR}/bin/${NAME}.lv2" + DEPENDS lv2_ttl_generator) endfunction() # dpf__build_vst2 @@ -488,6 +489,22 @@ function(dpf__add_dgl_system_libs) # target_compile_definitions(dgl-system-libs-definitions INTERFACE "HAVE_XCURSOR") #endif() endif() + + if(MSVC) + file(MAKE_DIRECTORY "${DPF_ROOT_DIR}/khronos/GL") + foreach(_gl_header "glext.h") + if(NOT EXISTS "${DPF_ROOT_DIR}/khronos/GL/${_gl_header}") + file(DOWNLOAD "https://www.khronos.org/registry/OpenGL/api/GL/${_gl_header}" "${DPF_ROOT_DIR}/khronos/GL/${_gl_header}" SHOW_PROGRESS) + endif() + endforeach() + foreach(_khr_header "khrplatform.h") + if(NOT EXISTS "${DPF_ROOT_DIR}/khronos/KHR/${_khr_header}") + file(DOWNLOAD "https://www.khronos.org/registry/EGL/api/KHR/${_khr_header}" "${DPF_ROOT_DIR}/khronos/KHR/${_khr_header}" SHOW_PROGRESS) + endif() + endforeach() + target_include_directories(dgl-system-libs-definitions INTERFACE "${DPF_ROOT_DIR}/khronos") + endif() + target_link_libraries(dgl-system-libs INTERFACE dgl-system-libs-definitions) endfunction() @@ -498,14 +515,7 @@ endfunction() # function(dpf__add_executable NAME) add_executable("${NAME}" ${ARGN}) - set_target_properties("${NAME}" PROPERTIES - POSITION_INDEPENDENT_CODE TRUE - C_VISIBILITY_PRESET "hidden" - CXX_VISIBILITY_PRESET "hidden" - VISIBILITY_INLINES_HIDDEN TRUE) - if (MINGW) - target_compile_options("${NAME}" PUBLIC "-mstackrealign") - endif() + dpf__set_target_defaults("${NAME}") endfunction() # dpf__add_module @@ -515,17 +525,7 @@ endfunction() # function(dpf__add_module NAME) add_library("${NAME}" MODULE ${ARGN}) - set_target_properties("${NAME}" PROPERTIES - POSITION_INDEPENDENT_CODE TRUE - C_VISIBILITY_PRESET "hidden" - CXX_VISIBILITY_PRESET "hidden" - VISIBILITY_INLINES_HIDDEN TRUE) - if ((NOT WIN32 AND NOT APPLE) OR MINGW) - target_link_libraries("${NAME}" PRIVATE "-Wl,--no-undefined") - endif() - if (MINGW) - target_compile_options("${NAME}" PUBLIC "-mstackrealign") - endif() + dpf__set_target_defaults("${NAME}") endfunction() # dpf__add_static_library @@ -535,14 +535,30 @@ endfunction() # function(dpf__add_static_library NAME) add_library("${NAME}" STATIC ${ARGN}) + dpf__set_target_defaults("${NAME}") +endfunction() + +# dpf__set_target_defaults +# ------------------------------------------------------------------------------ +# +# Set default properties which must apply to all DPF-defined targets. +# +function(dpf__set_target_defaults NAME) set_target_properties("${NAME}" PROPERTIES POSITION_INDEPENDENT_CODE TRUE C_VISIBILITY_PRESET "hidden" CXX_VISIBILITY_PRESET "hidden" VISIBILITY_INLINES_HIDDEN TRUE) + if(WIN32) + target_compile_definitions("${NAME}" PUBLIC "NOMINMAX") + endif() if (MINGW) target_compile_options("${NAME}" PUBLIC "-mstackrealign") endif() + if (MSVC) + target_compile_options("${NAME}" PUBLIC "/UTF-8") + target_compile_definitions("${NAME}" PUBLIC "_CRT_SECURE_NO_WARNINGS") + endif() endfunction() # dpf__add_plugin_main @@ -597,7 +613,7 @@ function(dpf__add_lv2_ttl_generator) return() endif() add_executable(lv2_ttl_generator "${DPF_ROOT_DIR}/utils/lv2-ttl-generator/lv2_ttl_generator.c") - if(NOT WINDOWS AND NOT APPLE AND NOT HAIKU) + if((NOT WIN32) AND (NOT APPLE) AND (NOT HAIKU)) target_link_libraries(lv2_ttl_generator "dl") endif() endfunction() diff --git a/distrho/DistrhoUtils.hpp b/distrho/DistrhoUtils.hpp index 9741d82b..c1988667 100644 --- a/distrho/DistrhoUtils.hpp +++ b/distrho/DistrhoUtils.hpp @@ -33,6 +33,11 @@ # include #endif +#if defined(DISTRHO_OS_WINDOWS) && defined(_MSC_VER) +#include +typedef SSIZE_T ssize_t; +#endif + #if defined(DISTRHO_OS_MAC) && ! defined(CARLA_OS_MAC) && ! defined(DISTRHO_PROPER_CPP11_SUPPORT) namespace std { inline float fmin(float __x, float __y) @@ -94,12 +99,12 @@ static inline void d_debug(const char* const fmt, ...) noexcept { try { - ::va_list args; - ::va_start(args, fmt); + va_list args; + va_start(args, fmt); std::fprintf(stdout, "\x1b[30;1m"); std::vfprintf(stdout, fmt, args); std::fprintf(stdout, "\x1b[0m\n"); - ::va_end(args); + va_end(args); } catch (...) {} } #endif @@ -111,11 +116,11 @@ static inline void d_stdout(const char* const fmt, ...) noexcept { try { - ::va_list args; - ::va_start(args, fmt); + va_list args; + va_start(args, fmt); std::vfprintf(stdout, fmt, args); std::fprintf(stdout, "\n"); - ::va_end(args); + va_end(args); } catch (...) {} } @@ -126,11 +131,11 @@ static inline void d_stderr(const char* const fmt, ...) noexcept { try { - ::va_list args; - ::va_start(args, fmt); + va_list args; + va_start(args, fmt); std::vfprintf(stderr, fmt, args); std::fprintf(stderr, "\n"); - ::va_end(args); + va_end(args); } catch (...) {} } @@ -141,12 +146,12 @@ static inline void d_stderr2(const char* const fmt, ...) noexcept { try { - ::va_list args; - ::va_start(args, fmt); + va_list args; + va_start(args, fmt); std::fprintf(stderr, "\x1b[31m"); std::vfprintf(stderr, fmt, args); std::fprintf(stderr, "\x1b[0m\n"); - ::va_end(args); + va_end(args); } catch (...) {} } diff --git a/distrho/extra/String.hpp b/distrho/extra/String.hpp index 335cd9b8..c1ec9809 100644 --- a/distrho/extra/String.hpp +++ b/distrho/extra/String.hpp @@ -651,14 +651,18 @@ public: "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; +#ifndef _MSC_VER const std::size_t kTmpBufSize = std::min(d_nextPowerOf2(static_cast(dataSize/3)), 65536U); +#else + constexpr std::size_t kTmpBufSize = 65536U; +#endif const uchar* bytesToEncode((const uchar*)data); uint i=0, j=0; uint charArray3[3], charArray4[4]; - char strBuf[kTmpBufSize+1]; + char strBuf[kTmpBufSize + 1]; strBuf[kTmpBufSize] = '\0'; std::size_t strBufIndex = 0; diff --git a/distrho/src/DistrhoDefines.h b/distrho/src/DistrhoDefines.h index 40f9873e..a9a316bb 100644 --- a/distrho/src/DistrhoDefines.h +++ b/distrho/src/DistrhoDefines.h @@ -55,7 +55,7 @@ # if HAVE_CPP11_SUPPORT # define DISTRHO_PROPER_CPP11_SUPPORT # endif -#elif __cplusplus >= 201103L || (defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 405) || __has_extension(cxx_noexcept) +#elif __cplusplus >= 201103L || (defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 405) || __has_extension(cxx_noexcept) || (defined(_MSC_VER) && _MSVC_LANG >= 201103L) # define DISTRHO_PROPER_CPP11_SUPPORT # if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 407 && ! defined(__clang__)) || (defined(__clang__) && ! __has_extension(cxx_override_control)) # define override // gcc4.7+ only @@ -74,7 +74,7 @@ #if defined(__GNUC__) # define DISTRHO_DEPRECATED __attribute__((deprecated)) #elif defined(_MSC_VER) -# define DISTRHO_DEPRECATED __declspec(deprecated) +# define DISTRHO_DEPRECATED [[deprecated]] /* Note: __declspec(deprecated) it not applicable to enum members */ #else # define DISTRHO_DEPRECATED #endif diff --git a/distrho/src/DistrhoUIInternal.hpp b/distrho/src/DistrhoUIInternal.hpp index 21a0625e..47c5b07a 100644 --- a/distrho/src/DistrhoUIInternal.hpp +++ b/distrho/src/DistrhoUIInternal.hpp @@ -48,9 +48,9 @@ extern Window* d_lastUiWindow; // ----------------------------------------------------------------------- #if DISTRHO_PLUGIN_HAS_EXTERNAL_UI -UI* createUiWrapper(void* dspPtr, uintptr_t winId, double scaleFactor, const char* bundlePath); +UI* createUiWrapper(void* const dspPtr, const uintptr_t winId, const double scaleFactor, const char* const bundlePath); #else // DISTRHO_PLUGIN_HAS_EXTERNAL_UI -UI* createUiWrapper(void* dspPtr, Window* window); +UI* createUiWrapper(void* const dspPtr, Window* const window); #endif #if !DISTRHO_PLUGIN_HAS_EXTERNAL_UI diff --git a/distrho/src/DistrhoUILV2.cpp b/distrho/src/DistrhoUILV2.cpp index 184b8b39..67ece68d 100644 --- a/distrho/src/DistrhoUILV2.cpp +++ b/distrho/src/DistrhoUILV2.cpp @@ -289,7 +289,7 @@ protected: // reserve atom space const size_t atomSize = sizeof(LV2_Atom) + msgSize; - char atomBuf[atomSize]; + char* const atomBuf = (char*)malloc(atomSize); std::memset(atomBuf, 0, atomSize); // set atom info @@ -302,6 +302,9 @@ protected: // send to DSP side fWriteFunction(fController, eventInPortIndex, atomSize, fURIDs.atomEventTransfer, atom); + + // free atom space + free(atomBuf); } #if DISTRHO_PLUGIN_WANT_MIDI_INPUT diff --git a/distrho/src/dssi/dssi.h b/distrho/src/dssi/dssi.h index ce36e186..26f22290 100644 --- a/distrho/src/dssi/dssi.h +++ b/distrho/src/dssi/dssi.h @@ -35,6 +35,10 @@ extern "C" { #endif +#ifndef DSSI_PLUGIN_EXPORT +# define DSSI_PLUGIN_EXPORT LADSPA_PLUGIN_EXPORT +#endif + /* There is a need for an API that supports hosted MIDI soft synths with GUIs in Linux audio applications. In time the GMPI initiative @@ -411,7 +415,7 @@ typedef struct _DSSI_Descriptor { * of a distinct plugin type. */ -const DSSI_Descriptor *dssi_descriptor(unsigned long Index); +DSSI_PLUGIN_EXPORT const DSSI_Descriptor *dssi_descriptor(unsigned long Index); typedef const DSSI_Descriptor *(*DSSI_Descriptor_Function)(unsigned long Index); diff --git a/distrho/src/ladspa/ladspa.h b/distrho/src/ladspa/ladspa.h index 5c30a8a4..755bdfab 100644 --- a/distrho/src/ladspa/ladspa.h +++ b/distrho/src/ladspa/ladspa.h @@ -30,6 +30,14 @@ extern "C" { #endif +#ifndef LADSPA_PLUGIN_EXPORT +# ifdef _WIN32 +# define LADSPA_PLUGIN_EXPORT __declspec(dllexport) +# else +# define LADSPA_PLUGIN_EXPORT __attribute__((visibility("default"))) +# endif +#endif + /*****************************************************************************/ /* Overview: @@ -586,7 +594,7 @@ typedef struct _LADSPA_Descriptor { returning NULL, so the plugin count can be determined by checking for the least index that results in NULL being returned. */ -const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index); +LADSPA_PLUGIN_EXPORT const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index); /* Datatype corresponding to the ladspa_descriptor() function. */ typedef const LADSPA_Descriptor * diff --git a/utils/lv2-ttl-generator/lv2_ttl_generator.c b/utils/lv2-ttl-generator/lv2_ttl_generator.c index f52d41b0..3be02a1c 100644 --- a/utils/lv2-ttl-generator/lv2_ttl_generator.c +++ b/utils/lv2-ttl-generator/lv2_ttl_generator.c @@ -15,6 +15,7 @@ */ #include +#include #include #ifdef _WIN32 @@ -30,6 +31,11 @@ typedef void (*TTL_Generator_Function)(const char* basename); +static int isPathSeparator(char c); +static char* makeNormalPath(const char* path); + +// TODO support Unicode paths on the Windows platform + int main(int argc, char* argv[]) { if (argc != 2) @@ -38,10 +44,12 @@ int main(int argc, char* argv[]) return 1; } + const char* path = argv[1]; + #ifdef TTL_GENERATOR_WINDOWS - const HMODULE handle = LoadLibraryA(argv[1]); + const HMODULE handle = LoadLibraryA(path); #else - void* const handle = dlopen(argv[1], RTLD_LAZY); + void* const handle = dlopen(path, RTLD_LAZY); #endif if (! handle) @@ -62,31 +70,32 @@ int main(int argc, char* argv[]) if (ttlFn != NULL) { - char basename[strlen(argv[1])+1]; + // convert the paths to a normalized form, such that path separators are + // replaced with '/', and duplicate separators are removed + char* normalPath = makeNormalPath(path); -#ifdef TTL_GENERATOR_WINDOWS - char* base2 = strrchr(argv[1], '\\'); -#else - char* base2 = strrchr(argv[1], '/'); -#endif - if (base2 != NULL) - { - strcpy(basename, base2+1); - basename[strrchr(base2, '.')-base2-1] = '\0'; - } - else if (argv[1][0] == '.' && argv[1][1] == '/') - { - strcpy(basename, argv[1]+2); - basename[strrchr(basename, '.')-basename] = '\0'; - } + // get rid of any "./" prefixes + path = normalPath; + while (path[0] == '.' && path[1] == '/') + path += 2; + + // extract the file name part + char* basename = strrchr(path, '/'); + if (basename != NULL) + basename += 1; else - { - strcpy(basename, argv[1]); - } + basename = (char*)path; + + // remove the file extension + char* dotPos = strrchr(basename, '.'); + if (dotPos) + *dotPos = '\0'; - printf("Generate ttl data for '%s', basename: '%s'\n", argv[1], basename); + printf("Generate ttl data for '%s', basename: '%s'\n", path, basename); ttlFn(basename); + + free(normalPath); } else printf("Failed to find 'lv2_generate_ttl' function\n"); @@ -99,3 +108,31 @@ int main(int argc, char* argv[]) return 0; } + +static int isPathSeparator(char c) +{ +#ifdef TTL_GENERATOR_WINDOWS + return c == '/' || c == '\\'; +#else + return c == '/'; +#endif +} + +static char* makeNormalPath(const char* path) +{ + size_t i, j; + size_t len = strlen(path); + char* result = (char*)malloc(len + 1); + int isSep, wasSep = 0; + for (i = 0, j = 0; i < len; ++i) + { + isSep = isPathSeparator(path[i]); + if (!isSep) + result[j++] = path[i]; + else if (!wasSep) + result[j++] = '/'; + wasSep = isSep; + } + result[j] = '\0'; + return result; +}