From 490fd4955747c9d3715954359d72937960f02a22 Mon Sep 17 00:00:00 2001 From: Dan Willemsen Date: Tue, 24 Nov 2015 17:53:15 -0800 Subject: Support cross-compiling Windows binaries on Linux This defines another mutator between HostOrDevice and Arch that will expand host modules into a module for each host type (Darwin/Linux/Windows) that is currently being built. Change-Id: I4c8ac6b616c229f6bd45ad8a35902652fb6a4fff --- Android.bp | 1 + cc/arm64_device.go | 2 +- cc/arm_device.go | 2 +- cc/builder.go | 9 ++- cc/cc.go | 115 +++++++++++++++++++++++----------- cc/mips64_device.go | 2 +- cc/mips_device.go | 2 +- cc/toolchain.go | 36 +++++++++-- cc/x86_64_device.go | 2 +- cc/x86_darwin_host.go | 13 ++-- cc/x86_device.go | 2 +- cc/x86_linux_host.go | 9 ++- cc/x86_windows_host.go | 150 ++++++++++++++++++++++++++++++++++++++++++++ common/arch.go | 167 +++++++++++++++++++++++++++++++++++++++++-------- common/module.go | 36 +++++++++-- common/variable.go | 10 +++ genrule/genrule.go | 6 +- 17 files changed, 469 insertions(+), 95 deletions(-) create mode 100644 cc/x86_windows_host.go diff --git a/Android.bp b/Android.bp index 4d1d7015..9a7beb82 100644 --- a/Android.bp +++ b/Android.bp @@ -130,6 +130,7 @@ bootstrap_go_package { "cc/x86_darwin_host.go", "cc/x86_linux_host.go", + "cc/x86_windows_host.go", ], testSrcs: [ "cc/cc_test.go", diff --git a/cc/arm64_device.go b/cc/arm64_device.go index 4acb218d..9d58a809 100644 --- a/cc/arm64_device.go +++ b/cc/arm64_device.go @@ -155,5 +155,5 @@ func arm64ToolchainFactory(arch common.Arch) Toolchain { } func init() { - registerToolchainFactory(common.Device, common.Arm64, arm64ToolchainFactory) + registerDeviceToolchainFactory(common.Arm64, arm64ToolchainFactory) } diff --git a/cc/arm_device.go b/cc/arm_device.go index 746de2e3..2d6d38c5 100644 --- a/cc/arm_device.go +++ b/cc/arm_device.go @@ -362,5 +362,5 @@ func armToolchainFactory(arch common.Arch) Toolchain { } func init() { - registerToolchainFactory(common.Device, common.Arm, armToolchainFactory) + registerDeviceToolchainFactory(common.Arm, armToolchainFactory) } diff --git a/cc/builder.go b/cc/builder.go index e3b9983b..64437d28 100644 --- a/cc/builder.go +++ b/cc/builder.go @@ -33,7 +33,6 @@ import ( const ( objectExtension = ".o" - sharedLibraryExtension = ".so" staticLibraryExtension = ".a" ) @@ -310,7 +309,7 @@ func TransformObjToDynamicBinary(ctx common.AndroidModuleContext, var libFlagsList []string if len(wholeStaticLibs) > 0 { - if ctx.Host() && runtime.GOOS == "darwin" { + if ctx.Host() && ctx.Darwin() { libFlagsList = append(libFlagsList, common.JoinWithPrefix(wholeStaticLibs, "-force_load ")) } else { libFlagsList = append(libFlagsList, "-Wl,--whole-archive ") @@ -334,11 +333,11 @@ func TransformObjToDynamicBinary(ctx common.AndroidModuleContext, if !strings.HasPrefix(file, "lib") { panic("shared library " + lib + " does not start with lib") } - if !strings.HasSuffix(file, sharedLibraryExtension) { - panic("shared library " + lib + " does not end with " + sharedLibraryExtension) + if !strings.HasSuffix(file, flags.toolchain.ShlibSuffix()) { + panic("shared library " + lib + " does not end with " + flags.toolchain.ShlibSuffix()) } libFlagsList = append(libFlagsList, - "-l"+strings.TrimSuffix(strings.TrimPrefix(file, "lib"), sharedLibraryExtension)) + "-l"+strings.TrimSuffix(strings.TrimPrefix(file, "lib"), flags.toolchain.ShlibSuffix())) ldDirs = append(ldDirs, dir) } diff --git a/cc/cc.go b/cc/cc.go index b1bc069b..00a09089 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -21,7 +21,6 @@ package cc import ( "fmt" "path/filepath" - "runtime" "strings" "github.com/google/blueprint" @@ -82,7 +81,6 @@ var ( "-Wno-unused", "-Winit-self", "-Wpointer-arith", - "-fdiagnostics-color", "-fdebug-prefix-map=/proc/self/cwd=", // COMMON_RELEASE_CFLAGS @@ -91,6 +89,8 @@ var ( } deviceGlobalCflags = []string{ + "-fdiagnostics-color", + // TARGET_ERROR_FLAGS "-Werror=return-type", "-Werror=non-virtual-dtor", @@ -407,9 +407,10 @@ func (c *CCBase) ccModuleType() CCModuleType { func (c *CCBase) findToolchain(ctx common.AndroidModuleContext) Toolchain { arch := ctx.Arch() hod := ctx.HostOrDevice() - factory := toolchainFactories[hod][arch.ArchType] + ht := ctx.HostType() + factory := toolchainFactories[hod][ht][arch.ArchType] if factory == nil { - ctx.ModuleErrorf("Toolchain not found for %s arch %q", hod.String(), arch.String()) + ctx.ModuleErrorf("Toolchain not found for %s %s arch %q", hod.String(), ht.String(), arch.String()) return nil } return factory(arch) @@ -512,6 +513,10 @@ func (c *CCBase) collectFlags(ctx common.AndroidModuleContext, toolchain Toolcha } } + if !toolchain.ClangSupported() { + flags.Clang = false + } + instructionSet := c.Properties.Instruction_set instructionSetFlags, err := toolchain.InstructionSetFlags(instructionSet) if flags.Clang { @@ -826,33 +831,52 @@ func (c *CCLinked) stl(ctx common.AndroidBaseContext) string { } } - switch c.Properties.Stl { - case "libc++", "libc++_static", - "libstdc++": - return c.Properties.Stl - case "none": - return "" - case "": - if c.static() { - return "libc++_static" - } else { - return "libc++" // TODO: mingw needs libstdc++ + if ctx.HostType() == common.Windows { + switch c.Properties.Stl { + case "libc++", "libc++_static", "libstdc++", "": + // libc++ is not supported on mingw + return "libstdc++" + case "none": + return "" + default: + ctx.ModuleErrorf("stl: %q is not a supported STL", c.Properties.Stl) + return "" + } + } else { + switch c.Properties.Stl { + case "libc++", "libc++_static", + "libstdc++": + return c.Properties.Stl + case "none": + return "" + case "": + if c.static() { + return "libc++_static" + } else { + return "libc++" + } + default: + ctx.ModuleErrorf("stl: %q is not a supported STL", c.Properties.Stl) + return "" } - default: - ctx.ModuleErrorf("stl: %q is not a supported STL", c.Properties.Stl) - return "" } } -var hostDynamicGccLibs, hostStaticGccLibs []string +var hostDynamicGccLibs, hostStaticGccLibs map[common.HostType][]string func init() { - if runtime.GOOS == "darwin" { - hostDynamicGccLibs = []string{"-lc", "-lSystem"} - hostStaticGccLibs = []string{"NO_STATIC_HOST_BINARIES_ON_DARWIN"} - } else { - hostDynamicGccLibs = []string{"-lgcc_s", "-lgcc", "-lc", "-lgcc_s", "-lgcc"} - hostStaticGccLibs = []string{"-Wl,--start-group", "-lgcc", "-lgcc_eh", "-lc", "-Wl,--end-group"} + hostDynamicGccLibs = map[common.HostType][]string{ + common.Linux: []string{"-lgcc_s", "-lgcc", "-lc", "-lgcc_s", "-lgcc"}, + common.Darwin: []string{"-lc", "-lSystem"}, + common.Windows: []string{"-lmsvcr110", "-lmingw32", "-lgcc", "-lmoldname", + "-lmingwex", "-lmsvcrt", "-ladvapi32", "-lshell32", "-luser32", + "-lkernel32", "-lmingw32", "-lgcc", "-lmoldname", "-lmingwex", + "-lmsvcrt"}, + } + hostStaticGccLibs = map[common.HostType][]string{ + common.Linux: []string{"-Wl,--start-group", "-lgcc", "-lgcc_eh", "-lc", "-Wl,--end-group"}, + common.Darwin: []string{"NO_STATIC_HOST_BINARIES_ON_DARWIN"}, + common.Windows: []string{"NO_STATIC_HOST_BINARIES_ON_WINDOWS"}, } } @@ -870,9 +894,9 @@ func (c *CCLinked) flags(ctx common.AndroidModuleContext, flags CCFlags) CCFlags flags.LdFlags = append(flags.LdFlags, "-nodefaultlibs") flags.LdFlags = append(flags.LdFlags, "-lm", "-lpthread") if c.staticBinary() { - flags.LdFlags = append(flags.LdFlags, hostStaticGccLibs...) + flags.LdFlags = append(flags.LdFlags, hostStaticGccLibs[ctx.HostType()]...) } else { - flags.LdFlags = append(flags.LdFlags, hostDynamicGccLibs...) + flags.LdFlags = append(flags.LdFlags, hostDynamicGccLibs[ctx.HostType()]...) } } else { if ctx.Arch().ArchType == common.Arm { @@ -900,9 +924,9 @@ func (c *CCLinked) flags(ctx common.AndroidModuleContext, flags CCFlags) CCFlags flags.CppFlags = append(flags.CppFlags, "-nostdinc++") flags.LdFlags = append(flags.LdFlags, "-nodefaultlibs") if c.staticBinary() { - flags.LdFlags = append(flags.LdFlags, hostStaticGccLibs...) + flags.LdFlags = append(flags.LdFlags, hostStaticGccLibs[ctx.HostType()]...) } else { - flags.LdFlags = append(flags.LdFlags, hostDynamicGccLibs...) + flags.LdFlags = append(flags.LdFlags, hostDynamicGccLibs[ctx.HostType()]...) } } default: @@ -1148,7 +1172,12 @@ func (c *CCLibrary) exportedFlags() []string { func (c *CCLibrary) flags(ctx common.AndroidModuleContext, flags CCFlags) CCFlags { flags = c.CCLinked.flags(ctx, flags) - flags.CFlags = append(flags.CFlags, "-fPIC") + // MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because + // all code is position independent, and then those warnings get promoted to + // errors. + if ctx.HostType() != common.Windows { + flags.CFlags = append(flags.CFlags, "-fPIC") + } if c.static() { flags.CFlags = append(flags.CFlags, c.LibraryProperties.Static.Cflags...) @@ -1172,13 +1201,13 @@ func (c *CCLibrary) flags(ctx common.AndroidModuleContext, flags CCFlags) CCFlag "-dynamiclib", "-single_module", //"-read_only_relocs suppress", - "-install_name @rpath/"+libName+sharedLibraryExtension, + "-install_name @rpath/"+libName+flags.Toolchain.ShlibSuffix(), ) } else { flags.LdFlags = append(flags.LdFlags, "-Wl,--gc-sections", sharedFlag, - "-Wl,-soname,"+libName+sharedLibraryExtension, + "-Wl,-soname,"+libName+flags.Toolchain.ShlibSuffix(), ) } } @@ -1224,7 +1253,7 @@ func (c *CCLibrary) compileSharedLibrary(ctx common.AndroidModuleContext, objFiles = append(objFiles, objFilesShared...) - outputFile := filepath.Join(common.ModuleOutDir(ctx), ctx.ModuleName()+sharedLibraryExtension) + outputFile := filepath.Join(common.ModuleOutDir(ctx), ctx.ModuleName()+flags.Toolchain.ShlibSuffix()) var linkerDeps []string @@ -1448,7 +1477,19 @@ func (c *CCBinary) ModifyProperties(ctx CCModuleContext) { func (c *CCBinary) flags(ctx common.AndroidModuleContext, flags CCFlags) CCFlags { flags = c.CCLinked.flags(ctx, flags) - flags.CFlags = append(flags.CFlags, "-fpie") + if ctx.Host() { + flags.LdFlags = append(flags.LdFlags, "-pie") + if ctx.HostType() == common.Windows { + flags.LdFlags = append(flags.LdFlags, "-Wl,-e_mainCRTStartup") + } + } + + // MinGW spits out warnings about -fPIC even for -fpie?!) being ignored because + // all code is position independent, and then those warnings get promoted to + // errors. + if ctx.HostType() != common.Windows { + flags.CFlags = append(flags.CFlags, "-fpie") + } if ctx.Device() { if Bool(c.BinaryProperties.Static_executable) { @@ -1495,7 +1536,7 @@ func (c *CCBinary) compileModule(ctx common.AndroidModuleContext, "from static libs or set static_executable: true") } - outputFile := filepath.Join(common.ModuleOutDir(ctx), c.getStem(ctx)) + outputFile := filepath.Join(common.ModuleOutDir(ctx), c.getStem(ctx)+flags.Toolchain.ExecutableSuffix()) c.out = outputFile if c.BinaryProperties.Prefix_symbols != "" { afterPrefixSymbols := outputFile @@ -1843,7 +1884,7 @@ func (c *ndkPrebuiltLibrary) compileModule(ctx common.AndroidModuleContext, flag includeDirs := pathtools.PrefixPaths(c.Properties.Export_include_dirs, common.ModuleSrcDir(ctx)) c.exportFlags = []string{common.JoinWithPrefix(includeDirs, "-isystem ")} - c.out = ndkPrebuiltModuleToPath(ctx, flags.Toolchain, sharedLibraryExtension, + c.out = ndkPrebuiltModuleToPath(ctx, flags.Toolchain, flags.Toolchain.ShlibSuffix(), c.Properties.Sdk_version) } @@ -1911,7 +1952,7 @@ func (c *ndkPrebuiltStl) compileModule(ctx common.AndroidModuleContext, flags CC c.exportFlags = []string{includeDirsToFlags(includeDirs)} libName := strings.TrimPrefix(ctx.ModuleName(), "ndk_") - libExt := sharedLibraryExtension + libExt := flags.Toolchain.ShlibSuffix() if c.LibraryProperties.BuildStatic { libExt = staticLibraryExtension } diff --git a/cc/mips64_device.go b/cc/mips64_device.go index d792d005..e0b6a89f 100644 --- a/cc/mips64_device.go +++ b/cc/mips64_device.go @@ -195,5 +195,5 @@ func mips64ToolchainFactory(arch common.Arch) Toolchain { } func init() { - registerToolchainFactory(common.Device, common.Mips64, mips64ToolchainFactory) + registerDeviceToolchainFactory(common.Mips64, mips64ToolchainFactory) } diff --git a/cc/mips_device.go b/cc/mips_device.go index 52bc1ecf..c3372fe6 100644 --- a/cc/mips_device.go +++ b/cc/mips_device.go @@ -227,5 +227,5 @@ func mipsToolchainFactory(arch common.Arch) Toolchain { } func init() { - registerToolchainFactory(common.Device, common.Mips, mipsToolchainFactory) + registerDeviceToolchainFactory(common.Mips, mipsToolchainFactory) } diff --git a/cc/toolchain.go b/cc/toolchain.go index 71a89794..5e4d02ff 100644 --- a/cc/toolchain.go +++ b/cc/toolchain.go @@ -22,15 +22,23 @@ import ( type toolchainFactory func(arch common.Arch) Toolchain -var toolchainFactories = map[common.HostOrDevice]map[common.ArchType]toolchainFactory{ - common.Host: make(map[common.ArchType]toolchainFactory), - common.Device: make(map[common.ArchType]toolchainFactory), +var toolchainFactories = map[common.HostOrDevice]map[common.HostType]map[common.ArchType]toolchainFactory{ + common.Host: map[common.HostType]map[common.ArchType]toolchainFactory{ + common.Linux: make(map[common.ArchType]toolchainFactory), + common.Darwin: make(map[common.ArchType]toolchainFactory), + common.Windows: make(map[common.ArchType]toolchainFactory), + }, + common.Device: map[common.HostType]map[common.ArchType]toolchainFactory{ + common.NoHostType: make(map[common.ArchType]toolchainFactory), + }, } -func registerToolchainFactory(hod common.HostOrDevice, arch common.ArchType, - factory toolchainFactory) { +func registerDeviceToolchainFactory(arch common.ArchType, factory toolchainFactory) { + toolchainFactories[common.Device][common.NoHostType][arch] = factory +} - toolchainFactories[hod][arch] = factory +func registerHostToolchainFactory(ht common.HostType, arch common.ArchType, factory toolchainFactory) { + toolchainFactories[common.Host][ht][arch] = factory } type Toolchain interface { @@ -47,6 +55,7 @@ type Toolchain interface { IncludeFlags() string InstructionSetFlags(string) (string, error) + ClangSupported() bool ClangTriple() string ToolchainClangCflags() string ClangCflags() string @@ -55,6 +64,9 @@ type Toolchain interface { ClangInstructionSetFlags(string) (string, error) Is64Bit() bool + + ShlibSuffix() string + ExecutableSuffix() string } type toolchainBase struct { @@ -86,6 +98,18 @@ func (toolchainBase) ToolchainClangCflags() string { return "" } +func (toolchainBase) ClangSupported() bool { + return true +} + +func (toolchainBase) ShlibSuffix() string { + return ".so" +} + +func (toolchainBase) ExecutableSuffix() string { + return "" +} + type toolchain64Bit struct { toolchainBase } diff --git a/cc/x86_64_device.go b/cc/x86_64_device.go index bd68ca50..728442cc 100644 --- a/cc/x86_64_device.go +++ b/cc/x86_64_device.go @@ -256,5 +256,5 @@ func x86_64ToolchainFactory(arch common.Arch) Toolchain { } func init() { - registerToolchainFactory(common.Device, common.X86_64, x86_64ToolchainFactory) + registerDeviceToolchainFactory(common.X86_64, x86_64ToolchainFactory) } diff --git a/cc/x86_darwin_host.go b/cc/x86_darwin_host.go index 4195dae3..9ca03bac 100644 --- a/cc/x86_darwin_host.go +++ b/cc/x86_darwin_host.go @@ -1,7 +1,6 @@ package cc import ( - "runtime" "strings" "android/soong/common" @@ -12,6 +11,8 @@ var ( "-fno-exceptions", // from build/core/combo/select.mk "-Wno-multichar", // from build/core/combo/select.mk + "-fdiagnostics-color", + "-fPIC", "-funwind-tables", @@ -195,6 +196,10 @@ func (t *toolchainDarwinX8664) ClangLdflags() string { return "${darwinClangLdflags} ${darwinX8664ClangLdflags}" } +func (t *toolchainDarwin) ShlibSuffix() string { + return ".dylib" +} + var toolchainDarwinX86Singleton Toolchain = &toolchainDarwinX86{} var toolchainDarwinX8664Singleton Toolchain = &toolchainDarwinX8664{} @@ -207,8 +212,6 @@ func darwinX8664ToolchainFactory(arch common.Arch) Toolchain { } func init() { - if runtime.GOOS == "darwin" { - registerToolchainFactory(common.Host, common.X86, darwinX86ToolchainFactory) - registerToolchainFactory(common.Host, common.X86_64, darwinX8664ToolchainFactory) - } + registerHostToolchainFactory(common.Darwin, common.X86, darwinX86ToolchainFactory) + registerHostToolchainFactory(common.Darwin, common.X86_64, darwinX8664ToolchainFactory) } diff --git a/cc/x86_device.go b/cc/x86_device.go index df0c0ffa..8543240c 100644 --- a/cc/x86_device.go +++ b/cc/x86_device.go @@ -258,5 +258,5 @@ func x86ToolchainFactory(arch common.Arch) Toolchain { } func init() { - registerToolchainFactory(common.Device, common.X86, x86ToolchainFactory) + registerDeviceToolchainFactory(common.X86, x86ToolchainFactory) } diff --git a/cc/x86_linux_host.go b/cc/x86_linux_host.go index f5444760..09a08033 100644 --- a/cc/x86_linux_host.go +++ b/cc/x86_linux_host.go @@ -1,7 +1,6 @@ package cc import ( - "runtime" "strings" "android/soong/common" @@ -12,6 +11,8 @@ var ( "-fno-exceptions", // from build/core/combo/select.mk "-Wno-multichar", // from build/core/combo/select.mk + "-fdiagnostics-color", + "-Wa,--noexecstack", "-fPIC", @@ -233,8 +234,6 @@ func linuxX8664ToolchainFactory(arch common.Arch) Toolchain { } func init() { - if runtime.GOOS == "linux" { - registerToolchainFactory(common.Host, common.X86, linuxX86ToolchainFactory) - registerToolchainFactory(common.Host, common.X86_64, linuxX8664ToolchainFactory) - } + registerHostToolchainFactory(common.Linux, common.X86, linuxX86ToolchainFactory) + registerHostToolchainFactory(common.Linux, common.X86_64, linuxX8664ToolchainFactory) } diff --git a/cc/x86_windows_host.go b/cc/x86_windows_host.go new file mode 100644 index 00000000..70ce74d5 --- /dev/null +++ b/cc/x86_windows_host.go @@ -0,0 +1,150 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cc + +import ( + "strings" + + "android/soong/common" +) + +var ( + windowsCflags = []string{ + "-fno-exceptions", // from build/core/combo/select.mk + "-Wno-multichar", // from build/core/combo/select.mk + + "-DUSE_MINGW", + "-DWIN32_LEAN_AND_MEAN", + "-Wno-unused-parameter", + "-m32", + + // Workaround differences in inttypes.h between host and target. + //See bug 12708004. + "-D__STDC_FORMAT_MACROS", + "-D__STDC_CONSTANT_MACROS", + + // Use C99-compliant printf functions (%zd). + "-D__USE_MINGW_ANSI_STDIO=1", + // Admit to using >= Win2K. Both are needed because of <_mingw.h>. + "-D_WIN32_WINNT=0x0500", + "-DWINVER=0x0500", + // Get 64-bit off_t and related functions. + "-D_FILE_OFFSET_BITS=64", + + // HOST_RELEASE_CFLAGS + "-O2", // from build/core/combo/select.mk + "-g", // from build/core/combo/select.mk + "-fno-strict-aliasing", // from build/core/combo/select.mk + } + + windowsIncludeFlags = []string{ + "-I${windowsGccRoot}/${windowsGccTriple}/include", + "-I${windowsGccRoot}/lib/gcc/${windowsGccTriple}/4.8.3/include", + } + + windowsLdflags = []string{ + "-m32", + "-L${windowsGccRoot}/${windowsGccTriple}", + "--enable-stdcall-fixup", + } +) + +func init() { + pctx.StaticVariable("windowsGccVersion", "4.8") + + pctx.StaticVariable("windowsGccRoot", + "${SrcDir}/prebuilts/gcc/${HostPrebuiltTag}/host/x86_64-w64-mingw32-${windowsGccVersion}") + + pctx.StaticVariable("windowsGccTriple", "x86_64-w64-mingw32") + + pctx.StaticVariable("windowsCflags", strings.Join(windowsCflags, " ")) + pctx.StaticVariable("windowsLdflags", strings.Join(windowsLdflags, " ")) +} + +type toolchainWindows struct { + toolchain32Bit + + cFlags, ldFlags string +} + +func (t *toolchainWindows) Name() string { + return "x86" +} + +func (t *toolchainWindows) GccRoot() string { + return "${windowsGccRoot}" +} + +func (t *toolchainWindows) GccTriple() string { + return "${windowsGccTriple}" +} + +func (t *toolchainWindows) GccVersion() string { + return "${windowsGccVersion}" +} + +func (t *toolchainWindows) Cflags() string { + return "${windowsCflags}" +} + +func (t *toolchainWindows) Cppflags() string { + return "" +} + +func (t *toolchainWindows) Ldflags() string { + return "${windowsLdflags}" +} + +func (t *toolchainWindows) IncludeFlags() string { + return "" +} + +func (t *toolchainWindows) ClangSupported() bool { + return false +} + +func (t *toolchainWindows) ClangTriple() string { + panic("Clang is not supported under mingw") +} + +func (t *toolchainWindows) ClangCflags() string { + panic("Clang is not supported under mingw") +} + +func (t *toolchainWindows) ClangCppflags() string { + panic("Clang is not supported under mingw") +} + +func (t *toolchainWindows) ClangLdflags() string { + panic("Clang is not supported under mingw") +} + +func (t *toolchainWindows) ShlibSuffix() string { + return ".dll" +} + +func (t *toolchainWindows) ExecutableSuffix() string { + return ".exe" +} + +var toolchainWindowsSingleton Toolchain = &toolchainWindows{} + +func windowsToolchainFactory(arch common.Arch) Toolchain { + return toolchainWindowsSingleton +} + +func init() { + registerHostToolchainFactory(common.Windows, common.X86, windowsToolchainFactory) +} diff --git a/common/arch.go b/common/arch.go index 8ac52e66..4cddc00e 100644 --- a/common/arch.go +++ b/common/arch.go @@ -29,6 +29,7 @@ func init() { RegisterTopDownMutator("defaults", defaultsMutator) RegisterBottomUpMutator("host_or_device", HostOrDeviceMutator) + RegisterBottomUpMutator("host_type", HostTypeMutator) RegisterBottomUpMutator("arch", ArchMutator) } @@ -261,6 +262,8 @@ type archProperties struct { Darwin_x86_64 interface{} `blueprint:"filter(android:\"arch_variant\")"` // Properties for module variants being built to run on windows hosts Windows interface{} `blueprint:"filter(android:\"arch_variant\")"` + // Properties for module variants being built to run on windows x86 hosts + Windows_x86 interface{} `blueprint:"filter(android:\"arch_variant\")"` // Properties for module variants being built to run on linux or darwin hosts Not_windows interface{} `blueprint:"filter(android:\"arch_variant\")"` } @@ -383,6 +386,52 @@ var hostOrDeviceName = map[HostOrDevice]string{ Host: "host", } +type HostType int + +const ( + NoHostType HostType = iota + Linux + Darwin + Windows +) + +func CurrentHostType() HostType { + switch runtime.GOOS { + case "linux": + return Linux + case "darwin": + return Darwin + default: + panic(fmt.Sprintf("unsupported OS: %s", runtime.GOOS)) + } +} + +func (ht HostType) String() string { + switch ht { + case Linux: + return "linux" + case Darwin: + return "darwin" + case Windows: + return "windows" + default: + panic(fmt.Sprintf("unexpected HostType value %d", ht)) + } +} + +func (ht HostType) Field() string { + switch ht { + case Linux: + return "Linux" + case Darwin: + return "Darwin" + case Windows: + return "Windows" + default: + panic(fmt.Sprintf("unexpected HostType value %d", ht)) + } +} + var ( commonArch = Arch{ ArchType: Common, @@ -421,6 +470,34 @@ func HostOrDeviceMutator(mctx AndroidBottomUpMutatorContext) { } } +func HostTypeMutator(mctx AndroidBottomUpMutatorContext) { + var module AndroidModule + var ok bool + if module, ok = mctx.Module().(AndroidModule); !ok { + return + } + + if !module.base().HostSupported() || !module.base().HostOrDevice().Host() { + return + } + + buildTypes, err := decodeHostTypesProductVariables(mctx.Config().(Config).ProductVariables) + if err != nil { + mctx.ModuleErrorf("%s", err.Error()) + return + } + + typeNames := []string{} + for _, ht := range buildTypes { + typeNames = append(typeNames, ht.String()) + } + + modules := mctx.CreateVariations(typeNames...) + for i, m := range modules { + m.(AndroidModule).base().SetHostType(buildTypes[i]) + } +} + func ArchMutator(mctx AndroidBottomUpMutatorContext) { var module AndroidModule var ok bool @@ -437,7 +514,7 @@ func ArchMutator(mctx AndroidBottomUpMutatorContext) { multilib := module.base().commonProperties.Compile_multilib if module.base().HostSupported() && module.base().HostOrDevice().Host() { - hostModuleArches, err := decodeMultilib(multilib, hostArches) + hostModuleArches, err := decodeMultilib(multilib, hostArches[module.base().HostType()]) if err != nil { mctx.ModuleErrorf("%s", err.Error()) } @@ -560,6 +637,7 @@ func (a *AndroidModuleBase) appendProperties(ctx AndroidBottomUpMutatorContext, func (a *AndroidModuleBase) setArchProperties(ctx AndroidBottomUpMutatorContext) { arch := a.commonProperties.CompileArch hod := a.commonProperties.CompileHostOrDevice + ht := a.commonProperties.CompileHostType if arch.ArchType == Common { return @@ -654,30 +732,21 @@ func (a *AndroidModuleBase) setArchProperties(ctx AndroidBottomUpMutatorContext) // key: value, // }, // }, - var osList = []struct { - goos string - field string - }{ - {"darwin", "Darwin"}, - {"linux", "Linux"}, - {"windows", "Windows"}, - } - if hod.Host() { - for _, v := range osList { - if v.goos == runtime.GOOS { - field := v.field - prefix := "target." + v.goos - a.appendProperties(ctx, genProps, archProps.Target, field, prefix) - t := arch.ArchType - field = v.field + "_" + t.Name - prefix = "target." + v.goos + "_" + t.Name - a.appendProperties(ctx, genProps, archProps.Target, field, prefix) - } - } - field := "Not_windows" - prefix := "target.not_windows" + field := ht.Field() + prefix := "target." + ht.String() + a.appendProperties(ctx, genProps, archProps.Target, field, prefix) + + t := arch.ArchType + field = ht.Field() + "_" + t.Name + prefix = "target." + ht.String() + "_" + t.Name a.appendProperties(ctx, genProps, archProps.Target, field, prefix) + + if ht != Windows { + field := "Not_windows" + prefix := "target.not_windows" + a.appendProperties(ctx, genProps, archProps.Target, field, prefix) + } } // Handle 64-bit device properties in the form: @@ -742,8 +811,24 @@ func forEachInterface(v reflect.Value, f func(reflect.Value)) { } } +// Get a list of HostTypes from the product variables +func decodeHostTypesProductVariables(variables productVariables) ([]HostType, error) { + ret := []HostType{CurrentHostType()} + + if variables.CrossHost != nil && *variables.CrossHost != "" { + switch *variables.CrossHost { + case "windows": + ret = append(ret, Windows) + default: + return nil, fmt.Errorf("Unsupported secondary host: %s", *variables.CrossHost) + } + } + + return ret, nil +} + // Convert the arch product variables into a list of host and device Arch structs -func decodeArchProductVariables(variables productVariables) ([]Arch, []Arch, error) { +func decodeArchProductVariables(variables productVariables) (map[HostType][]Arch, []Arch, error) { if variables.HostArch == nil { return nil, nil, fmt.Errorf("No host primary architecture set") } @@ -763,6 +848,38 @@ func decodeArchProductVariables(variables productVariables) ([]Arch, []Arch, err hostArches = append(hostArches, hostSecondaryArch) } + hostTypeArches := map[HostType][]Arch{ + CurrentHostType(): hostArches, + } + + if variables.CrossHost != nil && *variables.CrossHost != "" { + if variables.CrossHostArch == nil || *variables.CrossHostArch == "" { + return nil, nil, fmt.Errorf("No cross-host primary architecture set") + } + + crossHostArch, err := decodeArch(*variables.CrossHostArch, nil, nil, nil) + if err != nil { + return nil, nil, err + } + + crossHostArches := []Arch{crossHostArch} + + if variables.CrossHostSecondaryArch != nil && *variables.CrossHostSecondaryArch != "" { + crossHostSecondaryArch, err := decodeArch(*variables.CrossHostSecondaryArch, nil, nil, nil) + if err != nil { + return nil, nil, err + } + crossHostArches = append(crossHostArches, crossHostSecondaryArch) + } + + switch *variables.CrossHost { + case "windows": + hostTypeArches[Windows] = crossHostArches + default: + return nil, nil, fmt.Errorf("Unsupported cross-host: %s", *variables.CrossHost) + } + } + if variables.DeviceArch == nil { return nil, nil, fmt.Errorf("No device primary architecture set") } @@ -785,7 +902,7 @@ func decodeArchProductVariables(variables productVariables) ([]Arch, []Arch, err deviceArches = append(deviceArches, deviceSecondaryArch) } - return hostArches, deviceArches, nil + return hostTypeArches, deviceArches, nil } // Convert a set of strings from product variables into a single Arch struct diff --git a/common/module.go b/common/module.go index b64342f6..7bb21a25 100644 --- a/common/module.go +++ b/common/module.go @@ -17,7 +17,6 @@ package common import ( "android/soong" "path/filepath" - "runtime" "android/soong/glob" @@ -37,6 +36,7 @@ var ( type androidBaseContext interface { Arch() Arch HostOrDevice() HostOrDevice + HostType() HostType Host() bool Device() bool Darwin() bool @@ -88,6 +88,9 @@ type commonProperties struct { // Set by HostOrDeviceMutator CompileHostOrDevice HostOrDevice `blueprint:"mutated"` + // Set by HostTypeMutator + CompileHostType HostType `blueprint:"mutated"` + // Set by ArchMutator CompileArch Arch `blueprint:"mutated"` @@ -208,6 +211,10 @@ func (a *AndroidModuleBase) SetHostOrDevice(hod HostOrDevice) { a.commonProperties.CompileHostOrDevice = hod } +func (a *AndroidModuleBase) SetHostType(ht HostType) { + a.commonProperties.CompileHostType = ht +} + func (a *AndroidModuleBase) SetArch(arch Arch) { a.commonProperties.CompileArch = arch } @@ -216,6 +223,10 @@ func (a *AndroidModuleBase) HostOrDevice() HostOrDevice { return a.commonProperties.CompileHostOrDevice } +func (a *AndroidModuleBase) HostType() HostType { + return a.commonProperties.CompileHostType +} + func (a *AndroidModuleBase) HostSupported() bool { return a.commonProperties.HostOrDeviceSupported == HostSupported || a.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported && @@ -229,6 +240,12 @@ func (a *AndroidModuleBase) DeviceSupported() bool { } func (a *AndroidModuleBase) Disabled() bool { + if a.commonProperties.CompileHostOrDevice == Host && + a.commonProperties.CompileHostType == Windows && + a.commonProperties.Disabled == nil { + + return true + } return proptools.Bool(a.commonProperties.Disabled) } @@ -308,6 +325,7 @@ func (a *AndroidModuleBase) androidBaseContextFactory(ctx blueprint.BaseModuleCo return androidBaseContextImpl{ arch: a.commonProperties.CompileArch, hod: a.commonProperties.CompileHostOrDevice, + ht: a.commonProperties.CompileHostType, config: ctx.Config().(Config), } } @@ -320,7 +338,7 @@ func (a *AndroidModuleBase) GenerateBuildActions(ctx blueprint.ModuleContext) { installFiles: a.installFiles, } - if proptools.Bool(a.commonProperties.Disabled) { + if a.Disabled() { return } @@ -341,6 +359,7 @@ func (a *AndroidModuleBase) GenerateBuildActions(ctx blueprint.ModuleContext) { type androidBaseContextImpl struct { arch Arch hod HostOrDevice + ht HostType debug bool config Config } @@ -366,6 +385,10 @@ func (a *androidBaseContextImpl) HostOrDevice() HostOrDevice { return a.hod } +func (a *androidBaseContextImpl) HostType() HostType { + return a.ht +} + func (a *androidBaseContextImpl) Host() bool { return a.hod.Host() } @@ -375,7 +398,7 @@ func (a *androidBaseContextImpl) Device() bool { } func (a *androidBaseContextImpl) Darwin() bool { - return a.hod.Host() && runtime.GOOS == "darwin" + return a.hod.Host() && a.ht == Darwin } func (a *androidBaseContextImpl) Debug() bool { @@ -396,7 +419,12 @@ func (a *androidModuleContext) InstallFileName(installPath, name, srcPath string fullInstallPath = filepath.Join(config.DeviceOut(), "system", installPath, name) } else { - fullInstallPath = filepath.Join(config.HostOut(), installPath, name) + // TODO + if a.ht == Windows { + fullInstallPath = filepath.Join(config.BuildDir(), "host", "windows-x86", installPath, name) + } else { + fullInstallPath = filepath.Join(config.HostOut(), installPath, name) + } } deps = append(deps, a.installDeps...) diff --git a/common/variable.go b/common/variable.go index 9a5998f7..5b9092f3 100644 --- a/common/variable.go +++ b/common/variable.go @@ -17,6 +17,7 @@ package common import ( "fmt" "reflect" + "runtime" "strings" "github.com/google/blueprint/proptools" @@ -69,6 +70,10 @@ type productVariables struct { HostArch *string `json:",omitempty"` HostSecondaryArch *string `json:",omitempty"` + + CrossHost *string `json:",omitempty"` + CrossHostArch *string `json:",omitempty"` + CrossHostSecondaryArch *string `json:",omitempty"` } func boolPtr(v bool) *bool { @@ -99,6 +104,11 @@ func (v *productVariables) SetDefaultConfig() { DeviceSecondaryCpuVariant: stringPtr("denver"), DeviceSecondaryAbi: &[]string{"armeabi-v7a"}, } + + if runtime.GOOS == "linux" { + v.CrossHost = stringPtr("windows") + v.CrossHostArch = stringPtr("x86") + } } func variableMutator(mctx AndroidBottomUpMutatorContext) { diff --git a/genrule/genrule.go b/genrule/genrule.go index fb0dafcf..76b4f16a 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -88,8 +88,10 @@ func (g *generator) GeneratedSourceFiles() []string { func genruleDepsMutator(ctx common.AndroidBottomUpMutatorContext) { if g, ok := ctx.Module().(*generator); ok { if g.properties.Tool != "" { - ctx.AddFarVariationDependencies([]blueprint.Variation{{"hostordevice", common.Host.String()}}, - g.properties.Tool) + ctx.AddFarVariationDependencies([]blueprint.Variation{ + {"host_or_device", common.Host.String()}, + {"host_type", common.CurrentHostType().String()}, + }, g.properties.Tool) } } } -- cgit v1.2.3