From f7b62168c69b8992452e0c79ed1d5174e380e8b7 Mon Sep 17 00:00:00 2001 From: Vinicius Rangel Date: Sat, 20 Aug 2022 21:29:12 -0300 Subject: [PATCH] mingw build workflow --- .github/workflows/build.yml | 41 + .gitignore | 2 + ...sert_when_were_getting_line_metrics.patch} | 0 patches/mingw/0001-fixes-to-compile.patch | 650 ++++++++ ...002-gn-ninja-deletes-objs-workaround.patch | 26 + ...Don-t-download-prebuild-gn-and-emsdk.patch | 36 + patches/mingw/0006-add-missing-limits.patch | 12 + .../0007-add-mingw-toolchain-build.patch | 1313 +++++++++++++++++ .../0009-remove-as-needed-from-ldflags.patch | 27 + ...git-call-must-not-use-shell-in-mingw.patch | 25 + script/build.py | 52 +- script/checkout.py | 62 +- script/checkout_gn_mingw.py | 41 + script/common.py | 3 + 14 files changed, 2257 insertions(+), 33 deletions(-) rename patches/{13649_fix_assert_when_we're_getting_line_metrics.patch => 13649_fix_assert_when_were_getting_line_metrics.patch} (100%) create mode 100644 patches/mingw/0001-fixes-to-compile.patch create mode 100644 patches/mingw/0002-gn-ninja-deletes-objs-workaround.patch create mode 100644 patches/mingw/0003-Don-t-download-prebuild-gn-and-emsdk.patch create mode 100644 patches/mingw/0006-add-missing-limits.patch create mode 100644 patches/mingw/0007-add-mingw-toolchain-build.patch create mode 100644 patches/mingw/0009-remove-as-needed-from-ldflags.patch create mode 100644 patches/mingw/0010-git-call-must-not-use-shell-in-mingw.patch create mode 100644 script/checkout_gn_mingw.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 43d0c71..462e220 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -230,3 +230,44 @@ jobs: if: ${{ github.event.inputs.skip_release != 'true' }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + mingw: + runs-on: windows-2022 + strategy: + matrix: + build_type: [Debug, Release] + fail-fast: false + steps: + - run: git config --global core.autocrlf input + - uses: actions/checkout@v2 + - shell: bash + run: python3 script/check_release.py --version ${{ env.version }} --build-type ${{ matrix.build_type }} --host mingw + if: ${{ github.event.inputs.skip_release != 'true' }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - uses: msys2/setup-msys2@v2 + with: + msystem: 'MINGW64' + update: true + install: >- + git + mingw-w64-x86_64-python + mingw-w64-x86_64-ninja + mingw-w64-x86_64-gcc + - shell: msys2 {0} + run: python3 script/checkout.py --version ${{ env.version }} --host mingw + - shell: msys2 {0} + run: python3 script/checkout_gn_mingw.py --version ${{ env.version }} --host mingw + - shell: msys2 {0} + run: python3 script/build.py --build-type ${{ matrix.build_type }} --host mingw + - shell: bash + run: python3 script/archive.py --version ${{ env.version }} --build-type ${{ matrix.build_type }} --host mingw + - uses: actions/upload-artifact@v2 + with: + name: Skia-${{ env.version }}-mingw-${{ matrix.build_type }}-x64.zip + path: '*.zip' + - shell: bash + run: python3 script/release.py --version ${{ env.version }} --build-type ${{ matrix.build_type }} --host mingw + if: ${{ github.event.inputs.skip_release != 'true' }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + diff --git a/.gitignore b/.gitignore index 61bedf8..6ec9d1c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ /skia /depot_tools +/gn +/build *.zip __pycache__ \ No newline at end of file diff --git a/patches/13649_fix_assert_when_we're_getting_line_metrics.patch b/patches/13649_fix_assert_when_were_getting_line_metrics.patch similarity index 100% rename from patches/13649_fix_assert_when_we're_getting_line_metrics.patch rename to patches/13649_fix_assert_when_were_getting_line_metrics.patch diff --git a/patches/mingw/0001-fixes-to-compile.patch b/patches/mingw/0001-fixes-to-compile.patch new file mode 100644 index 0000000..cdf152a --- /dev/null +++ b/patches/mingw/0001-fixes-to-compile.patch @@ -0,0 +1,650 @@ +From f244a8bd9b2e2b472998720465ee0aa6b20acdcc Mon Sep 17 00:00:00 2001 +From: Vinicius Rangel +Date: Sat, 20 Aug 2022 16:16:52 -0300 +Subject: [PATCH] fixes to compile + +--- + BUILD.gn | 72 ++++++++++++++------ + gn/BUILDCONFIG.gn | 8 ++- + gn/portable/BUILD.gn | 4 +- + gn/skia/BUILD.gn | 79 ++++++++++++++-------- + gn/toolchain/BUILD.gn | 17 ++++- + src/ports/SkImageEncoder_WIC.cpp | 3 +- + src/ports/SkImageGeneratorWIC.cpp | 2 +- + src/ports/SkScalerContext_win_dw.cpp | 2 +- + src/utils/SkParse.cpp | 6 +- + third_party/third_party.gni | 2 +- + third_party/vulkanmemoryallocator/BUILD.gn | 2 +- + third_party/zlib/BUILD.gn | 10 +-- + 12 files changed, 142 insertions(+), 65 deletions(-) + +diff --git a/BUILD.gn b/BUILD.gn +index d59c186016..69f28b7c33 100644 +--- a/BUILD.gn ++++ b/BUILD.gn +@@ -184,7 +184,7 @@ opts("crc32") { + opts("sse2") { + enabled = is_x86 + sources = skia_opts.sse2_sources +- if (!is_clang && is_win) { ++ if (!is_clang && is_win && !is_mingw) { + defines = [ "SK_CPU_SSE_LEVEL=SK_CPU_SSE_LEVEL_SSE2" ] + } else { + cflags = [ "-msse2" ] +@@ -194,7 +194,7 @@ opts("sse2") { + opts("ssse3") { + enabled = is_x86 + sources = skia_opts.ssse3_sources +- if (!is_clang && is_win) { ++ if (!is_clang && is_win && !is_mingw) { + defines = [ "SK_CPU_SSE_LEVEL=SK_CPU_SSE_LEVEL_SSSE3" ] + } else { + cflags = [ "-mssse3" ] +@@ -204,7 +204,7 @@ opts("ssse3") { + opts("sse41") { + enabled = is_x86 + sources = skia_opts.sse41_sources +- if (!is_clang && is_win) { ++ if (!is_clang && is_win && !is_mingw) { + defines = [ "SK_CPU_SSE_LEVEL=SK_CPU_SSE_LEVEL_SSE41" ] + } else { + cflags = [ "-msse4.1" ] +@@ -214,7 +214,7 @@ opts("sse41") { + opts("sse42") { + enabled = is_x86 + sources = skia_opts.sse42_sources +- if (!is_clang && is_win) { ++ if (!is_clang && is_win && !is_mingw) { + defines = [ "SK_CPU_SSE_LEVEL=SK_CPU_SSE_LEVEL_SSE42" ] + } else { + cflags = [ "-msse4.2" ] +@@ -224,7 +224,7 @@ opts("sse42") { + opts("avx") { + enabled = is_x86 + sources = skia_opts.avx_sources +- if (is_win) { ++ if (is_win && !is_mingw) { + cflags = [ "/arch:AVX" ] + } else { + cflags = [ "-mavx" ] +@@ -237,7 +237,7 @@ opts("avx") { + opts("hsw") { + enabled = is_x86 + sources = skia_opts.hsw_sources +- if (is_win) { ++ if (is_win && !is_mingw) { + cflags = [ "/arch:AVX2" ] + } else { + cflags = [ "-march=haswell" ] +@@ -250,7 +250,7 @@ opts("hsw") { + opts("skx") { + enabled = is_x86 + sources = skia_opts.skx_sources +- if (is_win) { ++ if (is_win && !is_mingw) { + cflags = [ "/arch:AVX512" ] + } else { + cflags = [ "-march=skylake-avx512" ] +@@ -578,7 +578,11 @@ optional("fontmgr_win_gdi") { + + public = [ "include/ports/SkTypeface_win.h" ] + sources = [ "src/ports/SkFontHost_win.cpp" ] +- libs = [ "Gdi32.lib" ] ++ if (!is_mingw){ ++ libs = [ "Gdi32.lib" ] ++ } else { ++ libs = [ "gdi32" ] ++ } + } + + if (skia_lex) { +@@ -1679,7 +1679,7 @@ if (skia_enable_tools) { + } + + config("cpp17") { +- if (is_win) { ++ if (is_win && !is_mingw) { + cflags_cc = [ "/std:c++17" ] + } else { + cflags_cc = [ "-std=c++17" ] +@@ -943,7 +947,11 @@ optional("gpu") { + } else if (is_win && !skia_enable_winuwp) { + sources += [ "src/gpu/ganesh/gl/win/GrGLMakeNativeInterface_win.cpp" ] + if (target_cpu != "arm64") { +- libs += [ "OpenGL32.lib" ] ++ if (!is_mingw){ ++ libs = [ "OpenGL32.lib" ] ++ } else { ++ libs = [ "opengl32" ] ++ } + } + } else { + sources += [ "src/gpu/ganesh/gl/GrGLMakeNativeInterface_none.cpp" ] +@@ -1416,18 +1424,36 @@ skia_component("skia") { + "src/ports/SkOSFile_win.cpp", + "src/ports/SkOSLibrary_win.cpp", + ] +- libs += [ +- "Ole32.lib", +- "OleAut32.lib", +- ] + +- if (!skia_enable_winuwp) { ++ if (!is_mingw) { ++ libs += [ ++ "Ole32.lib", ++ "OleAut32.lib", ++ ] ++ } else { + libs += [ +- "FontSub.lib", +- "User32.lib", +- "Usp10.lib", ++ "ole32", ++ "oleaut32", ++ "uuid", + ] + } ++ ++ ++ if (!skia_enable_winuwp) { ++ if (!is_mingw) { ++ libs += [ ++ "FontSub.lib", ++ "User32.lib", ++ "Usp10.lib", ++ ] ++ } else { ++ libs += [ ++ "fontsub", ++ "user32", ++ "usp10", ++ ] ++ } ++ } + } else { + sources += [ + "src/ports/SkOSFile_posix.cpp", +@@ -1865,9 +1891,17 @@ if (skia_enable_tools) { + ] + } else if (is_win) { + sources += [ "tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp" ] +- libs += [ "Gdi32.lib" ] ++ if (!is_mingw){ ++ libs += [ "Gdi32.lib" ] ++ } else { ++ libs += [ "gdi32" ] ++ } + if (target_cpu != "arm64") { +- libs += [ "OpenGL32.lib" ] ++ if (!is_mingw){ ++ libs += [ "OpenGL32.lib" ] ++ } else { ++ libs += [ "opengl32" ] ++ } + } + } + } +diff --git a/gn/BUILDCONFIG.gn b/gn/BUILDCONFIG.gn +index 44f39c5aaa..c37cd5549b 100644 +--- a/gn/BUILDCONFIG.gn ++++ b/gn/BUILDCONFIG.gn +@@ -64,6 +64,8 @@ is_mac = current_os == "mac" + is_wasm = current_os == "wasm" + is_win = current_os == "win" + ++is_mingw = true ++ + # This is just to make the Dawn build files happy. Skia itself uses target_os = "linux" + # for ChromeOS, so this variable will not affect Skia proper. + is_chromeos = false +@@ -123,7 +125,7 @@ if (is_android) { + } + } + +-if (target_os == "win") { ++if (target_os == "win" && !is_mingw) { + # By default we look for 2017 (Enterprise, Pro, and Community), then 2015. If MSVC is installed in a + # non-default location, you can set win_vc to inform us where it is. + +@@ -134,7 +136,7 @@ if (target_os == "win") { + # directory. + } + +-if (target_os == "win") { ++if (target_os == "win" && !is_mingw) { + if (win_toolchain_version == "") { + win_toolchain_version = exec_script("//gn/highest_version_dir.py", + [ +@@ -224,7 +226,7 @@ if (!is_official_build) { + [ "//gn/skia:warnings_for_public_headers" ] + } + +-if (is_win) { ++if (is_win && !is_mingw) { + # Windows tool chain + set_default_toolchain("//gn/toolchain:msvc") + default_toolchain_name = "msvc" +diff --git a/gn/portable/BUILD.gn b/gn/portable/BUILD.gn +index 48cb62cc7f..0e34734dc1 100644 +--- a/gn/portable/BUILD.gn ++++ b/gn/portable/BUILD.gn +@@ -4,7 +4,7 @@ + # found in the LICENSE file. + + config("add_exceptions") { +- if (is_win) { ++ if (is_win && !is_mingw) { + cflags_cc = [ "/EHsc" ] + } else { + cflags_cc = [ "-fexceptions" ] +@@ -12,7 +12,7 @@ config("add_exceptions") { + } + + config("add_rtti") { +- if (is_win) { ++ if (is_win && !is_mingw) { + cflags_cc = [ "/GR" ] + } else { + cflags_cc = [ "-frtti" ] +diff --git a/gn/skia/BUILD.gn b/gn/skia/BUILD.gn +index e0f573c356..23e40f33ce 100644 +--- a/gn/skia/BUILD.gn ++++ b/gn/skia/BUILD.gn +@@ -60,7 +60,7 @@ config("default") { + # Disable warnings about unknown attributes. + # (These unknown attribute warnings are on by default, so we don't make + # disabling them part of :warnings, as some targets remove :warnings.) +- if (is_win && !is_clang) { ++ if (is_win && !is_clang && !is_mingw) { + cflags += [ "/wd5030" ] + } else { + cflags += [ "-Wno-attributes" ] +@@ -90,11 +90,25 @@ config("default") { + if (is_clang && target_cpu == "arm64") { + cflags += [ "--target=arm64-windows" ] + } +- cflags += [ +- "/bigobj", # Some of our files are bigger than the regular limits. +- "/utf-8", # Set Source and Executable character sets to UTF-8. +- ] +- cflags_cc += [ "/std:c++17" ] ++ if(!is_mingw) { ++ cflags += [ ++ "/bigobj", # Some of our files are bigger than the regular limits. ++ "/utf-8", # Set Source and Executable character sets to UTF-8. ++ ] ++ cflags_cc += [ "/std:c++17" ] ++ } else { ++ cflags += [ ++ "-fstrict-aliasing", ++ "-fPIC", ++ "-fvisibility=hidden", ++ ] ++ cflags_c += [ ++ "-fvisibility-inlines-hidden", ++ ] ++ cflags_cc += [ ++ "-std=c++17", ++ ] ++ } + defines += [ + "_CRT_SECURE_NO_WARNINGS", # Disables warnings about sscanf(). + "_HAS_EXCEPTIONS=0", # Disables exceptions in MSVC STL. +@@ -102,15 +116,19 @@ config("default") { + "NOMINMAX", + ] + +- _include_dirs = [ +- "$win_vc/Tools/MSVC/$win_toolchain_version/include", +- "$win_sdk/Include/$win_sdk_version/shared", +- "$win_sdk/Include/$win_sdk_version/ucrt", +- "$win_sdk/Include/$win_sdk_version/um", +- "$win_sdk/Include/$win_sdk_version/winrt", +- ] ++ if (!is_mingw) { ++ _include_dirs = [ ++ "$win_vc/Tools/MSVC/$win_toolchain_version/include", ++ "$win_sdk/Include/$win_sdk_version/shared", ++ "$win_sdk/Include/$win_sdk_version/ucrt", ++ "$win_sdk/Include/$win_sdk_version/um", ++ "$win_sdk/Include/$win_sdk_version/winrt", ++ ] ++ } else { ++ _include_dirs = [] ++ } + +- if (is_clang) { ++ if (is_clang && !is_mingw) { + foreach(dir, _include_dirs) { + cflags += [ + "-imsvc", +@@ -120,12 +138,15 @@ config("default") { + } else { + include_dirs = _include_dirs + } +- +- lib_dirs = [ +- "$win_sdk/Lib/$win_sdk_version/ucrt/$target_cpu", +- "$win_sdk/Lib/$win_sdk_version/um/$target_cpu", +- "$win_vc/Tools/MSVC/$win_toolchain_version/lib/$target_cpu", +- ] ++ if (!is_mingw){ ++ lib_dirs = [ ++ "$win_sdk/Lib/$win_sdk_version/ucrt/$target_cpu", ++ "$win_sdk/Lib/$win_sdk_version/um/$target_cpu", ++ "$win_vc/Tools/MSVC/$win_toolchain_version/lib/$target_cpu", ++ ] ++ } else { ++ lib_dirs = [] ++ } + } else { + cflags += [ + "-fstrict-aliasing", +@@ -144,7 +165,7 @@ config("default") { + "-mfpu=neon", + "-mthumb", + ] +- } else if (current_cpu == "x86" && !is_win) { ++ } else if (current_cpu == "x86" && is_mingw) { + asmflags += [ "-m32" ] + cflags += [ + "-m32", +@@ -154,7 +175,7 @@ config("default") { + ldflags += [ "-m32" ] + } + +- if (malloc != "" && !is_win) { ++ if (malloc != "" && is_mingw) { + cflags += [ + "-fno-builtin-malloc", + "-fno-builtin-calloc", +@@ -352,7 +373,7 @@ config("recover_pointer_overflow") { + + config("no_exceptions") { + # Exceptions are disabled by default on Windows. (Use /EHsc to enable them.) +- if (!is_win) { ++ if (!is_win || is_mingw) { + cflags_cc = [ "-fno-exceptions" ] + cflags_objcc = cflags_cc + } +@@ -365,14 +386,14 @@ config("warnings") { + cflags_objcc = [] + + if (werror) { +- if (is_win) { ++ if (!is_mingw && is_win) { + cflags += [ "/WX" ] + } else { + cflags += [ "-Werror" ] + } + } + +- if (is_win) { ++ if (is_win && !is_mingw) { + cflags += [ + "/W3", # Turn on lots of warnings. + +@@ -577,7 +598,7 @@ config("debug_symbols") { + "-gline-tables-only", + "-funwind-tables", # Helps make in-process backtraces fuller. + ] +- } else if (is_win) { ++ } else if (is_win && !is_mingw) { + cflags = [ "/Z7" ] + if (is_clang) { + cflags += [ "-gcodeview-ghash" ] +@@ -592,7 +613,7 @@ config("debug_symbols") { + + config("no_rtti") { + if (sanitize != "ASAN") { # -fsanitize=vptr requires RTTI +- if (is_win) { ++ if (is_win && !is_mingw) { + cflags_cc = [ "/GR-" ] + } else { + cflags_cc = [ "-fno-rtti" ] +@@ -602,7 +623,7 @@ config("no_rtti") { + } + + config("optimize") { +- if (is_win) { ++ if (is_win && !is_mingw) { + cflags = [ + "/O2", + "/Zc:inline", +@@ -642,7 +663,7 @@ config("executable") { + "-rdynamic", + "-Wl,-rpath,\$ORIGIN", + ] +- } else if (is_win) { ++ } else if (is_win && !is_mingw) { + ldflags = [ + "/SUBSYSTEM:CONSOLE", # Quiet "no subsystem specified; CONSOLE assumed". + "/INCREMENTAL:NO", # Quiet warnings about failing to incrementally link +diff --git a/gn/toolchain/BUILD.gn b/gn/toolchain/BUILD.gn +index ba85c3d54e..3864ace210 100644 +--- a/gn/toolchain/BUILD.gn ++++ b/gn/toolchain/BUILD.gn +@@ -322,6 +322,9 @@ template("gcc_like_toolchain") { + if (is_mac || is_ios) { + rpath = "-Wl,-install_name,@rpath/$soname" + } ++ if (is_mingw) { ++ rpath = "" # For PE/COFF the soname argument has no effect ++ } + + rspfile = "{{output}}.rsp" + rspfile_content = "{{inputs}}" +@@ -339,11 +342,23 @@ template("gcc_like_toolchain") { + _end_group = "" + } + +- command = "$link -shared {{ldflags}} $_start_group @$rspfile {{frameworks}} {{solibs}} $_end_group {{libs}} $rpath -o {{output}}" ++ _mingw_flags = "" ++ if (is_mingw) { ++ # Have MinGW linker generate a .def file and a .a import library ++ if (!is_clang) { ++ _mingw_flags += " -Wl,--dll " ++ } ++ _mingw_flags += ++ " -Wl,--output-def=$soname.def -Wl,--out-implib=$soname.a " ++ } ++ ++ command = "$link -shared {{ldflags}} $_start_group @$rspfile {{frameworks}} {{solibs}} $_end_group $_mingw_flags {{libs}} $rpath -o {{output}}" + outputs = [ "{{root_out_dir}}/$soname" ] + output_prefix = "lib" + if (is_mac || is_ios) { + default_output_extension = ".dylib" ++ } else if(is_mingw) { ++ default_output_extension = ".dll" + } else { + default_output_extension = ".so" + } +diff --git a/src/ports/SkImageEncoder_WIC.cpp b/src/ports/SkImageEncoder_WIC.cpp +index af1ec698ac..7cec2e8e65 100644 +--- a/src/ports/SkImageEncoder_WIC.cpp ++++ b/src/ports/SkImageEncoder_WIC.cpp +@@ -26,7 +26,8 @@ + //but CLSID_WICImagingFactory is then #defined to CLSID_WICImagingFactory2. + //Undo this #define if it has been done so that we link against the symbols + //we intended to link against on all SDKs. +-#if defined(CLSID_WICImagingFactory) ++ ++#if defined(CLSID_WICImagingFactory) && !defined(__MINGW32__) + #undef CLSID_WICImagingFactory + #endif + +diff --git a/src/ports/SkImageGeneratorWIC.cpp b/src/ports/SkImageGeneratorWIC.cpp +index a914d08fdb..891b2ec64d 100644 +--- a/src/ports/SkImageGeneratorWIC.cpp ++++ b/src/ports/SkImageGeneratorWIC.cpp +@@ -18,7 +18,7 @@ + // but CLSID_WICImagingFactory is then #defined to CLSID_WICImagingFactory2. + // Undo this #define if it has been done so that we link against the symbols + // we intended to link against on all SDKs. +-#if defined(CLSID_WICImagingFactory) ++#if defined(CLSID_WICImagingFactory) && !defined(__MINGW32__) + #undef CLSID_WICImagingFactory + #endif + +diff --git a/src/ports/SkScalerContext_win_dw.cpp b/src/ports/SkScalerContext_win_dw.cpp +index 045b59a361..ded0d3e156 100644 +--- a/src/ports/SkScalerContext_win_dw.cpp ++++ b/src/ports/SkScalerContext_win_dw.cpp +@@ -566,7 +566,7 @@ bool SkScalerContext_DW::isPngGlyph(const SkGlyph& glyph) { + + DWRITE_GLYPH_IMAGE_FORMATS f; + IDWriteFontFace4* fontFace4 = this->getDWriteTypeface()->fDWriteFontFace4.get(); +- HRBM(fontFace4->GetGlyphImageFormats(glyph.getGlyphID(), 0, UINT32_MAX, &f), ++ HRBM(fontFace4->GetGlyphImageFormats_(glyph.getGlyphID(), 0, UINT32_MAX, &f), + "Cannot get glyph image formats."); + return f & DWRITE_GLYPH_IMAGE_FORMATS_PNG; + } +@@ -580,7 +580,7 @@ bool SkScalerContext_DW::isSVGGlyph(const SkGlyph& glyph) { + + DWRITE_GLYPH_IMAGE_FORMATS f; + IDWriteFontFace4* fontFace4 = this->getDWriteTypeface()->fDWriteFontFace4.get(); +- HRBM(fontFace4->GetGlyphImageFormats(glyph.getGlyphID(), 0, UINT32_MAX, &f), ++ HRBM(fontFace4->GetGlyphImageFormats_(glyph.getGlyphID(), 0, UINT32_MAX, &f), + "Cannot get glyph image formats."); + return f & DWRITE_GLYPH_IMAGE_FORMATS_SVG; + } + +diff --git a/src/utils/SkParse.cpp b/src/utils/SkParse.cpp +index 085a7f6fcf..4bdb2cea4a 100644 +--- a/src/utils/SkParse.cpp ++++ b/src/utils/SkParse.cpp +@@ -208,7 +208,11 @@ const char* SkParse::FindMSec(const char str[], SkMSec* value) + + #if defined(SK_BUILD_FOR_WIN) + static const _locale_t kDefaultLocale = _create_locale(LC_ALL, "C"); +- #define strtof_l(a, b, c) _strtof_l((a), (b), (c)) ++ #if defined(__MINGW32__) ++ #define strtof_l(a, b, c) strtof(a, b) ++ #else ++ #define strtof_l(a, b, c) _strtof_l((a), (b), (c)) ++ #endif + #else + static const locale_t kDefaultLocale = newlocale(LC_ALL_MASK, "C", nullptr); + #endif +diff --git a/third_party/third_party.gni b/third_party/third_party.gni +index cbcd16cf38..7aa8e1e7b0 100644 +--- a/third_party/third_party.gni ++++ b/third_party/third_party.gni +@@ -92,7 +92,7 @@ template("third_party") { + if (!defined(cflags)) { + cflags = [] + } +- if (is_win) { ++ if (is_win && !is_mingw) { + cflags += [ "/w" ] + } else { + cflags += [ "-w" ] +diff --git a/third_party/vulkanmemoryallocator/BUILD.gn b/third_party/vulkanmemoryallocator/BUILD.gn +index f203a09591..5d7cfc47a4 100644 +--- a/third_party/vulkanmemoryallocator/BUILD.gn ++++ b/third_party/vulkanmemoryallocator/BUILD.gn +@@ -27,7 +27,7 @@ source_set("vulkanmemoryallocator") { + ] + + # Warnings are just noise if we're not maintaining the code. +- if (is_win) { ++ if (is_win && !is_mingw) { + cflags = [ "/w" ] + } else { + cflags = [ "-w" ] +diff --git a/third_party/zlib/BUILD.gn b/third_party/zlib/BUILD.gn +index 0c92eff65b..1212042c38 100644 +--- a/third_party/zlib/BUILD.gn ++++ b/third_party/zlib/BUILD.gn +@@ -50,7 +50,7 @@ if (skia_use_system_zlib) { + } + + # Warnings are just noise if we're not maintaining the code. +- if (is_win) { ++ if (is_win && !is_mingw) { + cflags = [ "/w" ] + } else { + cflags = [ "-w" ] +@@ -62,7 +62,7 @@ if (skia_use_system_zlib) { + configs += [ ":zlib_simd_config" ] + if (use_x86_x64_optimizations) { + defines = [ "ADLER32_SIMD_SSSE3" ] +- if (!is_win || is_clang) { ++ if (!is_win || is_clang || is_mingw) { + cflags = [ "-mssse3" ] + } + } +@@ -85,14 +85,14 @@ if (skia_use_system_zlib) { + # An ARMv7 GCC build will fail to compile without building this target + # for ARMv8-a+crc and letting runtime cpu detection select the correct + # function. +- if (!is_win && !is_clang) { ++ if (!is_win && !is_clang && !is_mingw) { + cflags_c = [ "-march=armv8-a+crc" ] + } + } + + if (use_x86_x64_optimizations) { + defines = [ "CRC32_SIMD_SSE42_PCLMUL" ] +- if (!is_win || is_clang) { ++ if (!is_win || is_clang || is_mingw) { + cflags = [ + "-msse4.2", + "-mpclmul", +@@ -138,7 +138,7 @@ if (skia_use_system_zlib) { + "CRC32_SIMD_SSE42_PCLMUL", + "DEFLATE_FILL_WINDOW_SSE2", + ] +- if (!is_win || is_clang) { ++ if (!is_win || is_clang || is_mingw) { + cflags = [ + "-msse4.2", + "-mpclmul", + +diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp +index d22cf559d1..01936879ad 100644 +--- a/src/ports/SkFontHost_win.cpp ++++ b/src/ports/SkFontHost_win.cpp +@@ -1073,7 +1073,8 @@ void SkScalerContext_GDI::RGBToA8(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, + for (int i = 0; i < width; i++) { + dst[i] = rgb_to_a8(src[i], table8); + if constexpr (kSkShowTextBlitCoverage) { +- dst[i] = std::max(dst[i], 10u); ++ uint8_t v = 10u; ++ dst[i] = std::max(dst[i], v); + } + } + src = SkTAddOffset(src, srcRB); + +diff --git a/src/utils/win/SkWGL_win.cpp b/src/utils/win/SkWGL_win.cpp +index 8987fbbde9..0f2f1635fe 100644 +--- a/src/utils/win/SkWGL_win.cpp ++++ b/src/utils/win/SkWGL_win.cpp +@@ -15,6 +15,8 @@ + #include "src/core/SkTSearch.h" + #include "src/core/SkTSort.h" + ++#include ++ + bool SkWGLExtensions::hasExtension(HDC dc, const char* ext) const { + if (nullptr == this->fGetExtensionsString) { + return false; + +diff --git a/src/ports/SkMemory_malloc.cpp b/src/ports/SkMemory_malloc.cpp +index 8839639f12..9369bf2055 100644 +--- a/src/ports/SkMemory_malloc.cpp ++++ b/src/ports/SkMemory_malloc.cpp +@@ -43,7 +43,7 @@ void sk_abort_no_print() { + // do not display a system dialog before aborting the process + _set_abort_behavior(0, _WRITE_ABORT_MSG); + #endif +-#if defined(SK_DEBUG) && defined(SK_BUILD_FOR_WIN) ++#if defined(SK_DEBUG) && defined(SK_BUILD_FOR_WIN) && !defined(__MINGW32__) + __fastfail(FAST_FAIL_FATAL_APP_EXIT); + #elif defined(__clang__) + __builtin_trap(); + +-- +2.37.1.windows.1 + diff --git a/patches/mingw/0002-gn-ninja-deletes-objs-workaround.patch b/patches/mingw/0002-gn-ninja-deletes-objs-workaround.patch new file mode 100644 index 0000000..613e377 --- /dev/null +++ b/patches/mingw/0002-gn-ninja-deletes-objs-workaround.patch @@ -0,0 +1,26 @@ +From 32c7b1cd351061bb4baa2af4f480b1e68997bd9c Mon Sep 17 00:00:00 2001 +From: Biswapriyo Nath +Date: Fri, 14 Aug 2020 09:34:44 +0530 +Subject: [PATCH 3/3] Do not remove output file after compilation + +Signed-off-by: Biswapriyo Nath +--- + build/build_linux.ninja.template | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/build/build_linux.ninja.template b/build/build_linux.ninja.template +index ab117fb..27339a7 100644 +--- a/build/build_linux.ninja.template ++++ b/build/build_linux.ninja.template +@@ -5,7 +5,7 @@ rule cxx + deps = gcc + + rule alink_thin +- command = rm -f $out && $ar rcsT $out $in ++ command = $ar rcsT $out $in + description = AR $out + + rule link +-- +2.27.0 + diff --git a/patches/mingw/0003-Don-t-download-prebuild-gn-and-emsdk.patch b/patches/mingw/0003-Don-t-download-prebuild-gn-and-emsdk.patch new file mode 100644 index 0000000..7616e3c --- /dev/null +++ b/patches/mingw/0003-Don-t-download-prebuild-gn-and-emsdk.patch @@ -0,0 +1,36 @@ +From dd5fa78166a2447fbf0a6c10990a622fb328b55e Mon Sep 17 00:00:00 2001 +From: Naveen M K +Date: Fri, 15 Apr 2022 17:00:39 +0530 +Subject: [PATCH] Don't download prebuild gn and emsdk + +Signed-off-by: Naveen M K +--- + tools/git-sync-deps | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/tools/git-sync-deps b/tools/git-sync-deps +index 44d936b4..1b94bcde 100755 +--- a/tools/git-sync-deps ++++ b/tools/git-sync-deps +@@ -259,12 +259,12 @@ def main(argv): + return 1 + + git_sync_deps(deps_file_path, argv, verbose) +- subprocess.check_call( +- [sys.executable, +- os.path.join(os.path.dirname(deps_file_path), 'bin', 'fetch-gn')]) +- subprocess.check_call( +- [sys.executable, +- os.path.join(os.path.dirname(deps_file_path), 'bin', 'activate-emsdk')]) ++ #subprocess.check_call( ++ # [sys.executable, ++ # os.path.join(os.path.dirname(deps_file_path), 'bin', 'fetch-gn')]) ++ #subprocess.check_call( ++ # [sys.executable, ++ # os.path.join(os.path.dirname(deps_file_path), 'bin', 'activate-emsdk')]) + return 0 + + +-- +2.35.2.windows.1 + diff --git a/patches/mingw/0006-add-missing-limits.patch b/patches/mingw/0006-add-missing-limits.patch new file mode 100644 index 0000000..faae03b --- /dev/null +++ b/patches/mingw/0006-add-missing-limits.patch @@ -0,0 +1,12 @@ +diff --git a/src/base/files/file_enumerator_win.cc b/src/base/files/file_enumerator_win.cc +index aa884ea8..7b6b3a35 100644 +--- a/src/base/files/file_enumerator_win.cc ++++ b/src/base/files/file_enumerator_win.cc +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + + #include "base/logging.h" + #include "base/win/win_util.h" diff --git a/patches/mingw/0007-add-mingw-toolchain-build.patch b/patches/mingw/0007-add-mingw-toolchain-build.patch new file mode 100644 index 0000000..e7ce5fb --- /dev/null +++ b/patches/mingw/0007-add-mingw-toolchain-build.patch @@ -0,0 +1,1313 @@ +diff --git a/config/BUILD.gn b/config/BUILD.gn +index ed94a16a0..3e4a62d24 100644 +--- a/config/BUILD.gn ++++ b/config/BUILD.gn +@@ -122,13 +122,13 @@ config("debug") { + defines += [ "DYNAMIC_ANNOTATIONS_PREFIX=NACL_" ] + } + +- if (is_win) { ++ if (is_win && !is_mingw) { + if (!enable_iterator_debugging && !use_custom_libcxx) { + # Iterator debugging is enabled by default by the compiler on debug + # builds, and we have to tell it to turn it off. + defines += [ "_HAS_ITERATOR_DEBUGGING=0" ] + } +- } else if ((is_linux || is_chromeos) && current_cpu == "x64" && ++ } else if ((is_linux || is_chromeos || is_mingw) && current_cpu == "x64" && + enable_iterator_debugging) { + # Enable libstdc++ debugging facilities to help catch problems early, see + # http://crbug.com/65151 . +@@ -163,7 +163,7 @@ config("release") { + + # This config defines the default libraries applied to all targets. + config("default_libs") { +- if (is_win) { ++ if (is_win && !is_mingw) { + # TODO(brettw) this list of defaults should probably be smaller, and + # instead the targets that use the less common ones (e.g. wininet or + # winspool) should include those explicitly. +@@ -289,8 +289,13 @@ group("shared_library_deps") { + + # Windows linker setup for EXEs and DLLs. + if (is_win) { +- _windows_linker_configs = [ +- "//build/config/win:sdk_link", ++ _windows_linker_configs = [] ++ if(!is_mingw){ ++ _windows_linker_configs += [ ++ "//build/config/win:sdk_link", ++ ] ++ } ++ _windows_linker_configs += [ + "//build/config/win:common_linker_setup", + ] + } +diff --git a/config/BUILDCONFIG.gn b/config/BUILDCONFIG.gn +index 725894d05..8918064c5 100644 +--- a/config/BUILDCONFIG.gn ++++ b/config/BUILDCONFIG.gn +@@ -130,12 +130,16 @@ declare_args() { + # separate flags. + is_official_build = false + ++ # Set to true when compiling with the MinGW GCC compiler on the MSYS2 environment. ++ is_mingw = getenv("MSYSTEM") != "" && getenv("MSYSTEM") != "MSYS" ++ + # Set to true when compiling with the Clang compiler. +- is_clang = current_os != "linux" || ++ is_clang = (current_os != "linux" || + (current_cpu != "s390x" && current_cpu != "s390" && + current_cpu != "ppc64" && current_cpu != "ppc" && + current_cpu != "mips" && current_cpu != "mips64" && +- current_cpu != "riscv64") ++ current_cpu != "riscv64")) || ++ (getenv("CXX") == "clang" || getenv("CXX") == "clang++") + + # Allows the path to a custom target toolchain to be injected as a single + # argument, and set as the default toolchain. +@@ -199,13 +203,17 @@ if (host_toolchain == "") { + # configurations we support this will always work and it saves build steps. + # Windows ARM64 targets require an x64 host for cross build. + if (target_cpu == "x86" || target_cpu == "x64") { +- if (is_clang) { ++ if (is_clang && !is_mingw) { + host_toolchain = "//build/toolchain/win:win_clang_$target_cpu" ++ } else if (is_mingw) { ++ host_toolchain = "//build/toolchain/win:mingw_$target_cpu" + } else { + host_toolchain = "//build/toolchain/win:$target_cpu" + } +- } else if (is_clang) { ++ } else if (is_clang && !is_mingw) { + host_toolchain = "//build/toolchain/win:win_clang_$host_cpu" ++ } else if (is_mingw) { ++ host_toolchain = "//build/toolchain/win:mingw_$host_cpu" + } else { + host_toolchain = "//build/toolchain/win:$host_cpu" + } +@@ -240,8 +248,10 @@ if (target_os == "android") { + } else if (target_os == "win") { + # On Windows, we use the same toolchain for host and target by default. + # Beware, win cross builds have some caveats, see docs/win_cross.md +- if (is_clang) { ++ if (is_clang && !is_mingw) { + _default_toolchain = "//build/toolchain/win:win_clang_$target_cpu" ++ } else if (is_mingw) { ++ _default_toolchain = "//build/toolchain/win:mingw_$target_cpu" + } else { + _default_toolchain = "//build/toolchain/win:$target_cpu" + } +diff --git a/config/compiler/BUILD.gn b/config/compiler/BUILD.gn +index 1904a2559..cd13c8d7d 100644 +--- a/config/compiler/BUILD.gn ++++ b/config/compiler/BUILD.gn +@@ -317,8 +317,8 @@ config("compiler") { + } + + # In general, Windows is totally different, but all the other builds share +- # some common compiler and linker configuration. +- if (!is_win) { ++ # some common GCC configuration. ++ if (!is_win || is_mingw) { + # Common POSIX compiler flags setup. + # -------------------------------- + cflags += [ "-fno-strict-aliasing" ] # See http://crbug.com/32204 +@@ -332,7 +332,7 @@ config("compiler") { + } else { + cflags += [ "-fstack-protector" ] + } +- } else if ((is_posix && !is_chromeos_ash && !is_nacl) || is_fuchsia) { ++ } else if ((is_posix && !is_chromeos && !is_nacl) || is_fuchsia || is_mingw) { + # TODO(phajdan.jr): Use -fstack-protector-strong when our gcc supports it. + # See also https://crbug.com/533294 + cflags += [ "--param=ssp-buffer-size=4" ] +@@ -343,6 +343,12 @@ config("compiler") { + } else if (current_os != "aix") { + # Not available on aix. + cflags += [ "-fstack-protector" ] ++ if(is_mingw) { ++ # In MingW's GCC -fstack-protector ++ # needs to be passed to the linker as well ++ # for it to link against the ssp library ++ ldflags += [ "-fstack-protector" ] ++ } + } + } + +@@ -375,7 +381,7 @@ config("compiler") { + + # Non-Mac Posix and Fuchsia compiler flags setup. + # ----------------------------------- +- if ((is_posix && !is_apple) || is_fuchsia) { ++ if ((is_posix && !is_apple) || is_fuchsia || is_mingw) { + if (enable_profiling) { + if (!is_debug) { + cflags += [ "-g" ] +@@ -515,11 +521,11 @@ config("compiler") { + # TODO(thakis): Make the driver pass --color-diagnostics to the linker + # if -fcolor-diagnostics is passed to it, and pass -fcolor-diagnostics + # in ldflags instead. +- if (is_win) { ++ if (is_win && !is_mingw) { + # On Windows, we call the linker directly, instead of calling it through + # the driver. + ldflags += [ "--color-diagnostics" ] +- } else { ++ } else if(!is_clang) { + ldflags += [ "-Wl,--color-diagnostics" ] + } + } +@@ -550,7 +556,7 @@ config("compiler") { + + # C11/C++11 compiler flags setup. + # --------------------------- +- if (is_linux || is_chromeos || is_android || (is_nacl && is_clang) || ++ if (is_linux || is_mingw || is_chromeos || is_android || (is_nacl && is_clang) || + current_os == "aix") { + if (target_os == "android") { + cxx11_override = use_cxx11_on_android +@@ -654,7 +660,7 @@ config("compiler") { + # should be able to better manage binary size increases on its own. + import_instr_limit = 5 + +- if (is_win) { ++ if (is_win && !is_mingw) { + ldflags += [ + "/opt:lldltojobs=all", + "-mllvm:-import-instr-limit=$import_instr_limit", +@@ -704,7 +710,7 @@ config("compiler") { + # TODO(https://crbug.com/1211155): investigate why this isn't effective on arm32. + if (!is_android || current_cpu == "arm64") { + cflags += [ "-fwhole-program-vtables" ] +- if (!is_win) { ++ if (!is_win || is_mingw) { + ldflags += [ "-fwhole-program-vtables" ] + } + } +@@ -722,7 +728,7 @@ config("compiler") { + if (compiler_timing) { + if (is_clang && !is_nacl) { + cflags += [ "-ftime-trace" ] +- } else if (is_win) { ++ } else if (is_win && !is_mingw) { + cflags += [ + # "Documented" here: + # http://aras-p.info/blog/2017/10/23/Best-unknown-MSVC-flag-d2cgsummary/ +@@ -742,12 +748,14 @@ config("compiler") { + # jumps. Turn it off by default and enable selectively for targets where it's + # beneficial. + if (use_lld && !enable_call_graph_profile_sort) { +- if (is_win) { ++ if (is_win && !is_mingw) { + ldflags += [ "/call-graph-profile-sort:no" ] + } else if (!is_apple) { + # TODO(thakis): Once LLD's Mach-O port basically works, implement call + # graph profile sorting for it, add an opt-out flag, and pass it here. +- ldflags += [ "-Wl,--no-call-graph-profile-sort" ] ++ if(!(is_mingw && is_clang)){ ++ ldflags += [ "-Wl,--no-call-graph-profile-sort" ] ++ } + } + } + +@@ -784,7 +792,7 @@ config("compiler") { + # Assign any flags set for the C compiler to asmflags so that they are sent + # to the assembler. The Windows assembler takes different types of flags + # so only do so for posix platforms. +- if (is_posix || is_fuchsia) { ++ if (is_posix || is_fuchsia || is_mingw) { + asmflags += cflags + asmflags += cflags_c + } +@@ -838,7 +846,7 @@ config("compiler_cpu_abi") { + ldflags = [] + defines = [] + +- if ((is_posix && !is_apple) || is_fuchsia) { ++ if ((is_posix && !is_apple) || is_fuchsia || is_mingw) { + # CPU architecture. We may or may not be doing a cross compile now, so for + # simplicity we always explicitly set the architecture. + if (current_cpu == "x64") { +@@ -1192,7 +1200,7 @@ config("compiler_deterministic") { + # Eliminate build metadata (__DATE__, __TIME__ and __TIMESTAMP__) for + # deterministic build. See https://crbug.com/314403 + if (!is_official_build) { +- if (is_win && !is_clang) { ++ if (is_win && !is_clang && !is_mingw) { + cflags += [ + "/wd4117", # Trying to define or undefine a predefined macro. + "/D__DATE__=", +@@ -1227,7 +1235,7 @@ config("compiler_deterministic") { + asmflags = [ "-Wa,-fdebug-compilation-dir,." ] + } + +- if (is_win && use_lld) { ++ if (is_win && use_lld && !is_mingw) { + if (symbol_level == 2 || (is_clang && using_sanitizer)) { + # Absolutize source file paths for PDB. Pass the real build directory + # if the pdb contains source-level debug information and if linker +@@ -1353,7 +1361,7 @@ config("default_warnings") { + cflags_cc = [] + ldflags = [] + +- if (is_win) { ++ if (is_win && !is_mingw) { + if (treat_warnings_as_errors) { + cflags += [ "/WX" ] + } +@@ -1563,15 +1571,34 @@ config("default_warnings") { + # files. + cflags += [ "-Wno-packed-not-aligned" ] + } ++ ++ if (is_mingw) { ++ cflags += [ ++ "-Wno-attributes", # "__decspec(dllimport) inline" ++ "-Wno-format", # PRIu64 llu support on MinGW ++ ] ++ if(!is_clang) { ++ cflags_cc += [ ++ "-Wno-subobject-linkage", # Tests having code in header files ++ ] ++ cflags += [ ++ "-Wno-unused-but-set-variable", ++ "-Wno-stringop-overflow", # False positive overflow error on gcc 10 ++ ] ++ } ++ } + } + + # Common Clang and GCC warning setup. +- if (!is_win || is_clang) { ++ if (!is_win || is_clang || is_mingw) { + cflags += [ + # Disables. + "-Wno-missing-field-initializers", # "struct foo f = {0};" + "-Wno-unused-parameter", # Unused function parameters. + ] ++ if(is_clang){ ++ cflags += ["-Wno-range-loop-construct"] # Use of "conditionally-supported" offsetof in c++17 ++ } + } + + if (is_clang) { +@@ -1617,12 +1644,16 @@ config("default_warnings") { + + # TODO(https://crbug.com/1028110): Evaluate and possible enable. + "-Wno-deprecated-copy", +- +- # TODO(https://crbug.com/1203071): Clean up and enable. +- "-Wno-unused-but-set-parameter", +- "-Wno-unused-but-set-variable", + ] + ++ if(!is_mingw){ # Clang on MinGW doesn't have these. ++ cflags += [ ++ # TODO(https://crbug.com/1203071): Clean up and enable. ++ "-Wno-unused-but-set-parameter", ++ "-Wno-unused-but-set-variable", ++ ] ++ } ++ + cflags_c += [ + # TODO(https://crbug.com/995993): Clean up and enable. + "-Wno-implicit-fallthrough", +@@ -1642,7 +1673,7 @@ config("default_warnings") { + # part of Chromium. + + config("chromium_code") { +- if (is_win) { ++ if (is_win && !is_mingw) { + cflags = [ "/W4" ] # Warning level 4. + + if (is_clang) { +@@ -1735,7 +1766,7 @@ config("no_chromium_code") { + cflags_cc = [] + defines = [] + +- if (is_win) { ++ if (is_win && !is_mingw) { + cflags += [ + "/W3", # Warning level 3. + "/wd4800", # Disable warning when forcing value to bool. +@@ -1798,7 +1829,7 @@ config("noshadowing") { + # Allows turning Run-Time Type Identification on or off. + + config("rtti") { +- if (is_win) { ++ if (is_win && !is_mingw) { + cflags_cc = [ "/GR" ] + } else { + cflags_cc = [ "-frtti" ] +@@ -1808,7 +1839,7 @@ config("rtti") { + config("no_rtti") { + # Some sanitizer configs may require RTTI to be left enabled globally + if (!use_rtti) { +- if (is_win) { ++ if (is_win && !is_mingw) { + cflags_cc = [ "/GR-" ] + } else { + cflags_cc = [ "-fno-rtti" ] +@@ -1850,7 +1881,7 @@ config("thin_archive") { + # archives. + # TODO(crbug.com/1221615): Enable on is_apple if use_lld once that no longer + # confuses lldb. +- if ((is_posix && !is_nacl && !is_apple) || is_fuchsia) { ++ if ((is_posix && !is_nacl && !is_apple) || is_fuchsia || is_mingw) { + arflags = [ "-T" ] + } else if (is_win && use_lld) { + arflags = [ "/llvmlibthin" ] +@@ -1863,7 +1894,7 @@ config("thin_archive") { + # Note: exceptions are disallowed in Google code. + + config("exceptions") { +- if (is_win) { ++ if (is_win && !is_mingw) { + # Enables exceptions in the STL. + if (!use_custom_libcxx) { + defines = [ "_HAS_EXCEPTIONS=1" ] +@@ -1872,11 +1903,17 @@ config("exceptions") { + } else { + cflags_cc = [ "-fexceptions" ] + cflags_objcc = cflags_cc ++ if (is_mingw && exclude_unwind_tables) { ++ # With exceptions explicitly allowed, ++ # override exclude_unwind_tables or ++ # linking will fail on MinGW ++ cflags_cc += [ "-funwind-tables", "-fasynchronous-unwind-tables" ] ++ } + } + } + + config("no_exceptions") { +- if (is_win) { ++ if (is_win && !is_mingw) { + # Disables exceptions in the STL. + # libc++ uses the __has_feature macro to control whether to use exceptions, + # so defining this macro is unnecessary. Defining _HAS_EXCEPTIONS to 0 also +@@ -1946,7 +1983,7 @@ config("no_shorten_64_warnings") { + if (is_clang) { + cflags = [ "-Wno-shorten-64-to-32" ] + } else { +- if (is_win) { ++ if (is_win && !is_mingw) { + # MSVC does not have an explicit warning equivalent to + # -Wshorten-64-to-32 but 4267 warns for size_t -> int + # on 64-bit builds, so is the closest. +@@ -1986,12 +2023,22 @@ config("no_incompatible_pointer_warnings") { + + # Shared settings for both "optimize" and "optimize_max" configs. + # IMPORTANT: On Windows "/O1" and "/O2" must go before the common flags. +-if (is_win) { +- common_optimize_on_cflags = [ ++if (is_win && !is_mingw) { ++ common_optimize_on_cflags = [] ++ if(is_clang) { ++ common_optimize_on_cflags += [ + "/Ob2", # Both explicit and auto inlining. ++ ] ++ } else { ++ common_optimize_on_cflags += [ ++ "/Ob3", # Both explicit and auto inlining. ++ ] ++ } ++ common_optimize_on_cflags += [ + "/Oy-", # Disable omitting frame pointers, must be after /O2. + "/Zc:inline", # Remove unreferenced COMDAT (faster links). + ] ++ + if (!is_asan) { + common_optimize_on_cflags += [ + # Put data in separate COMDATs. This allows the linker +@@ -2092,7 +2139,7 @@ config("default_stack_frames") { + + # Default "optimization on" config. + config("optimize") { +- if (is_win) { ++ if (is_win && !is_mingw) { + if (chrome_pgo_phase != 2) { + # Favor size over speed, /O1 must be before the common flags. + # /O1 implies /Os and /GF. +@@ -2127,7 +2174,7 @@ config("optimize") { + + # Turn off optimizations. + config("no_optimize") { +- if (is_win) { ++ if (is_win && !is_mingw) { + cflags = [ + "/Od", # Disable optimization. + "/Ob0", # Disable all inlining (on by default). +@@ -2179,7 +2226,7 @@ config("optimize_max") { + configs = [ "//build/config/nacl:irt_optimize" ] + } else { + ldflags = common_optimize_on_ldflags +- if (is_win) { ++ if (is_win && !is_mingw) { + # Favor speed over size, /O2 must be before the common flags. + # /O2 implies /Ot, /Oi, and /GF. + cflags = [ "/O2" ] + common_optimize_on_cflags +@@ -2211,7 +2258,7 @@ config("optimize_speed") { + configs = [ "//build/config/nacl:irt_optimize" ] + } else { + ldflags = common_optimize_on_ldflags +- if (is_win) { ++ if (is_win && !is_mingw) { + # Favor speed over size, /O2 must be before the common flags. + # /O2 implies /Ot, /Oi, and /GF. + cflags = [ "/O2" ] + common_optimize_on_cflags +@@ -2343,7 +2390,7 @@ config("win_pdbaltpath") { + + # Full symbols. + config("symbols") { +- if (is_win) { ++ if (is_win && !is_mingw) { + if (is_clang) { + cflags = [ "/Z7" ] # Debug information in the .obj files. + } else { +@@ -2385,7 +2432,8 @@ config("symbols") { + # build-directory-independent output. pnacl and nacl-clang do support that + # flag, so we can use use -g1 for pnacl and nacl-clang compiles. + # gcc nacl is is_nacl && !is_clang, pnacl and nacl-clang are && is_clang. +- if (!is_nacl || is_clang) { ++ # mingw cannot handle the size of the debug symbols generated. ++ if (!is_mingw && (!is_nacl || is_clang)) { + cflags += [ "-g2" ] + } + +@@ -2419,7 +2467,9 @@ config("symbols") { + # sections (llvm.org/PR34820). + cflags += [ "-ggnu-pubnames" ] + } +- ldflags += [ "-Wl,--gdb-index" ] ++ if(!(is_mingw && is_clang)){ ++ ldflags += [ "-Wl,--gdb-index" ] ++ } + } + } + +@@ -2438,7 +2488,7 @@ config("symbols") { + # This config guarantees to hold symbol for stack trace which are shown to user + # when crash happens in unittests running on buildbot. + config("minimal_symbols") { +- if (is_win) { ++ if (is_win && !is_mingw) { + # Functions, files, and line tables only. + cflags = [] + +@@ -2503,7 +2553,7 @@ config("minimal_symbols") { + # told to not generate debug information and the linker then just puts function + # names in the final debug information. + config("no_symbols") { +- if (is_win) { ++ if (is_win && !is_mingw) { + ldflags = [ "/DEBUG" ] + + # All configs using /DEBUG should include this: +@@ -2599,6 +2649,11 @@ buildflag_header("compiler_buildflags") { + config("cet_shadow_stack") { + if (enable_cet_shadow_stack && is_win) { + assert(target_cpu == "x64") +- ldflags = [ "/CETCOMPAT" ] ++ if(is_mingw){ ++ ldflags = [ "-fcf-protection=full" ] ++ cflags = [ "-fcf-protection=full" ] ++ } else { ++ ldflags = [ "/CETCOMPAT" ] ++ } + } + } +diff --git a/config/linux/pkg-config.py b/config/linux/pkg-config.py +index 5adf70cc3..e28e798df 100644 +--- a/config/linux/pkg-config.py ++++ b/config/linux/pkg-config.py +@@ -41,7 +41,11 @@ from optparse import OptionParser + # Additionally, you can specify the option --atleast-version. This will skip + # the normal outputting of a dictionary and instead print true or false, + # depending on the return value of pkg-config for the given package. +- ++# ++# --pkg_config_libdir= allows direct override ++# of the PKG_CONFIG_LIBDIR environment library. ++# ++# --full-path-libs causes lib names to include their full path. + + def SetConfigPath(options): + """Set the PKG_CONFIG_LIBDIR environment variable. +@@ -105,11 +109,29 @@ def RewritePath(path, strip_prefix, sysroot): + return path + + ++flag_regex = re.compile("(-.)(.+)") ++ ++def FlagReplace(matchobj): ++ if matchobj.group(1) == '-I': ++ return matchobj.group(1) + subprocess.check_output([u'cygpath',u'-w',matchobj.group(2)]).strip().decode("utf-8") ++ if matchobj.group(1) == '-L': ++ return matchobj.group(1) + subprocess.check_output([u'cygpath',u'-w',matchobj.group(2)]).strip().decode("utf-8") ++ if matchobj.group(1) == '-l': ++ return matchobj.group(1) + matchobj.group(2) + '.lib' ++ return matchobj.group(0) ++ ++def ConvertGCCToMSVC(flags): ++ """Rewrites GCC flags into MSVC flags.""" ++ # need a better way to determine mingw vs msvc build ++ if 'win32' not in sys.platform or "GCC" in sys.version: ++ return flags ++ return [ flag_regex.sub(FlagReplace,flag) for flag in flags] ++ + def main(): + # If this is run on non-Linux platforms, just return nothing and indicate + # success. This allows us to "kind of emulate" a Linux build from other + # platforms. +- if "linux" not in sys.platform: ++ if "linux" not in sys.platform and 'win32' not in sys.platform: + print("[[],[],[],[],[]]") + return 0 + +@@ -122,12 +144,15 @@ def main(): + parser.add_option('-a', action='store', dest='arch', type='string') + parser.add_option('--system_libdir', action='store', dest='system_libdir', + type='string', default='lib') ++ parser.add_option('--pkg_config_libdir', action='store', dest='pkg_config_libdir', ++ type='string') + parser.add_option('--atleast-version', action='store', + dest='atleast_version', type='string') + parser.add_option('--libdir', action='store_true', dest='libdir') + parser.add_option('--dridriverdir', action='store_true', dest='dridriverdir') + parser.add_option('--version-as-components', action='store_true', + dest='version_as_components') ++ parser.add_option('--full-path-libs', action='store_true', dest='full_path_libs') + (options, args) = parser.parse_args() + + # Make a list of regular expressions to strip out. +@@ -144,6 +169,10 @@ def main(): + else: + prefix = '' + ++ # Override PKG_CONFIG_LIBDIR ++ if options.pkg_config_libdir: ++ os.environ['PKG_CONFIG_LIBDIR'] = options.pkg_config_libdir ++ + if options.atleast_version: + # When asking for the return value, just run pkg-config and print the return + # value, no need to do other work. +@@ -203,7 +232,7 @@ def main(): + # For now just split on spaces to get the args out. This will break if + # pkgconfig returns quoted things with spaces in them, but that doesn't seem + # to happen in practice. +- all_flags = flag_string.strip().split(' ') ++ all_flags = ConvertGCCToMSVC(flag_string.strip().split(' ')) + + + sysroot = options.sysroot +@@ -220,7 +249,10 @@ def main(): + continue; + + if flag[:2] == '-l': +- libs.append(RewritePath(flag[2:], prefix, sysroot)) ++ library = RewritePath(flag[2:], prefix, sysroot) ++ # Skip math library on MSVC ++ if library != 'm.lib': ++ libs.append(library) + elif flag[:2] == '-L': + lib_dirs.append(RewritePath(flag[2:], prefix, sysroot)) + elif flag[:2] == '-I': +@@ -237,6 +269,14 @@ def main(): + else: + cflags.append(flag) + ++ if options.full_path_libs: ++ full_path_libs = [] ++ for lib_dir in lib_dirs: ++ for lib in libs: ++ if os.path.isfile(lib_dir+"/"+lib): ++ full_path_libs.append(lib_dir+"/"+lib) ++ libs = full_path_libs ++ + # Output a GN array, the first one is the cflags, the second are the libs. The + # JSON formatter prints GN compatible lists when everything is a list of + # strings. +diff --git a/config/linux/pkg_config.gni b/config/linux/pkg_config.gni +index 428e44ac0..a0d2175ee 100644 +--- a/config/linux/pkg_config.gni ++++ b/config/linux/pkg_config.gni +@@ -45,6 +45,9 @@ declare_args() { + # in similar fashion by setting the `system_libdir` variable in the build's + # args.gn file to 'lib' or 'lib64' as appropriate for the target architecture. + system_libdir = "lib" ++ ++ # Allow directly overriding the PKG_CONFIG_LIBDIR enviroment variable ++ pkg_config_libdir = "" + } + + pkg_config_script = "//build/config/linux/pkg-config.py" +@@ -87,6 +90,17 @@ if (host_pkg_config != "") { + host_pkg_config_args = pkg_config_args + } + ++if (pkg_config_libdir != "") { ++ pkg_config_args += [ ++ "--pkg_config_libdir", ++ pkg_config_libdir, ++ ] ++ host_pkg_config_args += [ ++ "--pkg_config_libdir", ++ pkg_config_libdir, ++ ] ++} ++ + template("pkg_config") { + assert(defined(invoker.packages), + "Variable |packages| must be defined to be a list in pkg_config.") +diff --git a/config/win/BUILD.gn b/config/win/BUILD.gn +index 59caa7b42..85b7099e5 100644 +--- a/config/win/BUILD.gn ++++ b/config/win/BUILD.gn +@@ -47,6 +47,7 @@ declare_args() { + # is applied to all targets. It is here to separate out the logic that is + # Windows-only. + config("compiler") { ++ if(!is_mingw){ + if (current_cpu == "x86") { + asmflags = [ + # When /safeseh is specified, the linker will only produce an image if it +@@ -69,16 +70,16 @@ config("compiler") { + cflags += [ "/Zc:twoPhase" ] + } + +- # Force C/C++ mode for the given GN detected file type. This is necessary +- # for precompiled headers where the same source file is compiled in both +- # modes. +- cflags_c = [ "/TC" ] +- cflags_cc = [ "/TP" ] ++ # Force C/C++ mode for the given GN detected file type. This is necessary ++ # for precompiled headers where the same source file is compiled in both ++ # modes. ++ cflags_c = [ "/TC" ] ++ cflags_cc = [ "/TP" ] + +- cflags += [ +- # Work around crbug.com/526851, bug in VS 2015 RTM compiler. +- "/Zc:sizedDealloc-", +- ] ++ cflags += [ ++ # Work around crbug.com/526851, bug in VS 2015 RTM compiler. ++ "/Zc:sizedDealloc-", ++ ] + + if (is_clang) { + # Required to make the 19041 SDK compatible with clang-cl. +@@ -188,6 +189,16 @@ config("compiler") { + # the source file is a no-op. + "/ignore:4221", + ] ++ } else { # is_mingw ++ cflags = [ ++ "-Wa,-mbig-obj" ++ ] ++ if(!is_clang) { ++ cflags += [ ++ "-fno-keep-inline-dllexport" ++ ] ++ } ++ } + } + + # This is included by reference in the //build/config/compiler:runtime_library +@@ -296,29 +307,31 @@ config("sdk_link") { + ldflags = [ "/MACHINE:ARM64" ] + } + +- vcvars_toolchain_data = exec_script("../../toolchain/win/setup_toolchain.py", +- [ +- visual_studio_path, +- windows_sdk_path, +- visual_studio_runtime_dirs, +- current_os, +- current_cpu, +- "none", +- ], +- "scope") +- +- vc_lib_path = vcvars_toolchain_data.vc_lib_path +- if (defined(vcvars_toolchain_data.vc_lib_atlmfc_path)) { +- vc_lib_atlmfc_path = vcvars_toolchain_data.vc_lib_atlmfc_path +- } +- vc_lib_um_path = vcvars_toolchain_data.vc_lib_um_path ++ if(!is_mingw){ ++ vcvars_toolchain_data = exec_script("../../toolchain/win/setup_toolchain.py", ++ [ ++ visual_studio_path, ++ windows_sdk_path, ++ visual_studio_runtime_dirs, ++ current_os, ++ current_cpu, ++ "none", ++ ], ++ "scope") ++ ++ vc_lib_path = vcvars_toolchain_data.vc_lib_path ++ if (defined(vcvars_toolchain_data.vc_lib_atlmfc_path)) { ++ vc_lib_atlmfc_path = vcvars_toolchain_data.vc_lib_atlmfc_path ++ } ++ vc_lib_um_path = vcvars_toolchain_data.vc_lib_um_path + +- lib_dirs = [ +- "$vc_lib_um_path", +- "$vc_lib_path", +- ] +- if (defined(vc_lib_atlmfc_path)) { +- lib_dirs += [ "$vc_lib_atlmfc_path" ] ++ lib_dirs = [ ++ "$vc_lib_um_path", ++ "$vc_lib_path", ++ ] ++ if (defined(vc_lib_atlmfc_path)) { ++ lib_dirs += [ "$vc_lib_atlmfc_path" ] ++ } + } + } + +@@ -326,19 +339,27 @@ config("sdk_link") { + # targets who want different library configurations can remove this and specify + # their own. + config("common_linker_setup") { +- ldflags = [ +- "/FIXED:NO", +- "/ignore:4199", +- "/ignore:4221", +- "/NXCOMPAT", +- "/DYNAMICBASE", +- ] +- +- if (win_linker_timing) { +- ldflags += [ +- "/time", +- "/verbose:incr", ++ if(is_mingw) { ++ # Enable DEP and ASLR ++ ldflags = [ ++ "-Wl,-dynamicbase", ++ "-Wl,-nxcompat", ++ ] ++ } else { ++ ldflags = [ ++ "/FIXED:NO", ++ "/ignore:4199", ++ "/ignore:4221", ++ "/NXCOMPAT", ++ "/DYNAMICBASE", + ] ++ ++ if (win_linker_timing) { ++ ldflags += [ ++ "/time", ++ "/verbose:incr", ++ ] ++ } + } + } + +@@ -347,7 +368,7 @@ config("default_cfg_compiler") { + # This is needed to allow functions to be called by code that is built + # with CFG enabled, such as system libraries. + # The CFG guards are only emitted if |win_enable_cfg_guards| is enabled. +- if (is_clang) { ++ if (is_clang && !is_mingw) { + if (win_enable_cfg_guards) { + cflags = [ "/guard:cf" ] + } else { +@@ -362,7 +383,7 @@ config("disable_guards_cfg_compiler") { + # Emit table of address-taken functions for Control-Flow Guard (CFG). + # This is needed to allow functions to be called by code that is built + # with CFG enabled, such as system libraries. +- if (is_clang) { ++ if (is_clang && !is_mingw) { + cflags = [ "/guard:cf,nochecks" ] + } + } +@@ -375,7 +396,7 @@ config("cfi_linker") { + # ASan and CFG leads to slow process startup. Chromium's test runner uses + # lots of child processes, so this means things are really slow. Disable CFG + # for now. https://crbug.com/846966 +- if (!is_debug && !is_asan) { ++ if (!is_debug && !is_asan && !is_mingw) { + # Turn on CFG bitmap generation and CFG load config. + ldflags = [ "/guard:cf" ] + } +@@ -466,20 +487,22 @@ config("delayloads_not_for_child_dll") { + # See https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx for a reference of + # what each value does. + config("default_crt") { +- if (is_component_build) { +- # Component mode: dynamic CRT. Since the library is shared, it requires +- # exceptions or will give errors about things not matching, so keep +- # exceptions on. +- configs = [ ":dynamic_crt" ] +- } else { +- if (current_os == "winuwp") { +- # https://blogs.msdn.microsoft.com/vcblog/2014/06/10/the-great-c-runtime-crt-refactoring/ +- # contains a details explanation of what is happening with the Windows +- # CRT in Visual Studio releases related to Windows store applications. ++ if(!is_mingw){ ++ if (is_component_build) { ++ # Component mode: dynamic CRT. Since the library is shared, it requires ++ # exceptions or will give errors about things not matching, so keep ++ # exceptions on. + configs = [ ":dynamic_crt" ] + } else { +- # Desktop Windows: static CRT. +- configs = [ ":static_crt" ] ++ if (current_os == "winuwp") { ++ # https://blogs.msdn.microsoft.com/vcblog/2014/06/10/the-great-c-runtime-crt-refactoring/ ++ # contains a details explanation of what is happening with the Windows ++ # CRT in Visual Studio releases related to Windows store applications. ++ configs = [ ":dynamic_crt" ] ++ } else { ++ # Desktop Windows: static CRT. ++ configs = [ ":static_crt" ] ++ } + } + } + } +@@ -541,42 +564,58 @@ config("static_crt") { + if (current_cpu == "x64") { + # The number after the comma is the minimum required OS version. + # 5.02 = Windows Server 2003. +- subsystem_version_suffix = ",5.02" ++ subsystem_version_suffix = "5.02" + } else if (current_cpu == "arm64") { + # Windows ARM64 requires Windows 10. +- subsystem_version_suffix = ",10.0" ++ subsystem_version_suffix = "10.0" + } else { + # 5.01 = Windows XP. +- subsystem_version_suffix = ",5.01" ++ subsystem_version_suffix = "5.01" + } + + config("console") { +- ldflags = [ "/SUBSYSTEM:CONSOLE$subsystem_version_suffix" ] ++ if(is_mingw){ ++ if(!is_clang) { ++ cflags = [ "-mconsole" ] ++ } ++ ldflags = [ "-Wl,--subsystem,console:$subsystem_version_suffix" ] ++ } else { ++ ldflags = [ "/SUBSYSTEM:CONSOLE,$subsystem_version_suffix" ] ++ } + } + config("windowed") { +- ldflags = [ "/SUBSYSTEM:WINDOWS$subsystem_version_suffix" ] ++ if(is_mingw){ ++ if(!is_clang) { ++ cflags = [ "-mwindows" ] ++ } ++ ldflags = [ "-Wl,--subsystem,windows:$subsystem_version_suffix" ] ++ } else { ++ ldflags = [ "/SUBSYSTEM:WINDOWS,$subsystem_version_suffix" ] ++ } + } + + # Incremental linking ---------------------------------------------------------- + + # Applies incremental linking or not depending on the current configuration. + config("default_incremental_linking") { +- # Enable incremental linking for debug builds and all component builds - any +- # builds where performance is not job one. +- # TODO(thakis): Always turn this on with lld, no reason not to. +- if (is_debug || is_component_build) { +- ldflags = [ "/INCREMENTAL" ] +- if (use_lld) { +- # lld doesn't use ilk files and doesn't really have an incremental link +- # mode; the only effect of the flag is that the .lib file timestamp isn't +- # updated if the .lib doesn't change. +- # TODO(thakis): Why pass /OPT:NOREF for lld, but not otherwise? +- # TODO(thakis): /INCREMENTAL is on by default in link.exe, but not in +- # lld. +- ldflags += [ "/OPT:NOREF" ] ++ if(!is_mingw){ ++ # Enable incremental linking for debug builds and all component builds - any ++ # builds where performance is not job one. ++ # TODO(thakis): Always turn this on with lld, no reason not to. ++ if (is_debug || is_component_build) { ++ ldflags = [ "/INCREMENTAL" ] ++ if (use_lld) { ++ # lld doesn't use ilk files and doesn't really have an incremental link ++ # mode; the only effect of the flag is that the .lib file timestamp isn't ++ # updated if the .lib doesn't change. ++ # TODO(thakis): Why pass /OPT:NOREF for lld, but not otherwise? ++ # TODO(thakis): /INCREMENTAL is on by default in link.exe, but not in ++ # lld. ++ ldflags += [ "/OPT:NOREF" ] ++ } ++ } else { ++ ldflags = [ "/INCREMENTAL:NO" ] + } +- } else { +- ldflags = [ "/INCREMENTAL:NO" ] + } + } + +@@ -588,6 +627,9 @@ config("unicode") { + "_UNICODE", + "UNICODE", + ] ++ if(is_mingw) { ++ cflags = [ "-municode" ] ++ } + } + + # Lean and mean ---------------------------------------------------------------- +@@ -608,3 +650,21 @@ config("lean_and_mean") { + config("nominmax") { + defines = [ "NOMINMAX" ] + } ++ ++# Let unit tests see all "for_testing" dll symbols. ++config("export_all_symbols") { ++ if(is_win && is_mingw){ ++ ldflags = [ "-Wl,--export-all-symbols" ] ++ } ++} ++ ++# Workaround a Mingw ld bug where large debug symbol data ++# causes the produced executable to be corrupted ++# https://stackoverflow.com/questions/22261539/ld-exe-crashing-in-mingw ++# this affects mksnapshot and v8 component. ++ ++config("strip_all_symbols_at_link_time") { ++ if(is_win && is_mingw){ ++ ldflags = [ "-Wl,--strip-all" ] ++ } ++} +diff --git a/config/win/manifest.gni b/config/win/manifest.gni +index e2115083f..c6bdef8fb 100644 +--- a/config/win/manifest.gni ++++ b/config/win/manifest.gni +@@ -85,12 +85,14 @@ if (is_win) { + foreach(i, rebase_path(invoker.sources, root_build_dir)) { + manifests += [ "/manifestinput:" + i ] + } +- ldflags = [ +- "/manifest:embed", ++ if(!is_mingw){ ++ ldflags = [ ++ "/manifest:embed", + +- # We handle UAC by adding explicit .manifest files instead. +- "/manifestuac:no", +- ] + manifests ++ # We handle UAC by adding explicit .manifest files instead. ++ "/manifestuac:no", ++ ] + manifests ++ } + } + + # This source set only exists to add a dep on the invoker's deps and to +diff --git a/config/x64.gni b/config/x64.gni +index 9e86979cb..ca8f47501 100644 +--- a/config/x64.gni ++++ b/config/x64.gni +@@ -16,7 +16,7 @@ if (current_cpu == "x64") { + x64_arch = "" + } + +- if ((is_posix && !is_apple) || is_fuchsia) { ++ if ((is_posix && !is_apple) || is_fuchsia || is_mingw) { + if (x64_arch == "") { + x64_arch = "x86-64" + } +diff --git a/toolchain/gcc_solink_wrapper.py b/toolchain/gcc_solink_wrapper.py +index 39aef4d1e..7e83b058a 100644 +--- a/toolchain/gcc_solink_wrapper.py ++++ b/toolchain/gcc_solink_wrapper.py +@@ -18,10 +18,11 @@ import sys + + import wrapper_utils + +- + def CollectSONAME(args): + """Replaces: readelf -d $sofile | grep SONAME""" + toc = '' ++ if ("GCC" in sys.version and sys.platform=='win32'): # Mingw's readelf doesn't work on PE files ++ return 0, toc + readelf = subprocess.Popen(wrapper_utils.CommandToRun( + [args.readelf, '-d', args.sofile]), + stdout=subprocess.PIPE, +@@ -36,6 +37,10 @@ def CollectSONAME(args): + def CollectDynSym(args): + """Replaces: nm --format=posix -g -D -p $sofile | cut -f1-2 -d' '""" + toc = '' ++ ++ if ("GCC" in sys.version and sys.platform=='win32'): # Mingw's nm doesn't work on PE/COFF files ++ return 0, toc ++ + nm = subprocess.Popen(wrapper_utils.CommandToRun( + [args.nm, '--format=posix', '-g', '-D', '-p', args.sofile]), + stdout=subprocess.PIPE, +@@ -94,6 +99,9 @@ def main(): + help='The strip binary to run', + metavar='PATH') + parser.add_argument('--dwp', help='The dwp binary to run', metavar='PATH') ++ parser.add_argument('--objcopy', ++ help='The objcopy binary to run', ++ metavar='PATH') + parser.add_argument('--sofile', + required=True, + help='Shared object file produced by linking command', +@@ -183,8 +191,18 @@ def main(): + + # Finally, strip the linked shared object file (if desired). + if args.strip: ++ if args.objcopy: ++ result = subprocess.call(wrapper_utils.CommandToRun( ++ [args.objcopy, '--only-keep-debug', args.sofile, args.output + '.debug'])) ++ if result != 0: ++ return result + result = subprocess.call(wrapper_utils.CommandToRun( + [args.strip, '-o', args.output, args.sofile])) ++ if result != 0: ++ return result ++ if args.objcopy: ++ result = subprocess.call(wrapper_utils.CommandToRun( ++ [args.objcopy, '--add-gnu-debuglink', args.output + '.debug',args.output])) + + if dwp_proc: + dwp_result = dwp_proc.wait() +@@ -193,6 +211,5 @@ def main(): + + return result + +- + if __name__ == "__main__": + sys.exit(main()) +diff --git a/toolchain/gcc_toolchain.gni b/toolchain/gcc_toolchain.gni +index a303d472b..789bc930a 100644 +--- a/toolchain/gcc_toolchain.gni ++++ b/toolchain/gcc_toolchain.gni +@@ -56,6 +56,7 @@ if (enable_resource_allowlist_generation) { + # - cc + # - cxx + # - ld ++# - rc (mingw only) + # + # Optional parameters that control the tools: + # +@@ -108,7 +109,9 @@ template("gcc_toolchain") { + assert(defined(invoker.cc), "gcc_toolchain() must specify a \"cc\" value") + assert(defined(invoker.cxx), "gcc_toolchain() must specify a \"cxx\" value") + assert(defined(invoker.ld), "gcc_toolchain() must specify a \"ld\" value") +- ++ if(is_mingw){ ++ assert(defined(invoker.rc), "gcc_toolchain() must specify a \"rc\" value") ++ } + # This define changes when the toolchain changes, forcing a rebuild. + # Nothing should ever use this define. + if (defined(invoker.rebuild_define)) { +@@ -279,15 +282,20 @@ template("gcc_toolchain") { + asm = asm_prefix + invoker.cc + ar = invoker.ar + ld = link_prefix + invoker.ld +- if (defined(invoker.readelf)) { +- readelf = invoker.readelf +- } else { +- readelf = "readelf" ++ if(!is_mingw){ ++ if (defined(invoker.readelf)) { ++ readelf = invoker.readelf ++ } else { ++ readelf = "readelf" ++ } ++ if (defined(invoker.nm)) { ++ nm = invoker.nm ++ } else { ++ nm = "nm" ++ } + } +- if (defined(invoker.nm)) { +- nm = invoker.nm +- } else { +- nm = "nm" ++ else { ++ rc = invoker.rc + } + if (defined(invoker.dwp)) { + dwp_switch = " --dwp=\"${invoker.dwp}\"" +@@ -295,6 +303,7 @@ template("gcc_toolchain") { + dwp_switch = "" + } + ++ + if (defined(invoker.shlib_extension)) { + default_shlib_extension = invoker.shlib_extension + } else { +@@ -372,6 +381,16 @@ template("gcc_toolchain") { + outputs = [ "$object_subdir/{{source_name_part}}.o" ] + } + ++ if(is_mingw){ ++ tool("rc") { ++ depfile = "{{output}}.d" ++ command = "$rc -i {{source}} -o {{output}}" ++ depsformat = "gcc" ++ description = "RC {{output}}" ++ outputs = [ "$object_subdir/{{source_name_part}}.o" ] ++ } ++ } ++ + tool("asm") { + # For GCC we can just use the C compiler to compile assembly. + depfile = "{{output}}.d" +@@ -435,8 +454,6 @@ template("gcc_toolchain") { + # .TOC file, overwrite it, otherwise, don't change it. + tocfile = sofile + ".TOC" + +- link_command = "$ld -shared -Wl,-soname=\"$soname\" {{ldflags}}${extra_ldflags} -o \"$unstripped_sofile\" @\"$rspfile\"" +- + # Generate a map file to be used for binary size analysis. + # Map file adds ~10% to the link time on a z620. + # With target_os="android", libchrome.so.map.gz is ~20MB. +@@ -446,13 +463,39 @@ template("gcc_toolchain") { + map_switch = " --map-file \"$map_file\"" + } + +- assert(defined(readelf), "to solink you must have a readelf") +- assert(defined(nm), "to solink you must have an nm") + strip_switch = "" + if (defined(invoker.strip)) { + strip_switch = "--strip=${invoker.strip} " + } + ++ mingw_flags = "" ++ soname_flags = "-Wl,-soname=\"$soname\"" ++ if(is_mingw){ ++ # Have MinGW linker generate a .def file and a .a import library ++ mingw_flags = "" ++ if(!is_clang){ ++ mingw_flags += " -Wl,--dll " ++ } ++ mingw_flags += " -Wl,--output-def=\"$sofile\".def -Wl,--out-implib=\"$sofile\".a " ++ readelf = "" ++ if (defined(invoker.readelf)) { ++ readelf = "${invoker.readelf} " ++ } ++ nm = "" ++ if (defined(invoker.nm)) { ++ readelf = "${invoker.nm} " ++ } ++ if(is_clang) { ++ # Clang on Windows does not support the -soname flag. ++ soname_flags = "" ++ } ++ } else { ++ assert(defined(readelf), "to solink you must have a readelf") ++ assert(defined(nm), "to solink you must have an nm") ++ } ++ ++ link_command = "$ld -shared ${soname_flags} ${mingw_flags} {{ldflags}}${extra_ldflags} -o \"$unstripped_sofile\" @\"$rspfile\"" ++ + # This needs a Python script to avoid using a complex shell command + # requiring sh control structures, pipelines, and POSIX utilities. + # The host might not have a POSIX shell and utilities (e.g. Windows). +diff --git a/toolchain/win/BUILD.gn b/toolchain/win/BUILD.gn +index c3def9ece..ef44fefb6 100644 +--- a/toolchain/win/BUILD.gn ++++ b/toolchain/win/BUILD.gn +@@ -10,6 +10,7 @@ import("//build/toolchain/cc_wrapper.gni") + import("//build/toolchain/goma.gni") + import("//build/toolchain/rbe.gni") + import("//build/toolchain/toolchain.gni") ++import("//build/toolchain/gcc_toolchain.gni") + + # Should only be running on Windows. + assert(is_win) +@@ -51,13 +52,15 @@ if (current_toolchain == default_toolchain) { + } else { + configuration_name = "Release" + } +- exec_script("../../vs_toolchain.py", +- [ +- "copy_dlls", +- rebase_path(root_build_dir), +- configuration_name, +- target_cpu, +- ]) ++ if(!is_mingw){ ++ exec_script("../../vs_toolchain.py", ++ [ ++ "copy_dlls", ++ rebase_path(root_build_dir), ++ configuration_name, ++ target_cpu, ++ ]) ++ } + } + + if (host_os == "win") { +@@ -537,3 +540,26 @@ if (target_os == "winuwp") { + } + } + } ++ ++template("mingw_toolchain") { ++ gcc_toolchain("mingw_" + target_name) { ++ forward_variables_from(invoker, "*") ++ cc = getenv("CC") ++ cxx = getenv("CXX") ++ ar = getenv("AR") ++ ld = cxx ++ rc = "windres" ++ strip = "strip" ++ executable_extension = ".exe" ++ toolchain_args = { ++ current_cpu = target_name ++ current_os = "win" ++ } ++ } ++} ++ ++mingw_toolchain("x64") { ++} ++ ++mingw_toolchain("x86") { ++} +diff --git a/util/lastchange.py b/util/lastchange.py +index 02a36642b..78934f1b0 100644 +--- a/util/lastchange.py ++++ b/util/lastchange.py +@@ -192,7 +192,10 @@ def GetGitTopDirectory(source_dir): + Returns: + The output of "git rev-parse --show-toplevel" as a string + """ +- return _RunGitCommand(source_dir, ['rev-parse', '--show-toplevel']) ++ directory = _RunGitCommand(source_dir, ['rev-parse', '--show-toplevel']) ++ if "GCC" in sys.version and sys.platform=='win32': ++ return subprocess.check_output(["cygpath", "-w", directory]).strip(b"\n").decode() ++ return directory + + + def WriteIfChanged(file_name, contents): +diff --git a/win/BUILD.gn b/win/BUILD.gn +index d449f5925..558e04229 100644 +--- a/win/BUILD.gn ++++ b/win/BUILD.gn +@@ -16,7 +16,7 @@ windows_manifest("default_exe_manifest") { + ] + } + +-if (is_win) { ++if (is_win && !is_mingw) { + assert(host_os != "mac" || target_cpu != "x86", + "Windows cross-builds from Mac must be 64-bit.") + +@@ -92,7 +92,7 @@ if (is_win) { + + group("runtime_libs") { + data = [] +- if (is_component_build) { ++ if (is_component_build && !is_mingw) { + # Copy the VS runtime DLLs into the isolate so that they don't have to be + # preinstalled on the target machine. The debug runtimes have a "d" at + # the end. diff --git a/patches/mingw/0009-remove-as-needed-from-ldflags.patch b/patches/mingw/0009-remove-as-needed-from-ldflags.patch new file mode 100644 index 0000000..8667fdc --- /dev/null +++ b/patches/mingw/0009-remove-as-needed-from-ldflags.patch @@ -0,0 +1,27 @@ +From e9b2e5e2c4e09a896e2ef9b6dc3d28d721fa21f5 Mon Sep 17 00:00:00 2001 +From: Naveen M K +Date: Tue, 30 Nov 2021 15:30:24 +0530 +Subject: [PATCH] remove as-needed from ldflags + +Signed-off-by: Naveen M K +--- + build/gen.py | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/build/gen.py b/build/gen.py +index 922bf46f..edcc0353 100644 +--- a/build/gen.py ++++ b/build/gen.py +@@ -375,7 +375,8 @@ def WriteGNNinja(path, platform, host, options): + ]) + + if platform.is_linux() or platform.is_mingw() or platform.is_msys(): +- ldflags.append('-Wl,--as-needed') ++ if not platform.is_mingw(): ++ ldflags.append('-Wl,--as-needed') + + if not options.no_static_libstdcpp: + ldflags.append('-static-libstdc++') +-- +2.34.1.windows.1 + diff --git a/patches/mingw/0010-git-call-must-not-use-shell-in-mingw.patch b/patches/mingw/0010-git-call-must-not-use-shell-in-mingw.patch new file mode 100644 index 0000000..36b4991 --- /dev/null +++ b/patches/mingw/0010-git-call-must-not-use-shell-in-mingw.patch @@ -0,0 +1,25 @@ +From baf0524386df8926d1244e0b870da5483280a56a Mon Sep 17 00:00:00 2001 +From: Vinicius Rangel +Date: Tue, 16 Aug 2022 01:54:04 -0300 +Subject: [PATCH] git call must not use shell in mingw + +--- + build/gen.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/build/gen.py b/build/gen.py +index 922bf46f..d7716271 100644 +--- a/build/gen.py ++++ b/build/gen.py +@@ -153,7 +153,7 @@ def main(argv): + def GenerateLastCommitPosition(host, header): + ROOT_TAG = 'initial-commit' + describe_output = subprocess.check_output( +- ['git', 'describe', 'HEAD', '--match', ROOT_TAG], shell=host.is_windows(), ++ ['git', 'describe', 'HEAD', '--match', ROOT_TAG], shell=host.is_windows() and not host.is_mingw(), + cwd=REPO_ROOT) + mo = re.match(ROOT_TAG + '-(\d+)-g([0-9a-f]+)', describe_output.decode()) + if not mo: +-- +2.37.1.windows.1 + diff --git a/script/build.py b/script/build.py index 7e2612a..5d5fdc3 100755 --- a/script/build.py +++ b/script/build.py @@ -1,9 +1,10 @@ #! /usr/bin/env python3 import common, os, subprocess, sys +from checkout import chdir_home def main(): - os.chdir(os.path.join(os.path.dirname(__file__), os.pardir, 'skia')) + chdir_home() build_type = common.build_type() machine = common.machine() @@ -11,9 +12,11 @@ def main(): host_machine = common.host_machine() target = common.target() ndk = common.ndk() + is_win = common.windows() + is_mingw = "mingw" == host tools_dir = "depot_tools" - ninja = 'ninja.exe' if 'windows' == host else 'ninja' + ninja = 'ninja.exe' if is_win else 'ninja' isIos = 'ios' == target or 'iosSim' == target isIosSim = 'iosSim' == target @@ -73,12 +76,19 @@ def main(): 'cc="gcc-9"', 'cxx="g++-9"', ] - elif 'windows' == target: - args += [ - # 'skia_use_angle=true', - 'skia_use_direct3d=true', - 'extra_cflags=["-DSK_FONT_HOST_USE_SYSTEM_SETTINGS"]', - ] + elif is_win: + if is_mingw: + args += [ + 'extra_cflags_cc=["-fno-exceptions", "-fno-rtti","-D_GLIBCXX_USE_CXX11_ABI=0", "-fpermissive"]', + 'cc="gcc"', + 'cxx="g++"', + ] + else: + args += [ + # 'skia_use_angle=true', + 'skia_use_direct3d=true', + 'extra_cflags=["-DSK_FONT_HOST_USE_SYSTEM_SETTINGS"]' + ] elif 'android' == target: args += [ 'ndk="'+ ndk + '"' @@ -123,11 +133,29 @@ def main(): tools_dir = 'tools' ninja = 'ninja-linux-arm64' + ninja_path = os.path.join('..', tools_dir, ninja) + + env = os.environ.copy() + + if is_mingw: + os.chdir("gn") + subprocess.check_call(["python", "build/gen.py", "--out-path=out/" + machine, "--platform=mingw"], env=env) + subprocess.check_call([ninja_path, "-C", "out/" + machine], env=env) + os.chdir("..") + + os.chdir('skia') + out = os.path.join('out', build_type + '-' + target + '-' + machine) - gn = 'gn.exe' if 'windows' == host else 'gn' - print([os.path.join('bin', gn), 'gen', out, '--args=' + ' '.join(args)]) - subprocess.check_call([os.path.join('bin', gn), 'gen', out, '--args=' + ' '.join(args)]) - subprocess.check_call([os.path.join('..', tools_dir, ninja), '-C', out, 'skia', 'modules']) + + gn = 'gn.exe' if is_win else 'gn' + if is_mingw: + gn_path = os.path.join('..', 'gn', 'out', machine, gn) + else: + gn_path = os.path.join('bin', gn) + + print([gn_path, 'gen', out, '--args=' + ' '.join(args)]) + subprocess.check_call([gn_path, 'gen', out, '--args=' + ' '.join(args)], env=env) + subprocess.check_call([ninja_path, '-C', out, 'skia', 'modules'], env=env) return 0 diff --git a/script/checkout.py b/script/checkout.py index 8e783c3..4499e7f 100755 --- a/script/checkout.py +++ b/script/checkout.py @@ -2,9 +2,39 @@ import argparse, common, os, pathlib, platform, re, subprocess, sys -def main(): +def checkout_and_chdir(url, path, branch, commit): + print("> Adding", path) + if os.path.exists(path): + os.chdir(path) + if subprocess.check_output(["git", "branch", "--list", branch]): + print("> Advancing", branch) + subprocess.check_call(["git", "checkout", "-B", branch]) + subprocess.check_call(["git", "fetch"]) + subprocess.check_call(["git", "reset", "--hard", "origin/" + branch]) + else: + print("> Fetching", branch) + subprocess.check_call(["git", "reset", "--hard"]) + subprocess.check_call(["git", "fetch", "origin", branch + ":remotes/origin/" + branch]) + subprocess.check_call(["git", "checkout", branch]) + else: + print("> Cloning", branch) + subprocess.check_call(["git", "clone", "--config", "core.autocrlf=input", url, "--quiet", "--single-branch", "--branch", branch, path]) + os.chdir(path) + + # Checkout commit + print("> Checking out", commit) + subprocess.check_call(["git", "-c", "advice.detachedHead=false", "checkout", commit]) + +def git_apply(file): + print("> Applying", file) + subprocess.check_call(["git", "apply", file]) + +def chdir_home(): os.chdir(os.path.join(os.path.dirname(__file__), os.pardir)) +def main(): + chdir_home() + parser = common.create_parser(True) args = parser.parse_args() @@ -18,24 +48,9 @@ def main(): raise Exception('Expected --version "m-", got "' + args.version + '"') branch = "chrome/" + match.group(1) commit = match.group(2) - iteration = match.group(3) + # iteration = match.group(3) - if os.path.exists("skia"): - os.chdir("skia") - if subprocess.check_output(["git", "branch", "--list", branch]): - print("> Advancing", branch) - subprocess.check_call(["git", "checkout", "-B", branch]) - subprocess.check_call(["git", "fetch"]) - subprocess.check_call(["git", "reset", "--hard", "origin/" + branch]) - else: - print("> Fetching", branch) - subprocess.check_call(["git", "reset", "--hard"]) - subprocess.check_call(["git", "fetch", "origin", branch + ":remotes/origin/" + branch]) - subprocess.check_call(["git", "checkout", branch]) - else: - print("> Cloning", branch) - subprocess.check_call(["git", "clone", "--config", "core.autocrlf=input", "https://skia.googlesource.com/skia", "--quiet", "--branch", branch, "skia"]) - os.chdir("skia") + checkout_and_chdir("https://skia.googlesource.com/skia", "skia", branch, commit) # Checkout commit print("> Checking out", commit) @@ -44,12 +59,17 @@ def main(): # Apply patches subprocess.check_call(["git", "reset", "--hard"]) for x in pathlib.Path(os.pardir, 'patches').glob('*.patch'): - print("> Applying", x) - subprocess.check_call(["git", "apply", str(x)]) + git_apply(str(x)) + + host = common.host() + + if 'mingw' == host: + file = os.pardir + "/patches/mingw/0003-Don-t-download-prebuild-gn-and-emsdk.patch" + git_apply(file) # git deps print("> Running tools/git-sync-deps") - if 'windows' == common.host(): + if common.windows(): env = os.environ.copy() env['PYTHONHTTPSVERIFY']='0' subprocess.check_call(["python", "tools/git-sync-deps"], env=env) diff --git a/script/checkout_gn_mingw.py b/script/checkout_gn_mingw.py new file mode 100644 index 0000000..74d5622 --- /dev/null +++ b/script/checkout_gn_mingw.py @@ -0,0 +1,41 @@ +#! /usr/bin/env python3 + +import argparse, common, os, pathlib, platform, re, subprocess, sys +from checkout import checkout_and_chdir, git_apply, chdir_home + + +def main(): + chdir_home() + + print("> Downloading gn source") + checkout_and_chdir("https://gn.googlesource.com/gn", "gn", "main", "d62642c920e6a0d1756316d225a90fd6faa9e21e") + + # Apply patches + patches = [ + "0002-gn-ninja-deletes-objs-workaround.patch", + "0006-add-missing-limits.patch", + "0009-remove-as-needed-from-ldflags.patch", + "0010-git-call-must-not-use-shell-in-mingw.patch", + ] + for x in patches: + git_apply(os.pardir + "/patches/mingw/" + x) + + print("> Downloading chromium build source") + chdir_home() + checkout_and_chdir("https://chromium.googlesource.com/chromium/src/build.git", "build", "main", "fd86d60f33cbc794537c4da2ef7e298d7f81138e") + git_apply(os.pardir + "/patches/mingw/0007-add-mingw-toolchain-build.patch") + + print("> Linking gn to skia build") + chdir_home() + subprocess.check_call(["rm", "-rf", "skia/build"]) + subprocess.check_call(["ln", "-sf", os.path.abspath('build'), 'skia']) + pathlib.Path("skia/build/config/gclient_args.gni").write_text("checkout_google_benchmark = false") + + print("> Patching skia") + os.chdir("skia") + git_apply(os.pardir + "/patches/mingw/0001-fixes-to-compile.patch") + + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/script/common.py b/script/common.py index 738f3c6..787b7f5 100644 --- a/script/common.py +++ b/script/common.py @@ -69,3 +69,6 @@ def ndk(): (args, _) = parser.parse_known_args() return args.ndk if args.ndk else '' +def windows(): + h = host() + return 'windows' == h or 'mingw' == h