further qmake related changes + more refactoring

This commit is contained in:
therecipe 2017-03-10 22:54:09 +01:00
parent 8fc476c30c
commit b07306acc2
43 changed files with 1502 additions and 896 deletions

95
cmd/qtdeploy/main.go Executable file
View file

@ -0,0 +1,95 @@
package main
import (
"flag"
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/therecipe/qt/internal/cmd"
"github.com/therecipe/qt/internal/cmd/deploy"
"github.com/therecipe/qt/internal/utils"
)
func qmake_main() {
flag.Usage = func() {
println("Usage: qtdeploy [-docker] [mode] [target] [path/to/project]\n")
println("Flags:\n")
flag.PrintDefaults()
print("\n")
println("Modes:\n")
modes := []struct{ name, desc string }{
{"build", "compile and bundle"},
{"run", "run the binary"},
{"test", "build and run"},
{"help", "print help"},
}
for _, mode := range modes {
fmt.Printf(" %v%v%v\n", mode.name, strings.Repeat(" ", 12-len(mode.name)), mode.desc)
}
print("\n")
os.Exit(0)
}
var docker bool
flag.BoolVar(&docker, "docker", false, "run command inside docker container")
var ldFlags string
flag.StringVar(&ldFlags, "ldflags", "", "arguments to pass on each go tool link invocation.")
if cmd.ParseFlags() {
flag.Usage()
}
mode := "test"
target := "desktop"
path, err := os.Getwd()
if err != nil {
utils.Log.WithError(err).Debug("failed to get cwd")
}
switch flag.NArg() {
case 0:
case 1:
mode = flag.Arg(0)
case 2:
mode = flag.Arg(0)
target = flag.Arg(1)
case 3:
mode = flag.Arg(0)
target = flag.Arg(1)
path = flag.Arg(2)
default:
flag.Usage()
}
if mode == "help" {
flag.Usage()
}
if target == runtime.GOOS {
target = "desktop"
}
if !filepath.IsAbs(path) {
path, err = filepath.Abs(path)
if err != nil {
utils.Log.WithError(err).WithField("path", path).Fatal("can't resolve absolute path")
}
}
utils.CheckBuildTarget(target)
deploy.Deploy(&deploy.State{
BuildMode: mode,
BuildTarget: target,
AppPath: path,
BuildDocker: docker,
LdFlags: ldFlags,
})
}

View file

@ -9,11 +9,10 @@ import (
"github.com/therecipe/qt/internal/cmd" "github.com/therecipe/qt/internal/cmd"
"github.com/therecipe/qt/internal/cmd/deploy" "github.com/therecipe/qt/internal/cmd/deploy"
"github.com/therecipe/qt/internal/utils" "github.com/therecipe/qt/internal/utils"
) )
//qtdeploy [ mode ] [ target ] [ path/to/project ] [ docker ]
var ( var (
appPath string appPath string
buildMode, buildTarget string buildMode, buildTarget string
@ -21,9 +20,17 @@ var (
) )
func main() { func main() {
if utils.QT_QMAKE_CGO() == true {
qmake_main()
return
}
var ldFlags = flag.String("ldflags", "", "arguments to pass on each go tool link invocation.") var ldFlags = flag.String("ldflags", "", "arguments to pass on each go tool link invocation.")
cmd.ParseFlags() if cmd.ParseFlags() {
flag.PrintDefaults()
return
}
args() args()
@ -77,7 +84,7 @@ func args() {
} }
} }
if utils.IsCI() { if utils.CI() {
buildMode = "build" buildMode = "build"
} }

67
cmd/qtminimal/main.go Executable file
View file

@ -0,0 +1,67 @@
package main
import (
"flag"
"os"
"path/filepath"
"runtime"
"github.com/therecipe/qt/internal/cmd"
"github.com/therecipe/qt/internal/cmd/minimal"
"github.com/therecipe/qt/internal/utils"
)
func qmake_main() {
flag.Usage = func() {
println("Usage: qtminimal [-docker] [target] [path/to/project]\n")
println("Flags:\n")
flag.PrintDefaults()
print("\n")
os.Exit(0)
}
var docker bool
flag.BoolVar(&docker, "docker", false, "run command inside docker container")
if cmd.ParseFlags() {
flag.Usage()
}
target := "desktop"
path, err := os.Getwd()
if err != nil {
utils.Log.WithError(err).Debug("failed to get cwd")
}
switch flag.NArg() {
case 0:
case 1:
target = flag.Arg(0)
case 2:
target = flag.Arg(0)
path = flag.Arg(1)
default:
flag.Usage()
}
if target == runtime.GOOS {
target = "desktop"
}
if !filepath.IsAbs(path) {
path, err = filepath.Abs(path)
if err != nil {
utils.Log.WithError(err).WithField("path", path).Fatal("can't resolve absolute path")
}
}
utils.CheckBuildTarget(target)
if docker {
cmd.Docker([]string{"qtminimal", "-debug"}, target, path)
} else {
minimal.QmakeMinimal(path, target)
}
}

View file

@ -9,13 +9,19 @@ import (
"github.com/therecipe/qt/internal/cmd" "github.com/therecipe/qt/internal/cmd"
"github.com/therecipe/qt/internal/cmd/minimal" "github.com/therecipe/qt/internal/cmd/minimal"
"github.com/therecipe/qt/internal/utils" "github.com/therecipe/qt/internal/utils"
) )
//qtminimal [ target ] [ path/to/project ] [ docker ]
func main() { func main() {
cmd.ParseFlags() if utils.QT_QMAKE_CGO() == true {
qmake_main()
return
}
if cmd.ParseFlags() {
flag.PrintDefaults()
return
}
var ( var (
buildTarget = "desktop" buildTarget = "desktop"
@ -43,7 +49,7 @@ func main() {
} }
} }
if !filepath.IsAbs(appPath) { if !filepath.IsAbs(appPath) {
appPath, _ = utils.Abs(appPath) appPath, _ = filepath.Abs(appPath)
} }
if _, err := ioutil.ReadDir(appPath); err != nil || strings.ContainsAny(buildTarget, "./\\") { if _, err := ioutil.ReadDir(appPath); err != nil || strings.ContainsAny(buildTarget, "./\\") {
utils.Log.Fatalln("usage:", "qtminimal", "[ desktop | android | ... ]", filepath.Join("path", "to", "project")) utils.Log.Fatalln("usage:", "qtminimal", "[ desktop | android | ... ]", filepath.Join("path", "to", "project"))

67
cmd/qtmoc/main.go Executable file
View file

@ -0,0 +1,67 @@
package main
import (
"flag"
"os"
"path/filepath"
"runtime"
"github.com/therecipe/qt/internal/cmd"
"github.com/therecipe/qt/internal/cmd/moc"
"github.com/therecipe/qt/internal/utils"
)
func qmake_main() {
flag.Usage = func() {
println("Usage: qtmoc [-docker] [target] [path/to/project]\n")
println("Flags:\n")
flag.PrintDefaults()
print("\n")
os.Exit(0)
}
var docker bool
flag.BoolVar(&docker, "docker", false, "run command inside docker container")
if cmd.ParseFlags() {
flag.Usage()
}
target := "desktop"
path, err := os.Getwd()
if err != nil {
utils.Log.WithError(err).Debug("failed to get cwd")
}
switch flag.NArg() {
case 0:
case 1:
target = flag.Arg(0)
case 2:
target = flag.Arg(0)
path = flag.Arg(1)
default:
flag.Usage()
}
if target == runtime.GOOS {
target = "desktop"
}
if !filepath.IsAbs(path) {
path, err = filepath.Abs(path)
if err != nil {
utils.Log.WithError(err).WithField("path", path).Fatal("can't resolve absolute path")
}
}
utils.CheckBuildTarget(target)
if docker {
cmd.Docker([]string{"qtmoc", "-debug"}, target, path)
} else {
moc.QmakeMoc(path, target)
}
}

View file

@ -10,15 +10,19 @@ import (
"github.com/therecipe/qt/internal/cmd" "github.com/therecipe/qt/internal/cmd"
"github.com/therecipe/qt/internal/cmd/moc" "github.com/therecipe/qt/internal/cmd/moc"
"github.com/therecipe/qt/internal/utils" "github.com/therecipe/qt/internal/utils"
) )
//qtmoc [ path/to/project ] [ docker ]
//qtmoc [ target ] [ path/to/project ] [ docker ]
func main() { func main() {
cmd.ParseFlags() if utils.QT_QMAKE_CGO() == true {
qmake_main()
return
}
if cmd.ParseFlags() {
flag.PrintDefaults()
return
}
var ( var (
appPath string appPath string
@ -47,7 +51,7 @@ func main() {
// validate that path is readable and a directory // validate that path is readable and a directory
if !filepath.IsAbs(appPath) { if !filepath.IsAbs(appPath) {
appPath, _ = utils.Abs(appPath) appPath, _ = filepath.Abs(appPath)
} }
fields["app_path"] = appPath fields["app_path"] = appPath

76
cmd/qtrcc/main.go Executable file
View file

@ -0,0 +1,76 @@
package main
import (
"flag"
"os"
"path/filepath"
"runtime"
"github.com/therecipe/qt/internal/cmd"
"github.com/therecipe/qt/internal/cmd/rcc"
"github.com/therecipe/qt/internal/utils"
)
func qmake_main() {
flag.Usage = func() {
println("Usage: qtrcc [-docker] [target] [path/to/project]\n")
println("Flags:\n")
flag.PrintDefaults()
print("\n")
os.Exit(0)
}
var docker bool
flag.BoolVar(&docker, "docker", false, "run command inside docker container")
var output string
flag.StringVar(&output, "o", os.Getenv("QTRCC_OUTPUT_DIR"), "specify an alternative output dir")
if cmd.ParseFlags() {
flag.Usage()
}
target := "desktop"
path, err := os.Getwd()
if err != nil {
utils.Log.WithError(err).Debug("failed to get cwd")
}
switch flag.NArg() {
case 0:
case 1:
target = flag.Arg(0)
case 2:
target = flag.Arg(0)
path = flag.Arg(1)
default:
flag.Usage()
}
if target == runtime.GOOS {
target = "desktop"
}
if !filepath.IsAbs(path) {
path, err = filepath.Abs(path)
if err != nil {
utils.Log.WithError(err).WithField("path", path).Fatal("can't resolve absolute path")
}
}
if !filepath.IsAbs(output) {
output, err = filepath.Abs(output)
if err != nil {
utils.Log.WithError(err).WithField("output", output).Fatal("can't resolve absolute path")
}
}
utils.CheckBuildTarget(target)
if docker {
cmd.Docker([]string{"qtrcc", "-debug"}, target, path)
} else {
rcc.QmakeRcc(path, target, &output)
}
}

View file

@ -8,32 +8,37 @@ import (
"github.com/therecipe/qt/internal/cmd" "github.com/therecipe/qt/internal/cmd"
"github.com/therecipe/qt/internal/cmd/rcc" "github.com/therecipe/qt/internal/cmd/rcc"
"github.com/therecipe/qt/internal/utils" "github.com/therecipe/qt/internal/utils"
) )
//qtrcc [ path/to/project ] [ docker ]
//qtrcc [ target ] [ path/to/project ] [ docker ]
func main() { func main() {
if utils.QT_QMAKE_CGO() == true {
qmake_main()
return
}
var appPath, _ = os.Getwd() var appPath, _ = os.Getwd()
if env_cwd := os.Getenv("QTRCC_CWD"); env_cwd != "" { if env_cwd := os.Getenv("QTRCC_CWD"); env_cwd != "" {
appPath = env_cwd appPath = env_cwd
} }
var output_dir = flag.String("o", "", "define alternative output dir") var output_dir = flag.String("o", "", "define alternative output dir")
cmd.ParseFlags() if cmd.ParseFlags() {
flag.PrintDefaults()
return
}
if *output_dir != "" { if *output_dir != "" {
if !filepath.IsAbs(*output_dir) { if !filepath.IsAbs(*output_dir) {
var tmp_output_dir, _ = utils.Abs(*output_dir) var tmp_output_dir, _ = filepath.Abs(*output_dir)
output_dir = &tmp_output_dir output_dir = &tmp_output_dir
} }
} else { } else {
env_output_dir := os.Getenv("QTRCC_OUTPUT_DIR") env_output_dir := os.Getenv("QTRCC_OUTPUT_DIR")
if env_output_dir != "" { if env_output_dir != "" {
if !filepath.IsAbs(env_output_dir) { if !filepath.IsAbs(env_output_dir) {
var tmp_output_dir, _ = utils.Abs(env_output_dir) var tmp_output_dir, _ = filepath.Abs(env_output_dir)
output_dir = &tmp_output_dir output_dir = &tmp_output_dir
} else { } else {
output_dir = &env_output_dir output_dir = &env_output_dir
@ -56,7 +61,7 @@ func main() {
} }
} }
if !filepath.IsAbs(appPath) { if !filepath.IsAbs(appPath) {
appPath, _ = utils.Abs(appPath) appPath, _ = filepath.Abs(appPath)
} }
if _, err := ioutil.ReadDir(appPath); err != nil { if _, err := ioutil.ReadDir(appPath); err != nil {
utils.Log.Fatalln("usage:", "qtrcc", filepath.Join("path", "to", "project"), "[ docker ]") utils.Log.Fatalln("usage:", "qtrcc", filepath.Join("path", "to", "project"), "[ docker ]")

92
cmd/qtsetup/main.go Executable file
View file

@ -0,0 +1,92 @@
package main
import (
"flag"
"fmt"
"os"
"runtime"
"strings"
"github.com/therecipe/qt/internal/cmd"
"github.com/therecipe/qt/internal/cmd/setup"
"github.com/therecipe/qt/internal/utils"
)
func qmake_main() {
flag.Usage = func() {
println("Usage: qtsetup [-debug] [mode] [target]\n")
println("Flags:\n")
flag.PrintDefaults()
print("\n")
println("Modes:\n")
modes := []struct{ name, desc string }{
{"prep", "try to symlink tooling into the PATH"},
{"check", "do some basic env checks"},
{"generate", "generate the code for all packages"},
{"install", "run go install for all packages"},
{"test", "build some examples"},
{"full", "run all of the above"},
{"help", "print help"},
{"update", "update 'cmd' and 'internal/cmd'"},
{"upgrade", "update everything"},
}
for _, mode := range modes {
fmt.Printf(" %v%v%v\n", mode.name, strings.Repeat(" ", 12-len(mode.name)), mode.desc)
}
print("\n")
os.Exit(0)
}
if cmd.ParseFlags() {
flag.Usage()
}
mode := "full"
target := "desktop"
switch flag.NArg() {
case 0:
case 1:
mode = flag.Arg(0)
case 2:
mode = flag.Arg(0)
target = flag.Arg(1)
default:
flag.Usage()
}
if target == runtime.GOOS {
target = "desktop"
}
utils.CheckBuildTarget(target)
switch mode {
case "full":
setup.Prep()
setup.Check(target)
setup.Generate(target)
setup.Install(target)
setup.Test(target)
case "prep":
setup.Prep()
case "check":
setup.Check(target)
case "generate":
setup.Generate(target)
case "install":
setup.Install(target)
case "test":
setup.Test(target)
case "update":
setup.Update()
case "upgrade":
setup.Upgrade()
default:
flag.Usage()
}
}

View file

@ -5,11 +5,19 @@ import (
"github.com/therecipe/qt/internal/cmd" "github.com/therecipe/qt/internal/cmd"
"github.com/therecipe/qt/internal/cmd/setup" "github.com/therecipe/qt/internal/cmd/setup"
"github.com/therecipe/qt/internal/utils" "github.com/therecipe/qt/internal/utils"
) )
func main() { func main() {
cmd.ParseFlags() if utils.QT_QMAKE_CGO() == true {
qmake_main()
return
}
if cmd.ParseFlags() {
flag.PrintDefaults()
return
}
var buildMode, buildTarget = "full", "desktop" var buildMode, buildTarget = "full", "desktop"

View file

@ -240,7 +240,7 @@ func IsPrivateSignal(f *parser.Function) bool {
switch runtime.GOOS { switch runtime.GOOS {
case "darwin": case "darwin":
{ {
if utils.UseHomeBrew() { if utils.QT_HOMEBREW() {
fData = utils.LoadOptional(filepath.Join(utils.QT_DARWIN_DIR(), "lib", fmt.Sprintf("%v.framework", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule)), "Versions", "5", "Headers", fPath)) fData = utils.LoadOptional(filepath.Join(utils.QT_DARWIN_DIR(), "lib", fmt.Sprintf("%v.framework", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule)), "Versions", "5", "Headers", fPath))
} else { } else {
fData = utils.Load(filepath.Join(utils.QT_DARWIN_DIR(), "lib", fmt.Sprintf("%v.framework", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule)), "Versions", "5", "Headers", fPath)) fData = utils.Load(filepath.Join(utils.QT_DARWIN_DIR(), "lib", fmt.Sprintf("%v.framework", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule)), "Versions", "5", "Headers", fPath))
@ -249,7 +249,7 @@ func IsPrivateSignal(f *parser.Function) bool {
case "windows": case "windows":
{ {
if utils.UseMsys2() { if utils.QT_MSYS2() {
fData = utils.LoadOptional(filepath.Join(utils.QT_MSYS2_DIR(), "include", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule), fPath)) fData = utils.LoadOptional(filepath.Join(utils.QT_MSYS2_DIR(), "include", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule), fPath))
} else { } else {
fData = utils.Load(filepath.Join(utils.QT_DIR(), utils.QT_VERSION_MAJOR(), "mingw53_32", "include", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule), fPath)) fData = utils.Load(filepath.Join(utils.QT_DIR(), utils.QT_VERSION_MAJOR(), "mingw53_32", "include", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule), fPath))
@ -258,7 +258,7 @@ func IsPrivateSignal(f *parser.Function) bool {
case "linux": case "linux":
{ {
if utils.UsePkgConfig() { if utils.QT_PKG_CONFIG() {
fData = utils.LoadOptional(filepath.Join(strings.TrimSpace(utils.RunCmd(exec.Command("pkg-config", "--variable=includedir", "Qt5Core"), "convert.IsPrivateSignal_includeDir")), strings.Title(parser.State.ClassMap[f.ClassName()].DocModule), fPath)) fData = utils.LoadOptional(filepath.Join(strings.TrimSpace(utils.RunCmd(exec.Command("pkg-config", "--variable=includedir", "Qt5Core"), "convert.IsPrivateSignal_includeDir")), strings.Title(parser.State.ClassMap[f.ClassName()].DocModule), fPath))
} else { } else {
fData = utils.Load(filepath.Join(utils.QT_DIR(), utils.QT_VERSION_MAJOR(), "gcc_64", "include", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule), fPath)) fData = utils.Load(filepath.Join(utils.QT_DIR(), utils.QT_VERSION_MAJOR(), "gcc_64", "include", strings.Title(parser.State.ClassMap[f.ClassName()].DocModule), fPath))

View file

@ -164,7 +164,7 @@ func (c *Class) fixBases() {
switch runtime.GOOS { switch runtime.GOOS {
case "windows": case "windows":
{ {
if utils.UseMsys2() { if utils.QT_MSYS2() {
prefixPath = utils.QT_MSYS2_DIR() prefixPath = utils.QT_MSYS2_DIR()
} else { } else {
prefixPath = filepath.Join(utils.QT_DIR(), utils.QT_VERSION_MAJOR(), "mingw53_32") prefixPath = filepath.Join(utils.QT_DIR(), utils.QT_VERSION_MAJOR(), "mingw53_32")
@ -180,7 +180,7 @@ func (c *Class) fixBases() {
case "linux": case "linux":
{ {
if utils.UsePkgConfig() { if utils.QT_PKG_CONFIG() {
prefixPath = strings.TrimSpace(utils.RunCmd(exec.Command("pkg-config", "--variable=includedir", "Qt5Core"), "parser.class_includedir")) prefixPath = strings.TrimSpace(utils.RunCmd(exec.Command("pkg-config", "--variable=includedir", "Qt5Core"), "parser.class_includedir"))
} else { } else {
prefixPath = filepath.Join(utils.QT_DIR(), utils.QT_VERSION_MAJOR(), "gcc_64") prefixPath = filepath.Join(utils.QT_DIR(), utils.QT_VERSION_MAJOR(), "gcc_64")
@ -216,7 +216,7 @@ func (c *Class) fixBases() {
case "QUiLoader", "QEGLNativeContext", "QWGLNativeContext", "QGLXNativeContext", "QEglFSFunctions", "QWindowsWindowFunctions", "QCocoaNativeContext", "QXcbWindowFunctions", "QCocoaWindowFunctions": case "QUiLoader", "QEGLNativeContext", "QWGLNativeContext", "QGLXNativeContext", "QEglFSFunctions", "QWindowsWindowFunctions", "QCocoaNativeContext", "QXcbWindowFunctions", "QCocoaWindowFunctions":
{ {
if utils.UsePkgConfig() { if utils.QT_PKG_CONFIG() {
c.Bases = getBasesFromHeader(utils.LoadOptional(filepath.Join(prefixPath, c.Module, strings.ToLower(c.Name)+".h")), c.Name, c.Module) c.Bases = getBasesFromHeader(utils.LoadOptional(filepath.Join(prefixPath, c.Module, strings.ToLower(c.Name)+".h")), c.Name, c.Module)
} else { } else {
c.Bases = getBasesFromHeader(utils.Load(filepath.Join(prefixPath, "include", c.Module, strings.ToLower(c.Name)+".h")), c.Name, c.Module) c.Bases = getBasesFromHeader(utils.Load(filepath.Join(prefixPath, "include", c.Module, strings.ToLower(c.Name)+".h")), c.Name, c.Module)
@ -226,7 +226,7 @@ func (c *Class) fixBases() {
case "QPlatformSystemTrayIcon", "QPlatformGraphicsBuffer": case "QPlatformSystemTrayIcon", "QPlatformGraphicsBuffer":
{ {
if utils.UsePkgConfig() { if utils.QT_PKG_CONFIG() {
c.Bases = getBasesFromHeader(utils.LoadOptional(filepath.Join(prefixPath, c.Module, utils.QT_VERSION(), c.Module, "qpa", strings.ToLower(c.Name)+".h")), c.Name, c.Module) c.Bases = getBasesFromHeader(utils.LoadOptional(filepath.Join(prefixPath, c.Module, utils.QT_VERSION(), c.Module, "qpa", strings.ToLower(c.Name)+".h")), c.Name, c.Module)
} else { } else {
c.Bases = getBasesFromHeader(utils.Load(filepath.Join(prefixPath, infixPath, c.Module+suffixPath+utils.QT_VERSION(), "QtGui", "qpa", strings.ToLower(c.Name)+".h")), c.Name, c.Module) c.Bases = getBasesFromHeader(utils.Load(filepath.Join(prefixPath, infixPath, c.Module+suffixPath+utils.QT_VERSION(), "QtGui", "qpa", strings.ToLower(c.Name)+".h")), c.Name, c.Module)
@ -238,7 +238,7 @@ func (c *Class) fixBases() {
{ {
for _, m := range append(LibDeps[strings.TrimPrefix(c.Module, "Qt")], strings.TrimPrefix(c.Module, "Qt")) { for _, m := range append(LibDeps[strings.TrimPrefix(c.Module, "Qt")], strings.TrimPrefix(c.Module, "Qt")) {
m = fmt.Sprintf("Qt%v", m) m = fmt.Sprintf("Qt%v", m)
if utils.UsePkgConfig() { if utils.QT_PKG_CONFIG() {
if utils.ExistsFile(filepath.Join(prefixPath, m, strings.ToLower(c.Name)+".h")) { if utils.ExistsFile(filepath.Join(prefixPath, m, strings.ToLower(c.Name)+".h")) {
c.Bases = getBasesFromHeader(utils.LoadOptional(filepath.Join(prefixPath, m, strings.ToLower(c.Name)+".h")), c.Name, c.Module) c.Bases = getBasesFromHeader(utils.LoadOptional(filepath.Join(prefixPath, m, strings.ToLower(c.Name)+".h")), c.Name, c.Module)
return return
@ -264,7 +264,7 @@ func (c *Class) fixBases() {
var found bool var found bool
for _, m := range libs { for _, m := range libs {
m = fmt.Sprintf("Qt%v", m) m = fmt.Sprintf("Qt%v", m)
if utils.UsePkgConfig() { if utils.QT_PKG_CONFIG() {
if utils.ExistsFile(filepath.Join(prefixPath, m, c.Name)) { if utils.ExistsFile(filepath.Join(prefixPath, m, c.Name)) {
var f = utils.LoadOptional(filepath.Join(prefixPath, m, c.Name)) var f = utils.LoadOptional(filepath.Join(prefixPath, m, c.Name))

View file

@ -240,6 +240,70 @@ func ShouldBuild(module string) bool {
return true return true
} }
func ShouldBuildForTarget(module, target string) bool {
if !ShouldBuild(module) {
return false
}
switch target {
case "windows":
if runtime.GOOS == "windows" {
return true
}
switch module {
case "WebEngine", "Designer", "Speech", "WebView":
return false
}
if strings.HasSuffix(module, "Extras") && module != "WinExtras" {
return false
}
case "android":
switch module {
case "DBus", "WebEngine", "Designer", "PrintSupport": //TODO: PrintSupport
return false
}
if strings.HasSuffix(module, "Extras") && module != "AndroidExtras" {
return false
}
case "ios", "ios-simulator":
switch module {
case "DBus", "WebEngine", "SerialPort", "SerialBus", "Designer", "PrintSupport": //TODO: PrintSupport
return false
}
if strings.HasSuffix(module, "Extras") {
return false
}
case "sailfish", "sailfish-emulator", "asteroid":
if !IsWhiteListedSailfishLib(module) {
return false
}
case "rpi1", "rpi2", "rpi3":
switch module {
case "WebEngine", "Designer":
return false
}
if strings.HasSuffix(module, "Extras") {
return false
}
}
return true
}
func IsWhiteListedSailfishLib(name string) bool {
switch name {
case "Core", "Quick", "Qml", "Network", "Gui", "Concurrent", "Multimedia", "Sql", "Svg", "XmlPatterns", "Xml", "DBus", "WebKit", "Sensors", "Positioning":
{
return true
}
default:
{
return false
}
}
}
func GetLibs() []string { func GetLibs() []string {
for i := len(Libs) - 1; i >= 0; i-- { for i := len(Libs) - 1; i >= 0; i-- {
switch { switch {
@ -250,11 +314,6 @@ func GetLibs() []string {
{ {
Libs = append(Libs[:i], Libs[i+1:]...) Libs = append(Libs[:i], Libs[i+1:]...)
} }
case utils.QT_VERSION() != "5.8.0" && Libs[i] == "Speech":
{
Libs = append(Libs[:i], Libs[i+1:]...)
}
} }
} }
return Libs return Libs

View file

@ -40,12 +40,12 @@ func LoadModule(m string) error {
err error err error
) )
switch { switch {
case utils.UseHomeBrew(), utils.UseMsys2(): case utils.QT_HOMEBREW(), utils.QT_MSYS2():
{ {
err = xml.Unmarshal([]byte(utils.LoadOptional(filepath.Join(utils.MustGoPath(), "src", "github.com", "therecipe", "qt", "internal", "binding", "files", "docs", utils.QT_VERSION(), fmt.Sprintf("qt%v.index", strings.ToLower(m))))), &module) err = xml.Unmarshal([]byte(utils.LoadOptional(filepath.Join(utils.MustGoPath(), "src", "github.com", "therecipe", "qt", "internal", "binding", "files", "docs", utils.QT_VERSION(), fmt.Sprintf("qt%v.index", strings.ToLower(m))))), &module)
} }
case utils.UsePkgConfig(): case utils.QT_PKG_CONFIG():
{ {
err = xml.Unmarshal([]byte(utils.LoadOptional(filepath.Join(utils.QT_DOC_DIR(), fmt.Sprintf("qt%v", strings.ToLower(m)), fmt.Sprintf("qt%v.index", strings.ToLower(m))))), &module) err = xml.Unmarshal([]byte(utils.LoadOptional(filepath.Join(utils.QT_DOC_DIR(), fmt.Sprintf("qt%v", strings.ToLower(m)), fmt.Sprintf("qt%v.index", strings.ToLower(m))))), &module)
} }

View file

@ -22,7 +22,7 @@ func CgoTemplate(module, mocPath, buildTarget string, mode int, pkg string) {
if !(strings.Contains(module, "droid") || strings.Contains(module, "fish")) { if !(strings.Contains(module, "droid") || strings.Contains(module, "fish")) {
cgoDarwin(module, mocPath, mode, pkg) cgoDarwin(module, mocPath, mode, pkg)
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
if utils.UseMsys2() { if utils.QT_MSYS2() {
cgoWindowsMsys2(module, mocPath, mode, pkg) //TODO: docker cgoWindowsMsys2(module, mocPath, mode, pkg) //TODO: docker
} else { } else {
cgoWindows(module, mocPath, mode, pkg) //TODO: docker cgoWindows(module, mocPath, mode, pkg) //TODO: docker
@ -30,7 +30,7 @@ func CgoTemplate(module, mocPath, buildTarget string, mode int, pkg string) {
} else { } else {
cgoWindowsForLinux(module, mocPath, mode, pkg) cgoWindowsForLinux(module, mocPath, mode, pkg)
} }
if utils.UsePkgConfig() { if utils.QT_PKG_CONFIG() {
cgoLinuxPkgConfig(module, mocPath, mode, pkg) //TODO: docker cgoLinuxPkgConfig(module, mocPath, mode, pkg) //TODO: docker
} else { } else {
cgoLinux(module, mocPath, mode, pkg) cgoLinux(module, mocPath, mode, pkg)
@ -804,7 +804,7 @@ func cgoSailfish(module, mocPath string, mode int, pkg string) {
fmt.Fprint(bb, "#cgo LDFLAGS: -rdynamic -L/srv/mer/targets/SailfishOS-i486/usr/lib -L/srv/mer/targets/SailfishOS-i486/lib -lsailfishapp -lmdeclarativecache5") fmt.Fprint(bb, "#cgo LDFLAGS: -rdynamic -L/srv/mer/targets/SailfishOS-i486/usr/lib -L/srv/mer/targets/SailfishOS-i486/lib -lsailfishapp -lmdeclarativecache5")
for _, m := range libs { for _, m := range libs {
if m != "UiPlugin" { if m != "UiPlugin" {
if IsWhiteListedSailfishLib(m) { if parser.IsWhiteListedSailfishLib(m) {
fmt.Fprintf(bb, " -lQt5%v", m) fmt.Fprintf(bb, " -lQt5%v", m)
} }
} }
@ -1128,20 +1128,6 @@ func GetiOSClang(buildTarget, buildARM string) []string {
return strings.Split(tmp, " ") return strings.Split(tmp, " ")
} }
func IsWhiteListedSailfishLib(name string) bool {
switch name {
case "Core", "Quick", "Qml", "Network", "Gui", "Concurrent", "Multimedia", "Sql", "Svg", "XmlPatterns", "Xml", "DBus", "WebKit", "Sensors", "Positioning":
{
return true
}
default:
{
return false
}
}
}
func cgoAsteroid(module, mocPath string, mode int, pkg string) { func cgoAsteroid(module, mocPath string, mode int, pkg string) {
var ( var (
bb = new(bytes.Buffer) bb = new(bytes.Buffer)
@ -1189,7 +1175,7 @@ func cgoAsteroid(module, mocPath string, mode int, pkg string) {
fmt.Fprintf(bb, "#cgo LDFLAGS: -rdynamic -L%[1]s/usr/lib -L%[1]s/lib -lmdeclarativecache5", os.Getenv("OECORE_TARGET_SYSROOT")) fmt.Fprintf(bb, "#cgo LDFLAGS: -rdynamic -L%[1]s/usr/lib -L%[1]s/lib -lmdeclarativecache5", os.Getenv("OECORE_TARGET_SYSROOT"))
for _, m := range libs { for _, m := range libs {
if m != "UiPlugin" { if m != "UiPlugin" {
if IsWhiteListedSailfishLib(m) { if parser.IsWhiteListedSailfishLib(m) {
fmt.Fprintf(bb, " -lQt5%v", m) fmt.Fprintf(bb, " -lQt5%v", m)
} }
} }

View file

@ -3,6 +3,7 @@ package templater
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"go/format"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
@ -21,6 +22,7 @@ const (
) )
func QmakeCgoTemplate(module, path, target string, mode int, ipkg string) (o string) { func QmakeCgoTemplate(module, path, target string, mode int, ipkg string) (o string) {
utils.Log.WithField("module", module).WithField("path", path).WithField("target", target).WithField("mode", mode).WithField("pkg", ipkg)
switch module { switch module {
case "AndroidExtras": case "AndroidExtras":
@ -37,43 +39,32 @@ func QmakeCgoTemplate(module, path, target string, mode int, ipkg string) (o str
path = utils.GoQtPkgPath(strings.ToLower(module)) path = utils.GoQtPkgPath(strings.ToLower(module))
} }
switch target { if target == "desktop" {
case "darwin", "linux":
if runtime.GOOS != target {
return
}
case "windows": //can be windows,linux,darwin
case "android":
switch module {
case "DBus", "WebEngine", "Designer":
return
}
if strings.HasSuffix(module, "Extras") && module != "AndroidExtras" {
return
}
case "ios", "ios-simulator":
switch module {
case "DBus", "WebEngine", "Designer", "SerialPort", "SerialBus":
return
}
if strings.HasSuffix(module, "Extras") {
return
}
case "sailfish", "sailfish-emulator", "asteroid":
if !IsWhiteListedSailfishLib(module) {
return
}
case "rpi1", "rpi2", "rpi3":
default:
target = runtime.GOOS target = runtime.GOOS
} }
if isAlreadyCached(module, path, target, mode) { if !parser.ShouldBuildForTarget(module, target) ||
isAlreadyCached(module, path, target, mode) {
utils.Log.Debugf("skipping cgo generation")
return return
} }
createProject(module, path, mode)
createMakefile(module, path, target, mode) switch target {
createCgo(module, path, target, mode, ipkg) case "rpi1":
cgoRaspberryPi1(module, path, mode, ipkg) //TODO:
case "rpi2":
cgoRaspberryPi2(module, path, mode, ipkg) //TODO:
case "rpi3":
cgoRaspberryPi3(module, path, mode, ipkg) //TODO:
case "sailfish", "sailfish-emulator":
cgoSailfish(module, path, mode, ipkg) //TODO:
case "asteroid":
cgoAsteroid(module, path, mode, ipkg) //TODO:
default:
createProject(module, path, mode)
createMakefile(module, path, target, mode)
createCgo(module, path, target, mode, ipkg)
}
utils.RemoveAll(filepath.Join(path, "Makefile")) utils.RemoveAll(filepath.Join(path, "Makefile"))
utils.RemoveAll(filepath.Join(path, "Makefile.Release")) utils.RemoveAll(filepath.Join(path, "Makefile.Release"))
@ -85,14 +76,16 @@ func isAlreadyCached(module, path, target string, mode int) bool {
for _, file := range cgoFileNames(module, path, target, mode) { for _, file := range cgoFileNames(module, path, target, mode) {
file = filepath.Join(path, file) file = filepath.Join(path, file)
if utils.ExistsFile(file) { if utils.ExistsFile(file) {
file = utils.Load(file)
switch target { switch target {
case "darwin", "linux", "windows": case "darwin", "linux", "windows":
//TODO msys pkg-config mxe brew //TODO msys pkg-config mxe brew
return strings.Contains(utils.Load(file), utils.QT_DIR()) || strings.Contains(utils.Load(file), utils.QT_DARWIN_DIR()) return strings.Contains(file, utils.QT_DIR()) || strings.Contains(file, utils.QT_DARWIN_DIR()) ||
strings.Contains(file, utils.QT_MSYS2_DIR()) || strings.Contains(file, utils.QT_MXE_TRIPLET())
case "android": case "android":
return strings.Contains(utils.Load(file), utils.QT_DIR()) && strings.Contains(utils.Load(file), utils.ANDROID_NDK_DIR()) return strings.Contains(file, utils.QT_DIR()) && strings.Contains(file, utils.ANDROID_NDK_DIR())
case "ios", "ios-simulator": case "ios", "ios-simulator":
return strings.Contains(utils.Load(file), utils.QT_DIR()) || strings.Contains(utils.Load(file), utils.QT_DARWIN_DIR()) return strings.Contains(file, utils.QT_DIR()) || strings.Contains(file, utils.QT_DARWIN_DIR())
case "sailfish", "sailfish-emulator", "asteroid": case "sailfish", "sailfish-emulator", "asteroid":
case "rpi1", "rpi2", "rpi3": case "rpi1", "rpi2", "rpi3":
} }
@ -181,7 +174,7 @@ func createMakefile(module, path, target string, mode int) {
utils.Save(pPath, "// +build windows\n"+content) utils.Save(pPath, "// +build windows\n"+content)
} }
} }
if mode == MOC || mode == RCC { if mode == MOC || mode == RCC || !utils.QT_MXE_STATIC() {
utils.RemoveAll(pPath) utils.RemoveAll(pPath)
} }
} }
@ -302,7 +295,12 @@ func createCgo(module, path, target string, mode int, ipkg string) string {
fmt.Fprint(bb, "*/\nimport \"C\"\n") fmt.Fprint(bb, "*/\nimport \"C\"\n")
tmp := bb.String() out, err := format.Source(bb.Bytes())
if err != nil {
utils.Log.WithError(err).Panicln("failed to format:", module)
}
tmp := string(out)
switch target { switch target {
case "ios": case "ios":
@ -339,10 +337,10 @@ func createCgo(module, path, target string, mode int, ipkg string) string {
for _, file := range cgoFileNames(module, path, target, mode) { for _, file := range cgoFileNames(module, path, target, mode) {
switch target { switch target {
case "windows": case "windows":
if utils.UseMsys2() && utils.QT_MSYS2_ARCH() == "amd64" { if utils.QT_MSYS2() && utils.QT_MSYS2_ARCH() == "amd64" {
tmp = strings.Replace(tmp, " -Wa,-mbig-obj ", " ", -1) tmp = strings.Replace(tmp, " -Wa,-mbig-obj ", " ", -1)
} }
if (utils.UseMsys2() && utils.QT_MSYS2_ARCH() == "amd64") || utils.QT_MXE_ARCH() == "amd64" { if (utils.QT_MSYS2() && utils.QT_MSYS2_ARCH() == "amd64") || utils.QT_MXE_ARCH() == "amd64" {
tmp = strings.Replace(tmp, " -Wl,-s ", " ", -1) tmp = strings.Replace(tmp, " -Wl,-s ", " ", -1)
} }
case "ios": case "ios":
@ -378,7 +376,7 @@ func cgoFileNames(module, path, target string, mode int) []string {
case "linux": case "linux":
sFixes = []string{"linux_amd64"} sFixes = []string{"linux_amd64"}
case "windows": case "windows":
if utils.QT_MXE_ARCH() == "amd64" || (utils.UseMsys2() && utils.QT_MSYS2_ARCH() == "amd64") { if utils.QT_MXE_ARCH() == "amd64" || (utils.QT_MSYS2() && utils.QT_MSYS2_ARCH() == "amd64") {
sFixes = []string{"windows_amd64"} sFixes = []string{"windows_amd64"}
} else { } else {
sFixes = []string{"windows_386"} sFixes = []string{"windows_386"}

View file

@ -10,15 +10,18 @@ import (
"strings" "strings"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/therecipe/qt/internal/utils" "github.com/therecipe/qt/internal/utils"
) )
func ParseFlags() { func ParseFlags() bool {
var ( var (
debug = flag.Bool("debug", false, "print debug logs") debug = flag.Bool("debug", false, "print debug logs")
p = flag.Int("p", runtime.NumCPU(), "the number of cpu's used") //TODO: docker
qt_dir = flag.String("qt_dir", "", "define alternative qt dir") help = flag.Bool("help", false, "print help")
qt_version = flag.String("qt_version", "", "define alternative qt version") p = flag.Int("p", runtime.NumCPU(), "specify the number of cpu's to be used")
qt_dir = flag.String("qt_dir", utils.QT_DIR(), "export QT_DIR")
qt_version = flag.String("qt_version", utils.QT_VERSION(), "export QT_VERSION")
) )
flag.Parse() flag.Parse()
@ -28,13 +31,15 @@ func ParseFlags() {
runtime.GOMAXPROCS(*p) runtime.GOMAXPROCS(*p)
if dir := *qt_dir; dir != "" { if dir := *qt_dir; dir != utils.QT_DIR() {
os.Setenv("QT_DIR", dir) os.Setenv("QT_DIR", dir)
} }
if version := *qt_version; version != "" { if version := *qt_version; version != utils.QT_VERSION() {
os.Setenv("QT_VERSION", version) os.Setenv("QT_VERSION", version)
} }
return help != nil && *help
} }
func Docker(arg []string, buildTarget, appPath string) { func Docker(arg []string, buildTarget, appPath string) {
@ -126,3 +131,181 @@ func Docker(arg []string, buildTarget, appPath string) {
utils.RunCmd(exec.Command("docker", args...), fmt.Sprintf("deploy binary for %v on %v with docker", buildTarget, runtime.GOOS)) utils.RunCmd(exec.Command("docker", args...), fmt.Sprintf("deploy binary for %v on %v with docker", buildTarget, runtime.GOOS))
} }
func EnvAndTagFlags(target string) (env map[string]string, tagFlags string) {
switch target {
case
"android":
{
tagFlags = fmt.Sprintf("-tags=\"%v\"", target)
switch runtime.GOOS {
case "darwin", "linux":
{
env = map[string]string{
"PATH": os.Getenv("PATH"),
"GOPATH": utils.MustGoPath(),
"GOROOT": runtime.GOROOT(),
"GOOS": "android",
"GOARCH": "arm",
"GOARM": "7",
"CGO_ENABLED": "1",
"CC": filepath.Join(utils.ANDROID_NDK_DIR(), "toolchains", "arm-linux-androideabi-4.9", "prebuilt", runtime.GOOS+"-x86_64", "bin", "arm-linux-androideabi-gcc"),
"CXX": filepath.Join(utils.ANDROID_NDK_DIR(), "toolchains", "arm-linux-androideabi-4.9", "prebuilt", runtime.GOOS+"-x86_64", "bin", "arm-linux-androideabi-g++"),
"CGO_CPPFLAGS": fmt.Sprintf("-isystem %v", filepath.Join(utils.ANDROID_NDK_DIR(), "platforms", "android-16", "arch-arm", "usr", "include")),
"CGO_LDFLAGS": fmt.Sprintf("--sysroot=%v -llog", filepath.Join(utils.ANDROID_NDK_DIR(), "platforms", "android-16", "arch-arm")),
}
}
case "windows":
{
env = map[string]string{
"PATH": os.Getenv("PATH"),
"GOPATH": utils.MustGoPath(),
"GOROOT": runtime.GOROOT(),
"TMP": os.Getenv("TMP"),
"TEMP": os.Getenv("TEMP"),
"GOOS": "android",
"GOARCH": "arm",
"GOARM": "7",
"CGO_ENABLED": "1",
"CC": filepath.Join(utils.ANDROID_NDK_DIR(), "toolchains", "arm-linux-androideabi-4.9", "prebuilt", runtime.GOOS+"-x86_64", "bin", "arm-linux-androideabi-gcc"),
"CXX": filepath.Join(utils.ANDROID_NDK_DIR(), "toolchains", "arm-linux-androideabi-4.9", "prebuilt", runtime.GOOS+"-x86_64", "bin", "arm-linux-androideabi-g++"),
"CGO_CPPFLAGS": fmt.Sprintf("-isystem %v", filepath.Join(utils.ANDROID_NDK_DIR(), "platforms", "android-16", "arch-arm", "usr", "include")),
"CGO_LDFLAGS": fmt.Sprintf("--sysroot=%v -llog", filepath.Join(utils.ANDROID_NDK_DIR(), "platforms", "android-16", "arch-arm")),
}
}
}
}
case
"ios", "ios-simulator":
{
tagFlags = "-tags=\"ios\""
var ClangDir, ClangPlatform, ClangFlag, ClangArch, GoArch = func() (string, string, string, string, string) {
if target == "ios" {
return "iPhoneOS", utils.IPHONEOS_SDK_DIR(), "iphoneos", "arm64", "arm64"
}
return "iPhoneSimulator", utils.IPHONESIMULATOR_SDK_DIR(), "ios-simulator", "x86_64", "amd64"
}()
env = map[string]string{
"PATH": os.Getenv("PATH"),
"GOPATH": utils.MustGoPath(),
"GOROOT": runtime.GOROOT(),
"GOOS": runtime.GOOS,
"GOARCH": GoArch,
"CGO_ENABLED": "1",
"CGO_CPPFLAGS": fmt.Sprintf("-isysroot %v/Contents/Developer/Platforms/%v.platform/Developer/SDKs/%v -m%v-version-min=7.0 -arch %v", utils.XCODE_DIR(), ClangDir, ClangPlatform, ClangFlag, ClangArch),
"CGO_LDFLAGS": fmt.Sprintf("-isysroot %v/Contents/Developer/Platforms/%v.platform/Developer/SDKs/%v -m%v-version-min=7.0 -arch %v", utils.XCODE_DIR(), ClangDir, ClangPlatform, ClangFlag, ClangArch),
}
}
case
"desktop":
{
if runtime.GOOS == "windows" {
env = map[string]string{
"PATH": os.Getenv("PATH"),
"GOPATH": utils.MustGoPath(),
"GOROOT": runtime.GOROOT(),
"TMP": os.Getenv("TMP"),
"TEMP": os.Getenv("TEMP"),
"GOOS": runtime.GOOS,
"GOARCH": "386",
"CGO_ENABLED": "1",
}
if utils.QT_MSYS2() {
env["GOARCH"] = utils.QT_MSYS2_ARCH()
}
}
}
case "sailfish", "sailfish-emulator":
{
tagFlags = fmt.Sprintf("-tags=\"%v\"", strings.Replace(target, "-", "_", -1))
env = map[string]string{
"PATH": os.Getenv("PATH"),
"GOPATH": utils.MustGoPath(),
"GOROOT": runtime.GOROOT(),
"GOOS": "linux",
"GOARCH": "386",
}
if runtime.GOOS == "windows" {
env["TMP"] = os.Getenv("TMP")
env["TEMP"] = os.Getenv("TEMP")
}
if target == "sailfish" {
env["GOARCH"] = "arm"
env["GOARM"] = "7"
}
}
case "rpi1", "rpi2", "rpi3":
{
if runtime.GOOS == "linux" {
tagFlags = fmt.Sprintf("-tags=\"%v\"", target)
env = map[string]string{
"PATH": os.Getenv("PATH"),
"GOPATH": utils.MustGoPath(),
"GOROOT": runtime.GOROOT(),
"GOOS": "linux",
"GOARCH": "arm",
"GOARM": "7",
"CGO_ENABLED": "1",
"CC": fmt.Sprintf("%v/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc", utils.RPI_TOOLS_DIR()),
"CXX": fmt.Sprintf("%v/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-g++", utils.RPI_TOOLS_DIR()),
}
if target == "rpi1" {
env["GOARM"] = "6"
}
} else {
utils.Log.Panicf("failed to install %v on %v", target, runtime.GOOS)
}
}
case "windows":
{
tagFlags = fmt.Sprintf("-tags=\"%v\"", target)
env = map[string]string{
"PATH": os.Getenv("PATH"),
"GOPATH": utils.MustGoPath(),
"GOROOT": runtime.GOROOT(),
"GOOS": "windows",
"GOARCH": utils.QT_MXE_ARCH(),
"CGO_ENABLED": "1",
"CC": utils.QT_MXE_BIN("gcc"),
"CXX": utils.QT_MXE_BIN("g++"),
}
}
default:
{
utils.Log.Panicf("failed to install %v on %v", target, runtime.GOOS)
}
}
return
}

View file

@ -18,10 +18,12 @@ import (
"github.com/therecipe/qt/internal/binding/parser" "github.com/therecipe/qt/internal/binding/parser"
"github.com/therecipe/qt/internal/binding/templater" "github.com/therecipe/qt/internal/binding/templater"
"github.com/therecipe/qt/internal/cmd" "github.com/therecipe/qt/internal/cmd"
"github.com/therecipe/qt/internal/cmd/minimal" "github.com/therecipe/qt/internal/cmd/minimal"
"github.com/therecipe/qt/internal/cmd/moc" "github.com/therecipe/qt/internal/cmd/moc"
"github.com/therecipe/qt/internal/cmd/rcc" "github.com/therecipe/qt/internal/cmd/rcc"
"github.com/therecipe/qt/internal/utils" "github.com/therecipe/qt/internal/utils"
) )
@ -49,7 +51,7 @@ func Deploy(s *State) {
gLdFlags = s.LdFlags gLdFlags = s.LdFlags
if !filepath.IsAbs(appPath) { if !filepath.IsAbs(appPath) {
appPath, _ = utils.Abs(appPath) appPath, _ = filepath.Abs(appPath)
} }
appName = filepath.Base(appPath) appName = filepath.Base(appPath)
@ -101,19 +103,19 @@ func Deploy(s *State) {
if env_output_dir := os.Getenv("QTRCC_OUTPUT_DIR"); env_output_dir != "" { if env_output_dir := os.Getenv("QTRCC_OUTPUT_DIR"); env_output_dir != "" {
qtrcc_output = &env_output_dir qtrcc_output = &env_output_dir
} }
rcc.QmakeCleanPath(appPath)
rcc.Rcc(qtrcc_cwd, buildTarget, qtrcc_output) rcc.Rcc(qtrcc_cwd, buildTarget, qtrcc_output)
utils.Log.Debug("qtrcc - done") utils.Log.Debug("qtrcc - done")
//moc //moc
utils.Log.Debug("qtmoc - start") utils.Log.Debug("qtmoc - start")
moc.QmakeCleanPath(appPath)
moc.MocTree(appPath, buildTarget) moc.MocTree(appPath, buildTarget)
utils.Log.Debug("qtmoc - done") utils.Log.Debug("qtmoc - done")
//minimal //minimal
utils.Log.Debug("qtminimal - start") utils.Log.Debug("qtminimal - start")
minimal.Minimal(appPath, buildTarget) minimal.Minimal(appPath, buildTarget)
parser.State.Minimal = false parser.State.Minimal = false
for _, c := range parser.State.ClassMap { for _, c := range parser.State.ClassMap {
@ -289,7 +291,7 @@ func build() {
"CGO_ENABLED": "1", "CGO_ENABLED": "1",
} }
if utils.UseMsys2() { if utils.QT_MSYS2() {
env["GOARCH"] = utils.QT_MSYS2_ARCH() env["GOARCH"] = utils.QT_MSYS2_ARCH()
} }
} }
@ -717,10 +719,10 @@ func deployInternal() {
} }
} }
case utils.UseMsys2(): case utils.QT_MSYS2():
{ {
var copyCmd = "xcopy" var copyCmd = "xcopy"
if os.Getenv("MSYSTEM") != "" { if utils.MSYSTEM() != "" {
copyCmd = "cp" copyCmd = "cp"
} }
@ -744,7 +746,7 @@ func deployInternal() {
utils.RunCmdOptional(exec.Command(copyCmd, filepath.Join(libraryPath, fmt.Sprintf("%v.dll", gccDep)), depPath), fmt.Sprintf("copy %v for %v on %v", gccDep, buildTarget, runtime.GOOS)) utils.RunCmdOptional(exec.Command(copyCmd, filepath.Join(libraryPath, fmt.Sprintf("%v.dll", gccDep)), depPath), fmt.Sprintf("copy %v for %v on %v", gccDep, buildTarget, runtime.GOOS))
libraryPath = filepath.Join(utils.QT_MSYS2_DIR(), "share", "qt5") libraryPath = filepath.Join(utils.QT_MSYS2_DIR(), "share", "qt5")
if os.Getenv("MSYSTEM") != "" { if utils.MSYSTEM() != "" {
utils.RunCmd(exec.Command("cp", "-R", filepath.Join(libraryPath, "qml/")+"/.", depPath), fmt.Sprintf("copy qml dir for %v on %v", buildTarget, runtime.GOOS)) utils.RunCmd(exec.Command("cp", "-R", filepath.Join(libraryPath, "qml/")+"/.", depPath), fmt.Sprintf("copy qml dir for %v on %v", buildTarget, runtime.GOOS))
utils.RunCmd(exec.Command("cp", "-R", filepath.Join(libraryPath, "plugins/")+"/.", depPath), fmt.Sprintf("copy plugins dir for %v on %v", buildTarget, runtime.GOOS)) utils.RunCmd(exec.Command("cp", "-R", filepath.Join(libraryPath, "plugins/")+"/.", depPath), fmt.Sprintf("copy plugins dir for %v on %v", buildTarget, runtime.GOOS))
} else { } else {
@ -784,7 +786,7 @@ func deployInternal() {
case runtime.GOOS == "darwin": case runtime.GOOS == "darwin":
{ {
if utils.UseHomeBrew() { if utils.QT_HOMEBREW() {
return return
} }
@ -798,7 +800,7 @@ func deployInternal() {
case runtime.GOOS == "linux": case runtime.GOOS == "linux":
{ {
if utils.UsePkgConfig() { if utils.QT_PKG_CONFIG() {
return return
} }
@ -1109,7 +1111,7 @@ func linuxSH() string {
fmt.Fprint(bb, "export LD_PRELOAD=\"/opt/vc/lib/libGLESv2.so /opt/vc/lib/libEGL.so\"\n") fmt.Fprint(bb, "export LD_PRELOAD=\"/opt/vc/lib/libGLESv2.so /opt/vc/lib/libEGL.so\"\n")
} }
if utils.UsePkgConfig() { if utils.QT_PKG_CONFIG() {
var ( var (
libDir = strings.TrimSpace(utils.RunCmd(exec.Command("pkg-config", "--variable=libdir", "Qt5Core"), fmt.Sprintf("get lib dir for %v on %v", buildTarget, runtime.GOOS))) libDir = strings.TrimSpace(utils.RunCmd(exec.Command("pkg-config", "--variable=libdir", "Qt5Core"), fmt.Sprintf("get lib dir for %v on %v", buildTarget, runtime.GOOS)))
miscDir = utils.QT_MISC_DIR() miscDir = utils.QT_MISC_DIR()

View file

@ -11,10 +11,15 @@ import (
"github.com/therecipe/qt/internal/binding/converter" "github.com/therecipe/qt/internal/binding/converter"
"github.com/therecipe/qt/internal/binding/parser" "github.com/therecipe/qt/internal/binding/parser"
"github.com/therecipe/qt/internal/binding/templater" "github.com/therecipe/qt/internal/binding/templater"
"github.com/therecipe/qt/internal/utils" "github.com/therecipe/qt/internal/utils"
) )
func Minimal(appPath, buildTarget string) { func Minimal(appPath, buildTarget string) {
if utils.QT_QMAKE_CGO() {
QmakeMinimal(appPath, buildTarget)
return
}
var ( var (
imported []string imported []string
@ -170,7 +175,7 @@ func Minimal(appPath, buildTarget string) {
delete(parser.State.ClassMap, c.Name) delete(parser.State.ClassMap, c.Name)
} }
if !IsWhiteListedSailfishLib(strings.TrimPrefix(c.Module, "Qt")) { if !parser.IsWhiteListedSailfishLib(strings.TrimPrefix(c.Module, "Qt")) {
delete(parser.State.ClassMap, c.Name) delete(parser.State.ClassMap, c.Name)
} }
@ -350,17 +355,3 @@ func isBlacklisted(appPath, currentPath string) bool {
return false return false
} }
func IsWhiteListedSailfishLib(name string) bool {
switch name {
case "Core", "Quick", "Qml", "Network", "Gui", "Concurrent", "Multimedia", "Sql", "Svg", "XmlPatterns", "Xml", "DBus", "WebKit", "Sensors", "Positioning":
{
return true
}
default:
{
return false
}
}
}

View file

@ -0,0 +1,293 @@
package minimal
import (
"fmt"
goparser "go/parser"
"go/token"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/therecipe/qt/internal/binding/converter"
"github.com/therecipe/qt/internal/binding/parser"
"github.com/therecipe/qt/internal/binding/templater"
"github.com/therecipe/qt/internal/utils"
)
func QmakeMinimal(path, target string) {
utils.Log.WithField("path", path).WithField("target", target).Debug("start QmakeMinimal")
var files []string
for _, path := range append([]string{path}, getAllImports(path, 0)...) {
fileList, err := ioutil.ReadDir(path)
if err != nil {
utils.Log.WithError(err).Error("failed to read dir")
continue
}
for _, file := range fileList {
path := filepath.Join(path, file.Name())
if !file.IsDir() && filepath.Ext(path) == ".go" {
files = append(files, utils.Load(path))
utils.Log.WithField("path", path).Debug("analyse for minimal")
}
}
}
c := len(files)
utils.Log.Debugln("found", c, "files to analyse")
if c == 0 {
return
}
if len(parser.State.ClassMap) == 0 {
parser.LoadModules()
} else {
utils.Log.Debug("modules already cached")
}
for _, f := range files {
for _, c := range parser.State.ClassMap {
if strings.Contains(f, c.Name) &&
strings.Contains(f, fmt.Sprintf("github.com/therecipe/qt/%v", strings.ToLower(strings.TrimPrefix(c.Module, "Qt")))) {
QmakeExportClass(c, files)
}
}
}
/* TODO:
if buildTarget == "sailfish" || buildTarget == "sailfish-emulator" {
if _, ok := parser.State.ClassMap["TestCase"]; ok {
delete(parser.State.ClassMap, "TestCase")
}
//TODO: use parseFloat
for _, c := range parser.State.ClassMap {
switch c.Since {
case "5.3", "5.4", "5.5", "5.6", "5.7", "5.8":
delete(parser.State.ClassMap, c.Name)
}
if !parser.IsWhiteListedSailfishLib(strings.TrimPrefix(c.Module, "Qt")) {
delete(parser.State.ClassMap, c.Name)
}
for _, f := range c.Functions {
switch f.Since {
case "5.3", "5.4", "5.5", "5.6", "5.7", "5.8":
f.Export = false
}
}
}
}
if buildTarget == "asteroid" {
if _, ok := parser.State.ClassMap["TestCase"]; ok {
delete(parser.State.ClassMap, "TestCase")
}
if _, ok := parser.State.ClassMap["QQuickWidget"]; ok {
parser.State.ClassMap["QQuickWidget"].Export = false
}
for k, c := range parser.State.ClassMap {
switch c.Since {
case "5.7", "5.8":
delete(parser.State.ClassMap, c.Name)
}
for _, f := range c.Functions {
switch f.Since {
case "5.7", "5.8":
f.Export = false
}
}
if strings.HasPrefix(k, "QAccessible") {
delete(parser.State.ClassMap, k)
}
}
}
if buildTarget == "ios" || buildTarget == "ios-simulator" {
parser.State.ClassMap["QProcess"].Export = false
parser.State.ClassMap["QProcessEnvironment"].Export = false
}
*/
//TODO: cleanup state
parser.State.Minimal = true
for _, m := range parser.Libs {
templater.GenModule(m, target, templater.MINIMAL)
}
parser.State.Minimal = false
for _, c := range parser.State.ClassMap {
c.Export = false
for _, f := range c.Functions {
f.Export = false
}
}
}
func getAllImports(path string, level int) []string {
utils.Log.WithField("path", path).WithField("level", level).Debug("getAllImports")
var imports []string
level++
if level > 2 {
return imports
}
files, err := ioutil.ReadDir(path)
if err != nil {
utils.Log.WithError(err).Fatal("failed to read dir")
}
var fileList []string
for _, f := range files {
if !f.IsDir() && filepath.Ext(f.Name()) == ".go" {
fileList = append(fileList, filepath.Join(path, f.Name()))
}
}
for _, f := range fileList {
file, err := goparser.ParseFile(token.NewFileSet(), f, nil, 0)
if err != nil {
utils.Log.WithError(err).Debugln("failed to parse", f)
continue
}
for _, i := range file.Imports {
if strings.Contains(i.Path.Value, "github.com/therecipe/qt") && !strings.Contains(i.Path.Value, "qt/internal") {
continue
}
for _, gopath := range strings.Split(os.Getenv("GOPATH"), string(os.PathListSeparator)) {
path := filepath.Join(gopath, "src", strings.Replace(i.Path.Value, "\"", "", -1))
if utils.ExistsDir(path) {
var has bool
for _, i := range imports {
if i == path {
has = true
break
}
}
if has {
continue
}
imports = append(imports, path)
for _, path := range getAllImports(path, level) {
var has bool
for _, i := range imports {
if i == path {
has = true
break
}
}
if !has {
imports = append(imports, path)
}
}
}
}
}
}
return imports
}
func QmakeExportClass(c *parser.Class, files []string) {
if c.Export {
return
}
c.Export = true
for _, file := range files {
for _, f := range c.Functions {
switch {
case f.Virtual == parser.IMPURE, f.Virtual == parser.PURE, f.Meta == parser.SIGNAL, f.Meta == parser.SLOT:
for _, mode := range []string{parser.CONNECT, parser.DISCONNECT, ""} {
f.SignalMode = mode
if strings.Contains(file, "."+converter.GoHeaderName(f)+"(") {
QmakeExportFunction(f, files)
}
}
default:
if f.Static {
if strings.Contains(file, "."+converter.GoHeaderName(f)+"(") {
QmakeExportFunction(f, files)
}
f.Static = false
if strings.Contains(file, "."+converter.GoHeaderName(f)+"(") {
QmakeExportFunction(f, files)
}
f.Static = true
} else {
if strings.Contains(file, "."+converter.GoHeaderName(f)+"(") {
QmakeExportFunction(f, files)
}
}
}
if strings.HasPrefix(f.Name, "__") || f.Meta == parser.CONSTRUCTOR ||
f.Meta == parser.DESTRUCTOR || f.Virtual == parser.PURE {
QmakeExportFunction(f, files)
}
}
}
for _, b := range c.GetAllBases() {
if c, ok := parser.State.ClassMap[b]; ok {
QmakeExportClass(c, files)
}
}
}
func QmakeExportFunction(f *parser.Function, files []string) {
if f.Export {
return
}
f.Export = true
for _, p := range f.Parameters {
if c, ok := parser.State.ClassMap[parser.CleanValue(p.Value)]; ok {
QmakeExportClass(c, files)
}
if parser.IsPackedList(p.Value) {
if c, ok := parser.State.ClassMap[parser.UnpackedList(p.Value)]; ok {
QmakeExportClass(c, files)
}
}
if parser.IsPackedMap(p.Value) {
key, value := parser.UnpackedMap(p.Value)
if c, ok := parser.State.ClassMap[key]; ok {
QmakeExportClass(c, files)
}
if c, ok := parser.State.ClassMap[value]; ok {
QmakeExportClass(c, files)
}
}
}
if c, ok := parser.State.ClassMap[parser.CleanValue(f.Output)]; ok {
QmakeExportClass(c, files)
}
if parser.IsPackedList(f.Output) {
if c, ok := parser.State.ClassMap[parser.UnpackedList(f.Output)]; ok {
QmakeExportClass(c, files)
}
}
if parser.IsPackedMap(f.Output) {
key, value := parser.UnpackedMap(f.Output)
if c, ok := parser.State.ClassMap[key]; ok {
QmakeExportClass(c, files)
}
if c, ok := parser.State.ClassMap[value]; ok {
QmakeExportClass(c, files)
}
}
}

View file

@ -24,7 +24,7 @@ func QmakeMoc(path, target string) {
if err != nil { if err != nil {
return err return err
} }
if path != current && info.IsDir() && !isBlacklistedPath(path, current) { if info.IsDir() && path != current && !isBlacklistedPath(path, current) {
QmakeMoc(current, target) QmakeMoc(current, target)
} }
return nil return nil
@ -153,17 +153,12 @@ func QmakeMoc(path, target string) {
utils.Log.Debug("done copy structors") utils.Log.Debug("done copy structors")
if err := utils.SaveBytes(filepath.Join(path, "moc.cpp"), templater.CppTemplate(parser.MOC, templater.MOC)); err != nil { if err := utils.SaveBytes(filepath.Join(path, "moc.cpp"), templater.CppTemplate(parser.MOC, templater.MOC)); err != nil {
utils.Log.WithError(err).Error("failed to run cppTemplate")
return return
} }
if err := utils.SaveBytes(filepath.Join(path, "moc.h"), templater.HTemplate(parser.MOC, templater.MOC)); err != nil { if err := utils.SaveBytes(filepath.Join(path, "moc.h"), templater.HTemplate(parser.MOC, templater.MOC)); err != nil {
utils.Log.WithError(err).Error("failed to run hTemplate")
return return
} }
if err := utils.SaveBytes(filepath.Join(path, "moc.go"), templater.GoTemplate(parser.MOC, false, templater.MOC, pkg)); err != nil { if err := utils.SaveBytes(filepath.Join(path, "moc.go"), templater.GoTemplate(parser.MOC, false, templater.MOC, pkg)); err != nil {
utils.Log.WithError(err).Error("failed to run goTemplate")
return return
} }
templater.QmakeCgoTemplate(parser.MOC, path, target, templater.MOC, pkg) templater.QmakeCgoTemplate(parser.MOC, path, target, templater.MOC, pkg)
@ -180,6 +175,7 @@ func QmakeMoc(path, target string) {
func parse(path string) ([]*parser.Class, string, error) { func parse(path string) ([]*parser.Class, string, error) {
utils.Log.WithField("path", path).Debug("parse") utils.Log.WithField("path", path).Debug("parse")
src, err := ioutil.ReadFile(path) src, err := ioutil.ReadFile(path)
if err != nil { if err != nil {
return nil, "", err return nil, "", err
@ -239,7 +235,7 @@ func parse(path string) ([]*parser.Class, string, error) {
meta = parser.SLOT meta = parser.SLOT
case strings.HasPrefix(tag, "property:"): case strings.HasPrefix(tag, "property:"):
meta = parser.PROP meta = parser.PROP
case strings.HasPrefix(tag, "constructor:"): case strings.HasPrefix(tag, "constructor:"): //TODO: more advanced constructor support (multiple constructors, custom inputs, error output, custom naming, ...)
meta = parser.CONSTRUCTOR meta = parser.CONSTRUCTOR
default: default:
continue continue

View file

@ -120,7 +120,7 @@ func qmlHeader(appName, appPath, buildTarget string) string {
import "C"`, import "C"`,
"${QT_WINDOWS_DIR}", func() string { "${QT_WINDOWS_DIR}", func() string {
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
if utils.UseMsys2() { if utils.QT_MSYS2() {
return filepath.Join(utils.QT_MSYS2_DIR(), "lib") return filepath.Join(utils.QT_MSYS2_DIR(), "lib")
} }
return "${QT_DIR}/${QT_VERSION_MAJOR}/mingw53_32/lib" return "${QT_DIR}/${QT_VERSION_MAJOR}/mingw53_32/lib"
@ -129,7 +129,7 @@ import "C"`,
}(), -1), }(), -1),
"${QT_DARWIN_DIR}", utils.QT_DARWIN_DIR(), -1), "${QT_DARWIN_DIR}", utils.QT_DARWIN_DIR(), -1),
"${QT_LINUX_DIR}", func() string { "${QT_LINUX_DIR}", func() string {
if utils.UsePkgConfig() { if utils.QT_PKG_CONFIG() {
return strings.TrimSpace(utils.RunCmd(exec.Command("pkg-config", "--variable=libdir", "Qt5Core"), fmt.Sprintf("find linux pkg-config lib dir on %v", runtime.GOOS))) return strings.TrimSpace(utils.RunCmd(exec.Command("pkg-config", "--variable=libdir", "Qt5Core"), fmt.Sprintf("find linux pkg-config lib dir on %v", runtime.GOOS)))
} }
return "${QT_DIR}/${QT_VERSION_MAJOR}/gcc_64/lib" return "${QT_DIR}/${QT_VERSION_MAJOR}/gcc_64/lib"

View file

@ -9,10 +9,13 @@ import (
"strings" "strings"
"github.com/therecipe/qt/internal/binding/templater" "github.com/therecipe/qt/internal/binding/templater"
"github.com/therecipe/qt/internal/utils" "github.com/therecipe/qt/internal/utils"
) )
func QmakeRcc(path, target string, output_dir *string) { func QmakeRcc(path, target string, output_dir *string) { //TODO: make output_dir string
utils.Log.WithField("path", path).WithField("target", target).Debug("start QmakeRcc")
if dir := filepath.Join(path, "qml"); !utils.ExistsDir(dir) { if dir := filepath.Join(path, "qml"); !utils.ExistsDir(dir) {
utils.MkdirAll(dir) utils.MkdirAll(dir)
} }
@ -44,7 +47,8 @@ func QmakeRcc(path, target string, output_dir *string) {
} }
var fileList []string var fileList []string
for _, f := range files { for _, f := range files {
if !f.IsDir() && strings.HasSuffix(f.Name(), ".qrc") { if !f.IsDir() && filepath.Ext(f.Name()) == ".qrc" {
//TODO: check for buildTags
fileList = append(fileList, filepath.Join(path, f.Name())) fileList = append(fileList, filepath.Join(path, f.Name()))
} }
} }

View file

@ -1,6 +1,7 @@
package setup package setup
import ( import (
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec" "os/exec"
@ -10,165 +11,129 @@ import (
"github.com/therecipe/qt/internal/utils" "github.com/therecipe/qt/internal/utils"
) )
func check(buildTarget string) { func Check(target string) {
utils.Log.Infof("running setup/check %v", buildTarget) utils.Log.Infof("running setup/check %v", target)
utils.CheckBuildTarget(buildTarget) hash := "please install git"
if _, err := exec.LookPath("git"); err == nil {
hCmd := exec.Command("git", "rev-parse", "--verify", "HEAD")
hCmd.Dir = utils.GoQtPkgPath()
hash = strings.TrimSpace(utils.RunCmdOptional(hCmd, "get git hash"))
}
utils.Log.Infoln("VERSION:", "0.0.4") vars := [][]string{
utils.Log.Infoln("GOOS:", runtime.GOOS) {"GOOS", runtime.GOOS},
utils.Log.Infoln("GOARCH:", runtime.GOARCH) {"GOARCH", runtime.GOARCH},
utils.Log.Infoln("GOVERSION:", runtime.Version()) {"GOVERSION", runtime.Version()},
utils.Log.Infoln("GOROOT:", runtime.GOROOT()) {"GOROOT", runtime.GOROOT()},
utils.Log.Infoln("GOPATH:", utils.MustGoPath()) {"GOPATH", utils.MustGoPath()},
utils.Log.Infoln("GOBIN:", utils.MustGoBin()) {"GOBIN", utils.MustGoBin()},
{"QT_HASH", hash},
{"QT_VERSION", utils.QT_VERSION()},
{"QT_VERSION_MAJOR", utils.QT_VERSION_MAJOR()},
{"QT_DIR", utils.QT_DIR()},
{"QT_STUB", fmt.Sprint(utils.QT_STUB())},
{"QT_DEBUG", fmt.Sprint(utils.QT_DEBUG())},
}
var hash = exec.Command("git", "rev-parse", "--verify", "HEAD") if utils.CI() {
hash.Dir = utils.GoQtPkgPath() vars = append(vars, [][]string{
utils.Log.Infoln("HASH:", strings.TrimSpace(utils.RunCmdOptional(hash, "get git hash"))) {"CI", fmt.Sprint(utils.CI())},
{"QT_QMAKE_DIR", utils.QT_QMAKE_DIR()},
{"QT_QMAKE_CGO", fmt.Sprint(utils.QT_QMAKE_CGO())},
}...)
}
utils.Log.Infoln("QT_VERSION:", utils.QT_VERSION()) switch target {
utils.Log.Infoln("QT_VERSION_MAJOR:", utils.QT_VERSION_MAJOR())
utils.Log.Infoln("QT_DIR:", utils.QT_DIR())
utils.Log.Infoln("QT_STUB:", utils.QT_STUB())
switch buildTarget {
case "desktop", "ios", "ios-simulator": case "desktop", "ios", "ios-simulator":
{
switch runtime.GOOS {
case "darwin":
{
utils.Log.Infoln("QT_HOMEBREW:", os.Getenv("QT_HOMEBREW"))
utils.Log.Infoln("IsHomeBrewQtDir:", utils.IsHomeBrewQtDir())
utils.Log.Infoln("UseHomebrew:", utils.UseHomeBrew())
utils.Log.Infoln("QT_DARWIN_DIR:", utils.QT_DARWIN_DIR())
utils.Log.Infoln("XCODE_DIR:", utils.XCODE_DIR())
utils.Log.Infoln("MACOS_SDK_DIR:", utils.MACOS_SDK_DIR())
utils.Log.Infoln("IPHONEOS_SDK_DIR:", utils.IPHONEOS_SDK_DIR())
utils.Log.Infoln("IPHONESIMULATOR_SDK_DIR:", utils.IPHONESIMULATOR_SDK_DIR())
}
case "linux":
{
utils.Log.Infoln("Distro:", utils.LinuxDistro())
utils.Log.Infoln("QT_PKG_CONFIG:", os.Getenv("QT_PKG_CONFIG"))
utils.Log.Infoln("UsePkgConfig:", utils.UsePkgConfig())
if utils.UsePkgConfig() {
utils.Log.Infoln("QT_DOC_DIR:", utils.QT_DOC_DIR())
utils.Log.Infoln("QT_MISC_DIR:", utils.QT_MISC_DIR())
}
}
case "windows":
{
utils.Log.Infoln("MSYSTEM:", os.Getenv("MSYSTEM"))
utils.Log.Infoln("QT_MSYS2:", os.Getenv("QT_MSYS2"))
utils.Log.Infoln("QT_MSYS2_DIR:", os.Getenv("QT_MSYS2_DIR"))
utils.Log.Infoln("IsMsys2QtDir:", utils.IsMsys2QtDir())
utils.Log.Infoln("UseMsys2:", utils.UseMsys2())
}
}
}
case "android":
{
utils.Log.Infoln("JDK_DIR:", utils.JDK_DIR())
utils.Log.Infoln("JAVA_HOME:", os.Getenv("JAVA_HOME"))
utils.Log.Infoln("ANDROID_SDK_DIR:", utils.ANDROID_SDK_DIR())
utils.Log.Infoln("ANDROID_NDK_DIR:", utils.ANDROID_NDK_DIR())
}
case "sailfish", "sailfish-emulator":
{
utils.Log.Infoln("VIRTUALBOX_DIR:", utils.VIRTUALBOX_DIR())
utils.Log.Infoln("SAILFISH_DIR:", utils.SAILFISH_DIR())
}
case "rpi1", "rpi2", "rpi3":
{
utils.Log.Infoln("RPI_TOOLS_DIR:", utils.RPI_TOOLS_DIR())
utils.Log.Infoln("RPI1_SYSROOT_DIR:", utils.RPI1_SYSROOT_DIR())
utils.Log.Infoln("RPI2_SYSROOT_DIR:", utils.RPI2_SYSROOT_DIR())
utils.Log.Infoln("RPI3_SYSROOT_DIR:", utils.RPI3_SYSROOT_DIR())
}
case "windows":
{
utils.Log.Infoln("QT_MXE_ARCH:", os.Getenv("QT_MXE_ARCH"))
}
case "windows-docker", "linux-docker", "android-docker":
{
//TODO:
}
}
if _, err := ioutil.ReadDir(utils.QT_DIR()); err != nil && !(utils.UsePkgConfig() || utils.UseHomeBrew() || utils.UseMsys2()) {
utils.Log.WithError(err).Panic("failed to find Qt dir, did you export QT_DIR?")
}
if !strings.HasSuffix(buildTarget, "-docker") {
switch runtime.GOOS { switch runtime.GOOS {
case "darwin": case "darwin":
{ vars = append(vars, [][]string{
if _, err := exec.LookPath("clang++"); err != nil { {"QT_HOMEBREW", fmt.Sprint(utils.QT_HOMEBREW())},
utils.Log.WithError(err).Panic("failed to find clang++, did you install Xcode?") {"XCODE_DIR", utils.XCODE_DIR()},
} //{"IPHONEOS_SDK_DIR", utils.IPHONEOS_SDK_DIR()}, //TODO: re-add after deploy is done; with absolute path
} //{"IPHONESIMULATOR_SDK_DIR", utils.IPHONESIMULATOR_SDK_DIR()}, //TODO: re-add after deploy is done; with absolute path
}...)
case "linux": case "linux":
{ vars = append(vars, [][]string{
if _, err := exec.LookPath("g++"); err != nil { {"QT_DISTRO", utils.QT_DISTRO()},
utils.Log.WithError(err).Panic("failed to find g++, did you install g++?") {"QT_PKG_CONFIG", fmt.Sprint(utils.QT_PKG_CONFIG())},
} }...)
}
if utils.QT_PKG_CONFIG() {
vars = append(vars, [][]string{
{"QT_DOC_DIR", utils.QT_DOC_DIR()},
{"QT_MISC_DIR", utils.QT_MISC_DIR()},
}...)
}
case "windows": case "windows":
{ vars = append(vars, [][]string{
if _, err := exec.LookPath("g++"); err != nil && !utils.UseMsys2() { {"QT_MSYS2", fmt.Sprint(utils.QT_MSYS2())},
utils.Log.WithError(err).Panic("failed to find g++, did you add the directory that contains g++ to your PATH?") {"QT_MSYS2_DIR", utils.QT_MSYS2_DIR()},
} {"QT_MSYS2_ARCH", utils.QT_MSYS2_ARCH()},
} }...)
} }
}
switch buildTarget {
case "android": case "android":
{ vars = append(vars, [][]string{
if _, err := ioutil.ReadDir(utils.ANDROID_SDK_DIR()); err != nil { {"JDK_DIR", utils.JDK_DIR()},
utils.Log.WithError(err).Panic("failed to find android-sdk dir, did you export ANDROID_SDK_DIR?") {"ANDROID_SDK_DIR", utils.ANDROID_SDK_DIR()},
} {"ANDROID_NDK_DIR", utils.ANDROID_NDK_DIR()},
}...)
if _, err := ioutil.ReadDir(utils.ANDROID_NDK_DIR()); err != nil {
utils.Log.WithError(err).Panic("failed to find android-ndk dir, did you export ANDROID_NDK_DIR?")
}
if _, err := ioutil.ReadDir(utils.JDK_DIR()); err != nil {
utils.Log.WithError(err).Panic("failed to find jdk dir, did you export JDK_DIR?")
}
}
case "sailfish", "sailfish-emulator": case "sailfish", "sailfish-emulator":
{ vars = append(vars, [][]string{
if _, err := ioutil.ReadDir(utils.VIRTUALBOX_DIR()); err != nil { {"VIRTUALBOX_DIR", utils.VIRTUALBOX_DIR()},
utils.Log.WithError(err).Panic("failed to find virtualbox dir, did you export VIRTUALBOX_DIR?") {"SAILFISH_DIR", utils.SAILFISH_DIR()},
} }...)
if _, err := ioutil.ReadDir(utils.SAILFISH_DIR()); err != nil {
utils.Log.WithError(err).Panic("failed to find sailfish-sdk dir, did you export SAILFISH_DIR?")
}
}
case "rpi1", "rpi2", "rpi3": case "rpi1", "rpi2", "rpi3":
{ vars = append(vars, [][]string{
//TODO: {"RPI_TOOLS_DIR", utils.RPI_TOOLS_DIR()},
} {"RPI1_SYSROOT_DIR", utils.RPI1_SYSROOT_DIR()},
{"RPI2_SYSROOT_DIR", utils.RPI2_SYSROOT_DIR()},
{"RPI3_SYSROOT_DIR", utils.RPI3_SYSROOT_DIR()},
}...)
case "windows":
vars = append(vars, [][]string{
{"QT_MXE_DIR", utils.QT_MXE_DIR()},
{"QT_MXE_ARCH", utils.QT_MXE_ARCH()},
//{"QT_MXE_STATIC", fmt.Sprint(utils.QT_MXE_STATIC())},
}...)
}
case "windows-docker", "linux-docker", "android-docker": for _, v := range vars {
{ var set string
if _, err := exec.LookPath("docker"); err != nil { if _, ok := os.LookupEnv(v[0]); ok {
utils.Log.WithError(err).Panic("failed to find docker, did you install docker?") set = "*"
}
utils.Log.Infof("%v:%v%v%v'%v'", v[0], strings.Repeat(" ", 25-len(v[0])), set, strings.Repeat(" ", 3-len(set)), v[1])
if strings.HasSuffix(v[0], "_DIR") {
if _, err := ioutil.ReadDir(v[1]); err != nil && v[1] != "" {
utils.Log.WithError(err).Panicf("failed to find %v (%v)", v[0], v[1])
} }
} }
} }
//TODO: combine -->
if !strings.HasSuffix(target, "-docker") {
switch runtime.GOOS {
case "darwin":
if _, err := exec.LookPath("clang++"); err != nil {
utils.Log.WithError(err).Panic("failed to find clang++, did you install Xcode?")
}
case "linux":
if _, err := exec.LookPath("g++"); err != nil {
utils.Log.WithError(err).Panic("failed to find g++, did you install g++?")
}
case "windows":
if _, err := exec.LookPath("g++"); err != nil && !utils.QT_MSYS2() {
utils.Log.WithError(err).Panic("failed to find g++, did you add the directory that contains g++ to your PATH?")
}
}
}
switch target {
case "windows-docker", "linux-docker", "android-docker":
if _, err := exec.LookPath("docker"); err != nil {
utils.Log.WithError(err).Panic("failed to find docker, did you install docker?")
}
}
//<--
} }

View file

@ -5,39 +5,32 @@ import (
"github.com/therecipe/qt/internal/binding/parser" "github.com/therecipe/qt/internal/binding/parser"
"github.com/therecipe/qt/internal/binding/templater" "github.com/therecipe/qt/internal/binding/templater"
"github.com/therecipe/qt/internal/utils" "github.com/therecipe/qt/internal/utils"
) )
func generate(buildTarget string) { func Generate(target string) {
utils.Log.Info("running setup/generate") utils.Log.Info("running setup/generate")
if testFile := utils.GoQtPkgPath("core", "cgo_desktop_darwin_amd64.go"); utils.ExistsFile(testFile) && strings.Contains(utils.Load(testFile), utils.QT_DIR()) {
if buildTarget != "desktop" && utils.QT_STUB() &&
!utils.ExistsFile(utils.GoQtPkgPath("core", "core.h")) &&
!utils.ExistsFile(utils.GoQtPkgPath("core", "core.cpp")) {
utils.Log.Debug("stub files are up to date -> don't re-generate")
return
}
if buildTarget != "desktop" && !utils.QT_STUB() &&
utils.ExistsFile(utils.GoQtPkgPath("core", "core.h")) &&
utils.ExistsFile(utils.GoQtPkgPath("core", "core.cpp")) {
utils.Log.Debug("full files are up to date -> don't re-generate")
return
}
}
parser.LoadModules() parser.LoadModules()
for _, module := range parser.GetLibs() { for _, module := range parser.GetLibs() {
utils.Log.Infof("generating %v qt/%v", func() string { if !parser.ShouldBuildForTarget(module, target) {
if utils.QT_STUB() { utils.Log.Debug("skipping generation of %v for %v", module, target)
return "stub" continue
} }
return "full"
}(), strings.ToLower(module)) mode := "full"
templater.GenModule(module, buildTarget, templater.NONE) if utils.QT_STUB() {
mode = "stub"
}
utils.Log.Infof("generating %v qt/%v", mode, strings.ToLower(module))
if target != "desktop" {
templater.CgoTemplate(module, "", target, templater.NONE, "")
continue
}
templater.GenModule(module, target, templater.NONE)
} }
} }

View file

@ -3,7 +3,6 @@ package setup
import ( import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"runtime" "runtime"
@ -11,267 +10,71 @@ import (
"strings" "strings"
"github.com/therecipe/qt/internal/binding/parser" "github.com/therecipe/qt/internal/binding/parser"
"github.com/therecipe/qt/internal/cmd"
"github.com/therecipe/qt/internal/utils" "github.com/therecipe/qt/internal/utils"
) )
func install(buildTarget string) { func Install(target string) {
utils.Log.Infof("running setup/install %v", buildTarget) utils.Log.Infof("running setup/install %v", target)
if strings.HasSuffix(buildTarget, "-docker") { env, tagFlags := cmd.EnvAndTagFlags(target)
utils.Log.Debugf("build target is %v -> skipping installation", buildTarget)
return
}
var env, tagFlags = getEnvAndTagflags(buildTarget) if target == "sailfish" {
if buildTarget == "sailfish" {
env["GOARCH"] = "386" env["GOARCH"] = "386"
delete(env, "GOARM") delete(env, "GOARM")
var _, err = ioutil.ReadDir(filepath.Join(runtime.GOROOT(), "bin", "linux_386")) if _, err := ioutil.ReadDir(filepath.Join(runtime.GOROOT(), "bin", "linux_386")); err != nil {
if err != nil { build := exec.Command("go", "tool", "dist", "test", "-rebuild", "-run=no_tests")
var build = exec.Command("go", "tool", "dist", "test", "-rebuild", "-run=no_tests")
for key, value := range env { for key, value := range env {
build.Env = append(build.Env, fmt.Sprintf("%v=%v", key, value)) build.Env = append(build.Env, fmt.Sprintf("%v=%v", key, value))
} }
utils.RunCmd(build, "failed to setup linux go tools for sailfish") utils.RunCmd(build, "setup linux go tools for sailfish")
} }
} }
if utils.UseMsys2() && !utils.QT_STUB() { if target != "desktop" || strings.HasSuffix(target, "-docker") {
utils.Log.Infof("build target is %v with msys2 -> skipping installation of modules -> re-run setup with QT_STUB=true for code-autocompletion", buildTarget) utils.Log.Debugf("build target is %v; skipping installation of modules", target)
return return
} }
if buildTarget != "desktop" { var failed []string
utils.Log.Debugf("build target is %v -> skipping installation of modules", buildTarget)
return
}
utils.Log.Infof("starting to install modules (~%v5min)", func() string {
if !utils.QT_STUB() {
return "1"
}
return ""
}())
for _, module := range parser.GetLibs() { for _, module := range parser.GetLibs() {
if parser.ShouldBuild(module) { if !parser.ShouldBuildForTarget(module, target) {
utils.Log.Debug("skipping installation of %v for %v", module, target)
if !(buildTarget == "android" && (module == "DBus" || module == "WebEngine" || module == "PrintSupport" || module == "Designer" || (strings.HasSuffix(module, "Extras") && module != "AndroidExtras"))) && continue
!(strings.HasPrefix(buildTarget, "ios") && (module == "DBus" || module == "SerialPort" || module == "SerialBus" || module == "WebEngine" || module == "PrintSupport" || module == "Designer" || strings.HasSuffix(module, "Extras"))) && //TODO: support for PrintSupport
!(strings.HasPrefix(buildTarget, "rpi") && (module == "WebEngine" || module == "Designer" || strings.HasSuffix(module, "Extras"))) { //TODO: support for WebEngine (rpi2 + rpi3)
utils.Log.Infof("installing%v qt/%v", func() string {
if utils.QT_STUB() {
return " stub"
}
return " full"
}(), strings.ToLower(module))
utils.RunCmdOptional(installPkgCmd(buildTarget, tagFlags, fmt.Sprintf("github.com/therecipe/qt/%v", strings.ToLower(module)), env), fmt.Sprintf("install.%v", strings.ToLower(module)))
//also install armv7 modules
if buildTarget == "ios" {
var cmd = installPkgCmd(buildTarget, tagFlags, fmt.Sprintf("github.com/therecipe/qt/%v", strings.ToLower(module)), env)
cmd.Env = append(strings.Split(strings.Replace(strings.Replace(strings.Join(cmd.Env, "|"), "-arch arm64", "-arch armv7", -1), "arm64", "arm", -1), "|"), "GOARM=7")
utils.RunCmdOptional(cmd, fmt.Sprintf("install.%v", strings.ToLower(module)))
}
}
} }
mode := "full"
if utils.QT_STUB() {
mode = "stub"
}
utils.Log.Infof("installing %v qt/%v", mode, strings.ToLower(module))
cmd := exec.Command("go", "install", "-p", strconv.Itoa(runtime.GOMAXPROCS(0)), "-v")
if tagFlags != "" {
cmd.Args = append(cmd.Args, tagFlags)
}
if target != "desktop" {
cmd.Args = append(cmd.Args, []string{"-installsuffix", strings.Replace(target, "-", "_", -1)}...)
cmd.Args = append(cmd.Args, []string{"-pkgdir", filepath.Join(utils.MustGoPath(), "pkg", fmt.Sprintf("%v_%v_%v", env["GOOS"], env["GOARCH"], strings.Replace(target, "-", "_", -1)))}...)
}
cmd.Args = append(cmd.Args, fmt.Sprintf("github.com/therecipe/qt/%v", strings.ToLower(module)))
for key, value := range env {
cmd.Env = append(cmd.Env, fmt.Sprintf("%v=%v", key, value))
}
if _, err := utils.RunCmdOptionalError(cmd, fmt.Sprintf("install %v", strings.ToLower(module))); err != nil {
failed = append(failed, strings.ToLower(module))
}
}
if l := len(failed); l > 0 {
utils.Log.Errorf("failed to install the following %v package(s):", l)
for _, f := range failed {
utils.Log.Error(f)
}
utils.Log.Errorf("you may want to run 'qtsetup install %v' if you depend on these package(s)", target)
} }
} }
func installPkgCmd(buildTarget, tagFlags, pkg string, env map[string]string) *exec.Cmd {
var cmd = exec.Command("go", "install", "-p", strconv.Itoa(runtime.GOMAXPROCS(0)), "-v")
if tagFlags != "" {
cmd.Args = append(cmd.Args, tagFlags)
}
if buildTarget != "desktop" {
cmd.Args = append(cmd.Args, []string{"-installsuffix", strings.Replace(buildTarget, "-", "_", -1)}...)
cmd.Args = append(cmd.Args, []string{"-pkgdir", filepath.Join(utils.MustGoPath(), "pkg", fmt.Sprintf("%v_%v_%v", env["GOOS"], env["GOARCH"], strings.Replace(buildTarget, "-", "_", -1)))}...)
}
cmd.Args = append(cmd.Args, pkg)
for key, value := range env {
cmd.Env = append(cmd.Env, fmt.Sprintf("%v=%v", key, value))
}
return cmd
}
func getEnvAndTagflags(buildTarget string) (env map[string]string, tagFlags string) {
utils.CheckBuildTarget(buildTarget)
switch buildTarget {
case
"android":
{
tagFlags = fmt.Sprintf("-tags=\"%v\"", buildTarget)
switch runtime.GOOS {
case "darwin", "linux":
{
env = map[string]string{
"PATH": os.Getenv("PATH"),
"GOPATH": utils.MustGoPath(),
"GOROOT": runtime.GOROOT(),
"GOOS": "android",
"GOARCH": "arm",
"GOARM": "7",
"CGO_ENABLED": "1",
"CC": filepath.Join(utils.ANDROID_NDK_DIR(), "toolchains", "arm-linux-androideabi-4.9", "prebuilt", runtime.GOOS+"-x86_64", "bin", "arm-linux-androideabi-gcc"),
"CXX": filepath.Join(utils.ANDROID_NDK_DIR(), "toolchains", "arm-linux-androideabi-4.9", "prebuilt", runtime.GOOS+"-x86_64", "bin", "arm-linux-androideabi-g++"),
"CGO_CPPFLAGS": fmt.Sprintf("-isystem %v", filepath.Join(utils.ANDROID_NDK_DIR(), "platforms", "android-16", "arch-arm", "usr", "include")),
"CGO_LDFLAGS": fmt.Sprintf("--sysroot=%v -llog", filepath.Join(utils.ANDROID_NDK_DIR(), "platforms", "android-16", "arch-arm")),
}
}
case "windows":
{
env = map[string]string{
"PATH": os.Getenv("PATH"),
"GOPATH": utils.MustGoPath(),
"GOROOT": runtime.GOROOT(),
"TMP": os.Getenv("TMP"),
"TEMP": os.Getenv("TEMP"),
"GOOS": "android",
"GOARCH": "arm",
"GOARM": "7",
"CGO_ENABLED": "1",
"CC": filepath.Join(utils.ANDROID_NDK_DIR(), "toolchains", "arm-linux-androideabi-4.9", "prebuilt", runtime.GOOS+"-x86_64", "bin", "arm-linux-androideabi-gcc"),
"CXX": filepath.Join(utils.ANDROID_NDK_DIR(), "toolchains", "arm-linux-androideabi-4.9", "prebuilt", runtime.GOOS+"-x86_64", "bin", "arm-linux-androideabi-g++"),
"CGO_CPPFLAGS": fmt.Sprintf("-isystem %v", filepath.Join(utils.ANDROID_NDK_DIR(), "platforms", "android-16", "arch-arm", "usr", "include")),
"CGO_LDFLAGS": fmt.Sprintf("--sysroot=%v -llog", filepath.Join(utils.ANDROID_NDK_DIR(), "platforms", "android-16", "arch-arm")),
}
}
}
}
case
"ios", "ios-simulator":
{
tagFlags = "-tags=\"ios\""
var ClangDir, ClangPlatform, ClangFlag, ClangArch, GoArch = func() (string, string, string, string, string) {
if buildTarget == "ios" {
return "iPhoneOS", utils.IPHONEOS_SDK_DIR(), "iphoneos", "arm64", "arm64"
}
return "iPhoneSimulator", utils.IPHONESIMULATOR_SDK_DIR(), "ios-simulator", "x86_64", "amd64"
}()
env = map[string]string{
"PATH": os.Getenv("PATH"),
"GOPATH": utils.MustGoPath(),
"GOROOT": runtime.GOROOT(),
"GOOS": runtime.GOOS,
"GOARCH": GoArch,
"CGO_ENABLED": "1",
"CGO_CPPFLAGS": fmt.Sprintf("-isysroot %v/Contents/Developer/Platforms/%v.platform/Developer/SDKs/%v -m%v-version-min=7.0 -arch %v", utils.XCODE_DIR(), ClangDir, ClangPlatform, ClangFlag, ClangArch),
"CGO_LDFLAGS": fmt.Sprintf("-isysroot %v/Contents/Developer/Platforms/%v.platform/Developer/SDKs/%v -m%v-version-min=7.0 -arch %v", utils.XCODE_DIR(), ClangDir, ClangPlatform, ClangFlag, ClangArch),
}
}
case
"desktop":
{
if runtime.GOOS == "windows" {
env = map[string]string{
"PATH": os.Getenv("PATH"),
"GOPATH": utils.MustGoPath(),
"GOROOT": runtime.GOROOT(),
"TMP": os.Getenv("TMP"),
"TEMP": os.Getenv("TEMP"),
"GOOS": runtime.GOOS,
"GOARCH": "386",
"CGO_ENABLED": "1",
}
if utils.UseMsys2() {
env["GOARCH"] = utils.QT_MSYS2_ARCH()
}
}
}
case "sailfish", "sailfish-emulator":
{
tagFlags = fmt.Sprintf("-tags=\"%v\"", strings.Replace(buildTarget, "-", "_", -1))
env = map[string]string{
"PATH": os.Getenv("PATH"),
"GOPATH": utils.MustGoPath(),
"GOROOT": runtime.GOROOT(),
"GOOS": "linux",
"GOARCH": "386",
}
if runtime.GOOS == "windows" {
env["TMP"] = os.Getenv("TMP")
env["TEMP"] = os.Getenv("TEMP")
}
if buildTarget == "sailfish" {
env["GOARCH"] = "arm"
env["GOARM"] = "7"
}
}
case "rpi1", "rpi2", "rpi3":
{
if runtime.GOOS == "linux" {
tagFlags = fmt.Sprintf("-tags=\"%v\"", buildTarget)
env = map[string]string{
"PATH": os.Getenv("PATH"),
"GOPATH": utils.MustGoPath(),
"GOROOT": runtime.GOROOT(),
"GOOS": "linux",
"GOARCH": "arm",
"GOARM": "7",
"CGO_ENABLED": "1",
"CC": fmt.Sprintf("%v/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc", utils.RPI_TOOLS_DIR()),
"CXX": fmt.Sprintf("%v/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-g++", utils.RPI_TOOLS_DIR()),
}
if buildTarget == "rpi1" {
env["GOARM"] = "6"
}
} else {
utils.Log.Panicf("failed to install %v on %v", buildTarget, runtime.GOOS)
}
}
case "windows":
{
tagFlags = fmt.Sprintf("-tags=\"%v\"", buildTarget)
env = map[string]string{
"PATH": os.Getenv("PATH"),
"GOPATH": utils.MustGoPath(),
"GOROOT": runtime.GOROOT(),
"GOOS": "windows",
"GOARCH": utils.QT_MXE_ARCH(),
"CGO_ENABLED": "1",
"CC": utils.QT_MXE_BIN("gcc"),
"CXX": utils.QT_MXE_BIN("g++"),
}
}
default:
{
utils.Log.Panicf("failed to install %v on %v", buildTarget, runtime.GOOS)
}
}
return
}

View file

@ -6,42 +6,50 @@ import (
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings"
"github.com/therecipe/qt/internal/utils" "github.com/therecipe/qt/internal/utils"
) )
func prep() { func Prep() {
utils.Log.Info("running setup/prep") utils.Log.Info("running setup/prep")
if utils.UseMsys2() { errString := "failed to create %v symlink in your PATH (%v); please use %v instead"
utils.RemoveAll(filepath.Join(utils.QT_MSYS2_DIR(), "..", "usr", "bin", "go.exe")) sucString := "successfully created %v symlink in your PATH (%v)"
utils.RunCmdOptional(exec.Command("cmd", "/C", "mklink", "/H", filepath.Join(utils.QT_MSYS2_DIR(), "..", "usr", "bin", "go.exe"), filepath.Join(runtime.GOROOT(), "bin", "go.exe")), fmt.Sprintf("create go symlink in your QT_MSYS2_DIR/usr/bin (%v)", filepath.Join(utils.QT_MSYS2_DIR(), "..", "usr", "bin")))
}
for _, app := range []string{"qtdeploy", "qtmoc", "qtrcc", "qtminimal"} { for _, app := range []string{"qtrcc", "qtmoc", "qtminimal", "qtdeploy", "go"} {
switch runtime.GOOS { if app == "go" && !utils.QT_MSYS2() {
case "darwin", "linux": continue
{ }
if os.Geteuid() == 0 || runtime.GOOS == "darwin" {
utils.RemoveAll(fmt.Sprintf("/usr/local/bin/%v", app)) if runtime.GOOS == "windows" {
var err = os.Symlink(filepath.Join(utils.MustGoBin(), app), fmt.Sprintf("/usr/local/bin/%v", app)) sPath := filepath.Join(utils.MustGoBin(), fmt.Sprintf("%v.exe", app))
if err != nil { dPath := filepath.Join(runtime.GOROOT(), "bin", fmt.Sprintf("%v.exe", app))
utils.Log.WithError(err).Warnf("failed to create %v symlink in your PATH (/usr/local/bin) -> use %v instead", app, filepath.Join(utils.MustGoBin(), app)) if utils.QT_MSYS2() {
} if app == "go" {
} else { sPath = dPath
utils.Log.Warnf("(not root) failed to create %v symlink in your PATH (/usr/local/bin) -> use %v instead", app, filepath.Join(utils.MustGoBin(), app)) }
dPath = filepath.Join(utils.QT_MSYS2_DIR(), "..", "usr", "bin", fmt.Sprintf("%v.exe", app))
}
utils.RemoveAll(dPath)
utils.RunCmdOptional(exec.Command("cmd", "/C", "mklink", "/H", dPath, sPath), fmt.Sprintf(errString, app, dPath, sPath))
continue
} else {
var suc bool
sPath := filepath.Join(utils.MustGoBin(), app)
var dPath string
for _, pdPath := range strings.Split("/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:"+filepath.Join(filepath.Join(runtime.GOROOT(), "bin")), string(os.PathListSeparator)) {
dPath = filepath.Join(pdPath, app)
utils.RemoveAll(dPath)
if err := os.Symlink(sPath, dPath); err == nil {
suc = true
break
} }
} }
if suc {
case "windows": utils.Log.Infof(sucString, app, dPath)
{ } else {
if utils.UseMsys2() { utils.Log.Warnf(errString, app, dPath, sPath)
utils.RemoveAll(filepath.Join(utils.QT_MSYS2_DIR(), "..", "usr", "bin", fmt.Sprintf("%v.exe", app)))
utils.RunCmdOptional(exec.Command("cmd", "/C", "mklink", "/H", filepath.Join(utils.QT_MSYS2_DIR(), "..", "usr", "bin", fmt.Sprintf("%v.exe", app)), filepath.Join(utils.MustGoBin(), fmt.Sprintf("%v.exe", app))), fmt.Sprintf("create %v symlink in your PATH (GOROOT/bin) -> use %v instead", app, filepath.Join(utils.MustGoBin(), fmt.Sprintf("%v.exe", app))))
} else {
utils.RemoveAll(filepath.Join(runtime.GOROOT(), "bin", fmt.Sprintf("%v.exe", app)))
utils.RunCmdOptional(exec.Command("cmd", "/C", "mklink", "/H", filepath.Join(runtime.GOROOT(), "bin", fmt.Sprintf("%v.exe", app)), filepath.Join(utils.MustGoBin(), fmt.Sprintf("%v.exe", app))), fmt.Sprintf("create %v symlink in your PATH (GOROOT/bin) -> use %v instead", app, filepath.Join(utils.MustGoBin(), fmt.Sprintf("%v.exe", app))))
}
} }
} }
} }

View file

@ -3,31 +3,24 @@ package setup
func Setup(buildMode, buildTarget string) { func Setup(buildMode, buildTarget string) {
switch buildMode { switch buildMode {
case "full": case "full":
prep() Prep()
check(buildTarget) Check(buildTarget)
generate(buildTarget) Generate(buildTarget)
install(buildTarget) Install(buildTarget)
test(buildTarget) Test(buildTarget)
case "prep": case "prep":
prep() Prep()
case "check": case "check":
check(buildTarget) Check(buildTarget)
case "generate": case "generate":
generate(buildTarget) Generate(buildTarget)
case "install": case "install":
install(buildTarget) Install(buildTarget)
case "test": case "test":
test(buildTarget) Test(buildTarget)
case "update": case "update":
update() Update()
case "upgrade": case "upgrade":
upgrade() Upgrade()
} }
} }

View file

@ -9,44 +9,50 @@ import (
"strings" "strings"
"github.com/therecipe/qt/internal/cmd/deploy" "github.com/therecipe/qt/internal/cmd/deploy"
"github.com/therecipe/qt/internal/cmd/minimal"
"github.com/therecipe/qt/internal/cmd/moc"
"github.com/therecipe/qt/internal/utils" "github.com/therecipe/qt/internal/utils"
) )
func test(buildTarget string) { func Test(target string) {
//TODO: split qtmoc test for windows if utils.CI() {
if utils.IsCI() && runtime.GOOS != "windows" { if !(runtime.GOOS == "windows" || target == "windows") { //TODO: split test for windows ?
utils.Log.Infof("running setup/test CI (~2min)") utils.Log.Infof("running setup/test %v CI", target)
utils.RunCmd(exec.Command(filepath.Join(os.Getenv("GOPATH"), "bin", "qtmoc"), utils.GoQtPkgPath("internal", "cmd", "moc", "test")), "run qtmoc") path := utils.GoQtPkgPath("internal", "cmd", "moc", "test")
utils.RunCmd(exec.Command(filepath.Join(os.Getenv("GOPATH"), "bin", "qtminimal"), "desktop", utils.GoQtPkgPath("internal", "cmd", "moc", "test")), "run qtminimal")
var cmd = exec.Command("go", "test", "-v", "-tags=minimal") moc.QmakeMoc(path, target)
cmd.Dir = utils.GoQtPkgPath("internal", "cmd", "moc", "test") minimal.QmakeMinimal(path, target)
if runtime.GOOS == "windows" {
for key, value := range map[string]string{
"PATH": os.Getenv("PATH"),
"GOPATH": utils.MustGoPath(),
"GOROOT": runtime.GOROOT(),
"TMP": os.Getenv("TMP"), cmd := exec.Command("go", "test", "-v", "-tags=minimal")
"TEMP": os.Getenv("TEMP"), cmd.Dir = path
if runtime.GOOS == "windows" {
for key, value := range map[string]string{
"PATH": os.Getenv("PATH"),
"GOPATH": utils.MustGoPath(),
"GOROOT": runtime.GOROOT(),
"GOOS": runtime.GOOS, "TMP": os.Getenv("TMP"),
"GOARCH": "386", "TEMP": os.Getenv("TEMP"),
"CGO_ENABLED": "1", "GOOS": runtime.GOOS,
} { "GOARCH": "386",
cmd.Env = append(cmd.Env, fmt.Sprintf("%v=%v", key, value))
"CGO_ENABLED": "1",
} {
cmd.Env = append(cmd.Env, fmt.Sprintf("%v=%v", key, value))
}
} }
utils.RunCmd(cmd, "run qtmoc")
} }
utils.RunCmd(cmd, "run qtmoc")
} }
var buildMode = "test" mode := "test"
var examples map[string][]string var examples map[string][]string
if utils.IsCI() { if utils.CI() {
buildMode = "build" mode = "build"
examples = map[string][]string{ examples = map[string][]string{
"androidextras": []string{"jni", "notification"}, "androidextras": []string{"jni", "notification"},
@ -57,14 +63,14 @@ func test(buildTarget string) {
filepath.Join("threejs", "planets"), filepath.Join("threejs", "planets"),
}, },
"charts": []string{"audio"}, //"charts": []string{"audio"}, //TODO: ios, ios-simulator
//"grpc": []string{"hello_world","hello_world2"}, //"grpc": []string{"hello_world","hello_world2"},
"gui": []string{"analogclock", "rasterwindow"}, "gui": []string{"analogclock", "rasterwindow"},
"qml": []string{"application", "drawer_nav_x", "gallery", "material", "qml": []string{"application", "drawer_nav_x", "gallery", "material",
"prop", "prop2" /*, "webview"*/}, "prop", "prop2" /*"webview"*/},
"qt3d": []string{"audio-visualizer-qml"}, "qt3d": []string{"audio-visualizer-qml"},
@ -77,12 +83,12 @@ func test(buildTarget string) {
"uitools": []string{"calculator"}, "uitools": []string{"calculator"},
"widgets": []string{"bridge2" /*"dropsite",*/, "graphicsscene", "line_edits", "pixel_editor", "widgets": []string{"bridge2" /*"dropsite"*/, "graphicsscene", "line_edits", "pixel_editor",
/*"renderer",*/ "systray" /*"table",*/, "textedit", filepath.Join("treeview", "treeview_dual"), /*"renderer"*/ "systray" /*"table"*/, "textedit", filepath.Join("treeview", "treeview_dual"),
filepath.Join("treeview", "treeview_filelist"), "video_player"}, filepath.Join("treeview", "treeview_filelist"), "video_player" /*"webengine"*/},
} }
} else { } else {
if strings.HasPrefix(buildTarget, "sailfish") { if strings.HasPrefix(target, "sailfish") {
examples = map[string][]string{ examples = map[string][]string{
"quick": []string{"sailfish"}, "quick": []string{"sailfish"},
@ -99,21 +105,19 @@ func test(buildTarget string) {
} }
} }
utils.Log.Infof("running setup/test %v (~5min)", buildTarget) utils.Log.Infof("running setup/test %v", target)
for cat, list := range examples { for cat, list := range examples {
for _, example := range list { for _, example := range list {
if buildTarget != "desktop" && example == "textedit" { if target != "desktop" && example == "textedit" {
continue continue
} }
var example = filepath.Join(cat, example) example := filepath.Join(cat, example)
utils.Log.Infoln("testing", example) utils.Log.Infoln("testing", example)
deploy.Deploy(&deploy.State{ deploy.Deploy(&deploy.State{
BuildMode: buildMode, BuildMode: mode,
BuildTarget: strings.TrimSuffix(buildTarget, "-docker"), BuildTarget: strings.TrimSuffix(target, "-docker"),
AppPath: utils.GoQtPkgPath("internal", "examples", example), AppPath: utils.GoQtPkgPath("internal", "examples", example),
BuildDocker: strings.HasSuffix(buildTarget, "-docker"), BuildDocker: strings.HasSuffix(target, "-docker"),
}) })
} }
} }

View file

@ -8,45 +8,27 @@ import (
"github.com/therecipe/qt/internal/utils" "github.com/therecipe/qt/internal/utils"
) )
func fetch() { func Update() {
var fetch = exec.Command("git", "fetch", "--all")
fetch.Dir = filepath.Join(utils.MustGoPath(), "src", "github.com", "therecipe", "qt")
utils.RunCmd(fetch, "run \"git fetch\"")
}
func tooling() {
utils.RunCmd(exec.Command("go", "install", "-v", fmt.Sprintf("github.com/therecipe/qt/cmd/...")), "run \"go install\"")
}
func update() {
utils.RunCmd(exec.Command("go", "clean", "-i", "github.com/therecipe/qt/cmd/..."), "run \"go clean cmd\"") utils.RunCmd(exec.Command("go", "clean", "-i", "github.com/therecipe/qt/cmd/..."), "run \"go clean cmd\"")
utils.RunCmd(exec.Command("go", "clean", "-i", "github.com/therecipe/qt/internal/..."), "run \"go clean internal\"") utils.RunCmd(exec.Command("go", "clean", "-i", "github.com/therecipe/qt/internal/..."), "run \"go clean internal\"")
fetch() fetch := exec.Command("git", "fetch", "--all")
fetch.Dir = filepath.Join(utils.MustGoPath(), "src", "github.com", "therecipe", "qt")
utils.RunCmd(fetch, "run \"git fetch\"")
var checkoutCmd = exec.Command("git", "checkout", "--", utils.GoQtPkgPath("cmd")) checkoutCmd := exec.Command("git", "checkout", "--", utils.GoQtPkgPath("cmd"))
checkoutCmd.Dir = filepath.Join(utils.MustGoPath(), "src", "github.com", "therecipe", "qt") checkoutCmd.Dir = filepath.Join(utils.MustGoPath(), "src", "github.com", "therecipe", "qt")
utils.RunCmd(checkoutCmd, "run \"git checkout cmd\"") utils.RunCmd(checkoutCmd, "run \"git checkout cmd\"")
var checkoutInternal = exec.Command("git", "checkout", "--", utils.GoQtPkgPath("internal")) checkoutInternal := exec.Command("git", "checkout", "--", utils.GoQtPkgPath("internal"))
checkoutInternal.Dir = filepath.Join(utils.MustGoPath(), "src", "github.com", "therecipe", "qt") checkoutInternal.Dir = filepath.Join(utils.MustGoPath(), "src", "github.com", "therecipe", "qt")
utils.RunCmd(checkoutInternal, "run \"git checkout internal\"") utils.RunCmd(checkoutInternal, "run \"git checkout internal\"")
tooling() utils.RunCmd(exec.Command("go", "install", "-v", fmt.Sprintf("github.com/therecipe/qt/cmd/...")), "run \"go install\"")
} }
func upgrade() { func Upgrade() {
utils.RunCmd(exec.Command("go", "clean", "-i", "github.com/therecipe/qt/..."), "run \"go clean\"") utils.RunCmd(exec.Command("go", "clean", "-i", "github.com/therecipe/qt/..."), "run \"go clean\"")
utils.RemoveAll(utils.GoQtPkgPath())
fetch() utils.RunCmd(exec.Command("go", "get", "-v", fmt.Sprintf("github.com/therecipe/qt/cmd/...")), "run \"go get\"")
var clean = exec.Command("git", "clean", "--force")
clean.Dir = filepath.Join(utils.MustGoPath(), "src", "github.com", "therecipe", "qt")
utils.RunCmd(clean, "run \"git clean\"")
var reset = exec.Command("git", "reset", "--hard")
reset.Dir = filepath.Join(utils.MustGoPath(), "src", "github.com", "therecipe", "qt")
utils.RunCmd(reset, "run \"git reset\"")
tooling()
} }

View file

@ -0,0 +1,10 @@
FROM therecipe/qt:base
RUN echo "deb http://pkg.mxe.cc/repos/apt/debian jessie main" | tee --append /etc/apt/sources.list.d/mxeapt.list > /dev/null && apt-key adv --keyserver keyserver.ubuntu.com --recv-keys D43A795B73B16ABE9643FE1AFD8FFF16DB45C6AB && apt-get -qq update && apt-get -y -qq install mxe-i686-w64-mingw32.static-qt3d mxe-i686-w64-mingw32.static-qtactiveqt mxe-i686-w64-mingw32.static-qtbase mxe-i686-w64-mingw32.static-qtcanvas3d mxe-i686-w64-mingw32.static-qtcharts mxe-i686-w64-mingw32.static-qtconnectivity mxe-i686-w64-mingw32.static-qtdatavis3d mxe-i686-w64-mingw32.static-qtdeclarative mxe-i686-w64-mingw32.static-qtgamepad mxe-i686-w64-mingw32.static-qtgraphicaleffects mxe-i686-w64-mingw32.static-qtimageformats mxe-i686-w64-mingw32.static-qtlocation mxe-i686-w64-mingw32.static-qtmultimedia mxe-i686-w64-mingw32.static-qtofficeopenxml mxe-i686-w64-mingw32.static-qtpurchasing mxe-i686-w64-mingw32.static-qtquickcontrols mxe-i686-w64-mingw32.static-qtquickcontrols2 mxe-i686-w64-mingw32.static-qtscript mxe-i686-w64-mingw32.static-qtscxml mxe-i686-w64-mingw32.static-qtsensors mxe-i686-w64-mingw32.static-qtserialbus mxe-i686-w64-mingw32.static-qtserialport mxe-i686-w64-mingw32.static-qtservice mxe-i686-w64-mingw32.static-qtsvg mxe-i686-w64-mingw32.static-qtsystems mxe-i686-w64-mingw32.static-qttools mxe-i686-w64-mingw32.static-qttranslations mxe-i686-w64-mingw32.static-qtvirtualkeyboard mxe-i686-w64-mingw32.static-qtwebchannel mxe-i686-w64-mingw32.static-qtwebsockets mxe-i686-w64-mingw32.static-qtwinextras mxe-i686-w64-mingw32.static-qtxlsxwriter mxe-i686-w64-mingw32.static-qtxmlpatterns && apt-get -qq clean
ENV QT_MXE_ARCH 386
ENV QT_MXE_STATIC true
RUN $GOPATH/bin/qtsetup check windows
RUN $GOPATH/bin/qtsetup generate

View file

@ -0,0 +1,10 @@
FROM therecipe/qt:base
RUN echo "deb http://pkg.mxe.cc/repos/apt/debian jessie main" | tee --append /etc/apt/sources.list.d/mxeapt.list > /dev/null && apt-key adv --keyserver keyserver.ubuntu.com --recv-keys D43A795B73B16ABE9643FE1AFD8FFF16DB45C6AB && apt-get -qq update && apt-get -y -qq install mxe-x86-64-w64-mingw32.static-qt3d mxe-x86-64-w64-mingw32.static-qtactiveqt mxe-x86-64-w64-mingw32.static-qtbase mxe-x86-64-w64-mingw32.static-qtcanvas3d mxe-x86-64-w64-mingw32.static-qtcharts mxe-x86-64-w64-mingw32.static-qtconnectivity mxe-x86-64-w64-mingw32.static-qtdatavis3d mxe-x86-64-w64-mingw32.static-qtdeclarative mxe-x86-64-w64-mingw32.static-qtgamepad mxe-x86-64-w64-mingw32.static-qtgraphicaleffects mxe-x86-64-w64-mingw32.static-qtimageformats mxe-x86-64-w64-mingw32.static-qtlocation mxe-x86-64-w64-mingw32.static-qtmultimedia mxe-x86-64-w64-mingw32.static-qtofficeopenxml mxe-x86-64-w64-mingw32.static-qtpurchasing mxe-x86-64-w64-mingw32.static-qtquickcontrols mxe-x86-64-w64-mingw32.static-qtquickcontrols2 mxe-x86-64-w64-mingw32.static-qtscript mxe-x86-64-w64-mingw32.static-qtscxml mxe-x86-64-w64-mingw32.static-qtsensors mxe-x86-64-w64-mingw32.static-qtserialbus mxe-x86-64-w64-mingw32.static-qtserialport mxe-x86-64-w64-mingw32.static-qtservice mxe-x86-64-w64-mingw32.static-qtsvg mxe-x86-64-w64-mingw32.static-qtsystems mxe-x86-64-w64-mingw32.static-qttools mxe-x86-64-w64-mingw32.static-qttranslations mxe-x86-64-w64-mingw32.static-qtvirtualkeyboard mxe-x86-64-w64-mingw32.static-qtwebchannel mxe-x86-64-w64-mingw32.static-qtwebsockets mxe-x86-64-w64-mingw32.static-qtwinextras mxe-x86-64-w64-mingw32.static-qtxlsxwriter mxe-x86-64-w64-mingw32.static-qtxmlpatterns && apt-get -qq clean
ENV QT_MXE_ARCH amd64
ENV QT_MXE_STATIC true
RUN $GOPATH/bin/qtsetup check windows
RUN $GOPATH/bin/qtsetup generate

View file

@ -0,0 +1,52 @@
package main
import (
"os"
"github.com/therecipe/qt/core"
"github.com/therecipe/qt/webengine"
"github.com/therecipe/qt/widgets"
)
const htmlData = `<!DOCTYPE html>
<html>
<body>
<div id="div1">
<p id="p1">This is a paragraph.</p>
<p id="p2">This is another paragraph.</p>
</div>
</body>
</html>`
const jsData = `var para = document.createElement("p");
var node = document.createTextNode("This is new.");
para.appendChild(node);
var element = document.getElementById("div1");
element.appendChild(para);`
func main() {
widgets.NewQApplication(len(os.Args), os.Args)
var window = widgets.NewQMainWindow(nil, 0)
var centralWidget = widgets.NewQWidget(nil, 0)
centralWidget.SetLayout(widgets.NewQVBoxLayout())
var view = webengine.NewQWebEngineView(nil)
view.SetHtml(htmlData, core.NewQUrl())
centralWidget.Layout().AddWidget(view)
var button = widgets.NewQPushButton2("click me", nil)
button.ConnectClicked(func(checked bool) {
view.Page().RunJavaScript4(jsData)
})
centralWidget.Layout().AddWidget(button)
window.SetCentralWidget(centralWidget)
window.Show()
widgets.QApplication_Exec()
}

View file

@ -39,6 +39,9 @@ func ANDROID_SDK_DIR() string {
if dir := os.Getenv("ANDROID_SDK_DIR"); dir != "" { if dir := os.Getenv("ANDROID_SDK_DIR"); dir != "" {
return filepath.Clean(dir) return filepath.Clean(dir)
} }
if dir := os.Getenv("ANDROID_SDK_ROOT"); dir != "" {
return filepath.Clean(dir)
}
switch runtime.GOOS { switch runtime.GOOS {
case "windows": case "windows":
@ -62,6 +65,10 @@ func ANDROID_NDK_DIR() string {
if dir := os.Getenv("ANDROID_NDK_DIR"); dir != "" { if dir := os.Getenv("ANDROID_NDK_DIR"); dir != "" {
return filepath.Clean(dir) return filepath.Clean(dir)
} }
if dir := os.Getenv("ANDROID_NDK_ROOT"); dir != "" {
return filepath.Clean(dir)
}
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
return "C:\\android-ndk-r13b" return "C:\\android-ndk-r13b"
} }

View file

@ -55,17 +55,21 @@ func IPHONESIMULATOR_SDK_DIR() string {
return "" return ""
} }
func UseHomeBrew() bool { func QT_HOMEBREW() bool {
return strings.ToLower(os.Getenv("QT_HOMEBREW")) == "true" || IsHomeBrewQtDir() return useHomeBrew()
} }
func IsHomeBrewQtDir() bool { func useHomeBrew() bool {
return strings.ToLower(os.Getenv("QT_HOMEBREW")) == "true" || isHomeBrewQtDir()
}
func isHomeBrewQtDir() bool {
return ExistsFile(filepath.Join(QT_DIR(), "INSTALL_RECEIPT.json")) return ExistsFile(filepath.Join(QT_DIR(), "INSTALL_RECEIPT.json"))
} }
func QT_DARWIN_DIR() string { func QT_DARWIN_DIR() string {
if UseHomeBrew() { if useHomeBrew() {
if IsHomeBrewQtDir() { if isHomeBrewQtDir() {
return QT_DIR() return QT_DIR()
} }
return "/usr/local/opt/qt5" return "/usr/local/opt/qt5"

View file

@ -31,7 +31,7 @@ func QT_DIR() string {
} }
func QT_STUB() bool { func QT_STUB() bool {
return strings.ToLower(os.Getenv("QT_STUB")) == "true" || UseMsys2() return strings.ToLower(os.Getenv("QT_STUB")) == "true" || QT_MSYS2()
} }
func QT_DEBUG() bool { func QT_DEBUG() bool {
@ -48,11 +48,7 @@ func CheckBuildTarget(buildTarget string) {
switch buildTarget { switch buildTarget {
case "windows": case "windows":
{ {
if runtime.GOOS == "windows" && !buildDocker {
} else if runtime.GOOS == "linux" || buildDocker {
} else {
Log.Fatalf("%v is currently not supported as a deploy target on %v", buildTarget, runtime.GOOS)
}
} }
case "darwin", "ios", "ios-simulator": case "darwin", "ios", "ios-simulator":
@ -82,17 +78,17 @@ func CheckBuildTarget(buildTarget string) {
if buildTarget == "android" || strings.HasPrefix(buildTarget, "ios") { if buildTarget == "android" || strings.HasPrefix(buildTarget, "ios") {
switch { switch {
case UseMsys2(): case QT_MSYS2():
{ {
Log.Fatalf("%v is not supported as a deploy target on %v with MSYS2 -> install the official Qt version instead and try again", buildTarget, runtime.GOOS) Log.Fatalf("%v is not supported as a deploy target on %v with MSYS2 -> install the official Qt version instead and try again", buildTarget, runtime.GOOS)
} }
case UseHomeBrew(): case QT_HOMEBREW():
{ {
Log.Fatalf("%v is not supported as a deploy target on %v with HomeBrew -> install the official Qt version instead and try again", buildTarget, runtime.GOOS) Log.Fatalf("%v is not supported as a deploy target on %v with HomeBrew -> install the official Qt version instead and try again", buildTarget, runtime.GOOS)
} }
case UsePkgConfig(): case QT_PKG_CONFIG():
{ {
Log.Fatalf("%v is not supported as a deploy target on %v with PkgConfig -> install the official Qt version instead and try again", buildTarget, runtime.GOOS) Log.Fatalf("%v is not supported as a deploy target on %v with PkgConfig -> install the official Qt version instead and try again", buildTarget, runtime.GOOS)
} }
@ -100,7 +96,7 @@ func CheckBuildTarget(buildTarget string) {
} }
} }
func IsCI() bool { func CI() bool {
return strings.ToLower(os.Getenv("CI")) == "true" return strings.ToLower(os.Getenv("CI")) == "true"
} }
@ -121,7 +117,7 @@ func QT_DOCKER() bool {
func ToolPath(tool, target string) string { func ToolPath(tool, target string) string {
//TODO: only temporary //TODO: only temporary
if target == "desktop" { if target == "desktop" || target == "sailfish" || target == "sailfish-emulator" {
target = runtime.GOOS target = runtime.GOOS
} }
// //
@ -138,14 +134,14 @@ func ToolPath(tool, target string) string {
return filepath.Join(QT_DARWIN_DIR(), "bin", tool) return filepath.Join(QT_DARWIN_DIR(), "bin", tool)
case "windows": case "windows":
if runtime.GOOS == target { if runtime.GOOS == target {
if UseMsys2() { if QT_MSYS2() {
return filepath.Join(QT_MSYS2_DIR(), "bin", tool) return filepath.Join(QT_MSYS2_DIR(), "bin", tool)
} }
return filepath.Join(QT_DIR(), QT_VERSION_MAJOR(), "mingw53_32", "bin", tool) return filepath.Join(QT_DIR(), QT_VERSION_MAJOR(), "mingw53_32", "bin", tool)
} }
return filepath.Join(QT_MXE_DIR(), "usr", QT_MXE_TRIPLET(), "qt5", "bin", tool) return filepath.Join(QT_MXE_DIR(), "usr", QT_MXE_TRIPLET(), "qt5", "bin", tool)
case "linux": case "linux":
if UsePkgConfig() { if QT_PKG_CONFIG() {
if QT_QMAKE_CGO() { if QT_QMAKE_CGO() {
return filepath.Join(strings.TrimSpace(RunCmd(exec.Command("pkg-config", "--variable=host_bins", "Qt5Core"), "cgo.LinuxPkgConfig_hostBins")), tool) return filepath.Join(strings.TrimSpace(RunCmd(exec.Command("pkg-config", "--variable=host_bins", "Qt5Core"), "cgo.LinuxPkgConfig_hostBins")), tool)
} }
@ -156,10 +152,12 @@ func ToolPath(tool, target string) string {
return filepath.Join(QT_DIR(), QT_VERSION_MAJOR(), "ios", "bin", tool) return filepath.Join(QT_DIR(), QT_VERSION_MAJOR(), "ios", "bin", tool)
case "android": case "android":
return filepath.Join(QT_DIR(), QT_VERSION_MAJOR(), "android_armv7", "bin", tool) return filepath.Join(QT_DIR(), QT_VERSION_MAJOR(), "android_armv7", "bin", tool)
/*
case "sailfish": case "sailfish":
return filepath.Join(os.Getenv("HOME"), ".config", "SailfishOS-SDK", "mer-sdk-tools", "MerSDK", "SailfishOS-armv7hl", tool) return filepath.Join(os.Getenv("HOME"), ".config", "SailfishOS-SDK", "mer-sdk-tools", "MerSDK", "SailfishOS-armv7hl", tool)
case "sailfish-emulator": case "sailfish-emulator":
return filepath.Join(os.Getenv("HOME"), ".config", "SailfishOS-SDK", "mer-sdk-tools", "MerSDK", "SailfishOS-i486", tool) return filepath.Join(os.Getenv("HOME"), ".config", "SailfishOS-SDK", "mer-sdk-tools", "MerSDK", "SailfishOS-i486", tool)
*/
case "asteroid": case "asteroid":
case "rp1", "rpi2", "rpi3": case "rp1", "rpi2", "rpi3":
return filepath.Join(QT_DIR(), QT_VERSION_MAJOR(), target, "bin", tool) return filepath.Join(QT_DIR(), QT_VERSION_MAJOR(), target, "bin", tool)

View file

@ -8,7 +8,11 @@ import (
"strings" "strings"
) )
func UsePkgConfig() bool { func QT_PKG_CONFIG() bool {
return usePkgConfig()
}
func usePkgConfig() bool {
return strings.ToLower(os.Getenv("QT_PKG_CONFIG")) == "true" return strings.ToLower(os.Getenv("QT_PKG_CONFIG")) == "true"
} }
@ -17,7 +21,7 @@ func QT_DOC_DIR() string {
return filepath.Clean(dir) return filepath.Clean(dir)
} }
switch LinuxDistro() { switch QT_DISTRO() {
case "arch": case "arch":
{ {
return "/usr/share/doc/qt" return "/usr/share/doc/qt"
@ -51,7 +55,7 @@ func QT_MISC_DIR() string {
return filepath.Clean(dir) return filepath.Clean(dir)
} }
switch LinuxDistro() { switch QT_DISTRO() {
case "arch": case "arch":
return filepath.Join(strings.TrimSpace(RunCmd(exec.Command("pkg-config", "--variable=libdir", "Qt5Core"), "cgo.LinuxPkgConfig_libDir")), "qt") return filepath.Join(strings.TrimSpace(RunCmd(exec.Command("pkg-config", "--variable=libdir", "Qt5Core"), "cgo.LinuxPkgConfig_libDir")), "qt")
case "fedora", "suse", "ubuntu": case "fedora", "suse", "ubuntu":
@ -61,7 +65,10 @@ func QT_MISC_DIR() string {
return "" return ""
} }
func LinuxDistro() string { func QT_DISTRO() string {
if d, ok := os.LookupEnv("QT_DISTRO"); ok {
return d
}
if _, err := exec.LookPath("pacman"); err == nil { if _, err := exec.LookPath("pacman"); err == nil {
return "arch" return "arch"

View file

@ -11,18 +11,20 @@ func VIRTUALBOX_DIR() string {
if dir := os.Getenv("VIRTUALBOX_DIR"); dir != "" { if dir := os.Getenv("VIRTUALBOX_DIR"); dir != "" {
return filepath.Clean(dir) return filepath.Clean(dir)
} }
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
return "C:\\Program Files\\Oracle\\VirtualBox" return "C:\\Program Files\\Oracle\\VirtualBox"
} }
var path, err = exec.LookPath("vboxmanage") var path, err = exec.LookPath("vboxmanage")
if err != nil { if err != nil {
Log.WithError(err).Error("failed to find vboxmanage in your PATH") Log.WithError(err).Error("failed to find vboxmanage in your PATH")
} }
path = filepath.Dir(path)
path, err = Abs(filepath.Dir(path)) if !filepath.IsAbs(path) {
path, err = filepath.Abs(path)
if err != nil {
Log.WithError(err).WithField("path", path).Fatal("can't resolve absolute path")
}
}
return path return path
} }

View file

@ -40,6 +40,8 @@ func Save(name, data string) error {
var err = ioutil.WriteFile(name, []byte(data), 0777) var err = ioutil.WriteFile(name, []byte(data), 0777)
if err != nil { if err != nil {
Log.WithError(err).Panicf("failed to save %v", name) Log.WithError(err).Panicf("failed to save %v", name)
} else {
Log.Debugf("saved file len(%v) %v", len(data), name)
} }
return err return err
} }
@ -70,18 +72,11 @@ func LoadOptional(name string) string {
return string(out) return string(out)
} }
func Abs(appPath string) (string, error) {
var path, err = filepath.Abs(appPath)
if err != nil {
Log.WithError(err).Panicf("failed to get absolute path for %v", appPath)
}
return path, err
}
func GoQtPkgPath(s ...string) string { func GoQtPkgPath(s ...string) string {
return filepath.Join(MustGoPath(), "src", "github.com", "therecipe", "qt", filepath.Join(s...)) return filepath.Join(MustGoPath(), "src", "github.com", "therecipe", "qt", filepath.Join(s...))
} }
//TODO: export error
func RunCmd(cmd *exec.Cmd, name string) string { func RunCmd(cmd *exec.Cmd, name string) string {
fields := logrus.Fields{"func": "RunCmd", "name": name, "cmd": strings.Join(cmd.Args, " "), "env": strings.Join(cmd.Env, " ")} fields := logrus.Fields{"func": "RunCmd", "name": name, "cmd": strings.Join(cmd.Args, " "), "env": strings.Join(cmd.Env, " ")}
Log.WithFields(fields).Debug("Execute") Log.WithFields(fields).Debug("Execute")
@ -94,6 +89,7 @@ func RunCmd(cmd *exec.Cmd, name string) string {
return string(out) return string(out)
} }
//TODO: export error
func RunCmdOptional(cmd *exec.Cmd, name string) string { func RunCmdOptional(cmd *exec.Cmd, name string) string {
fields := logrus.Fields{"func": "RunCmdOptional", "name": name, "cmd": strings.Join(cmd.Args, " "), "env": strings.Join(cmd.Env, " ")} fields := logrus.Fields{"func": "RunCmdOptional", "name": name, "cmd": strings.Join(cmd.Args, " "), "env": strings.Join(cmd.Env, " ")}
Log.WithFields(fields).Debug("Execute") Log.WithFields(fields).Debug("Execute")
@ -104,3 +100,14 @@ func RunCmdOptional(cmd *exec.Cmd, name string) string {
} }
return string(out) return string(out)
} }
func RunCmdOptionalError(cmd *exec.Cmd, name string) (string, error) {
fields := logrus.Fields{"func": "RunCmdOptionalError", "name": name, "cmd": strings.Join(cmd.Args, " "), "env": strings.Join(cmd.Env, " ")}
Log.WithFields(fields).Debug("Execute")
var out, err = cmd.CombinedOutput()
if err != nil {
Log.WithError(err).WithFields(fields).Error("failed to run command")
println(string(out))
}
return string(out), err
}

View file

@ -8,8 +8,12 @@ import (
"strings" "strings"
) )
func UseMsys2() bool { func QT_MSYS2() bool {
return strings.ToLower(os.Getenv("QT_MSYS2")) == "true" || IsMsys2QtDir() || os.Getenv("MSYSTEM") != "" return useMsys2()
}
func useMsys2() bool {
return strings.ToLower(os.Getenv("QT_MSYS2")) == "true" || IsMsys2QtDir() || MSYSTEM() != ""
} }
func QT_MSYS2_DIR() string { func QT_MSYS2_DIR() string {
@ -20,14 +24,15 @@ func QT_MSYS2_DIR() string {
return filepath.Join(dir, "mingw32") return filepath.Join(dir, "mingw32")
} }
var prefix = "msys32" prefix := "msys32"
if runtime.GOARCH == "amd64" { if runtime.GOARCH == "amd64" {
prefix = "msys64" prefix = "msys64"
} }
suffix := "mingw32"
if QT_MSYS2_ARCH() == "amd64" { if QT_MSYS2_ARCH() == "amd64" {
return fmt.Sprintf("C:\\%v\\mingw64", prefix) suffix = "mingw64"
} }
return fmt.Sprintf("C:\\%v\\mingw32", prefix) return fmt.Sprintf("C:\\%v\\%v", prefix, suffix)
} }
func IsMsys2QtDir() bool { func IsMsys2QtDir() bool {
@ -35,8 +40,15 @@ func IsMsys2QtDir() bool {
} }
func QT_MSYS2_ARCH() string { func QT_MSYS2_ARCH() string {
if os.Getenv("MSYSTEM") == "MINGW64" { if v, ok := os.LookupEnv("QT_MSYS2_ARCH"); ok {
return v
}
if MSYSTEM() == "MINGW64" {
return "amd64" return "amd64"
} }
return "386" return "386"
} }
func MSYSTEM() string {
return os.Getenv("MSYSTEM")
}

View file

@ -1,65 +0,0 @@
// +build !minimal
#define protected public
#define private public
#include "opengl.h"
#include "_cgo_export.h"
#include <QGL>
int QGL_SingleBuffer_Type()
{
return QGL::SingleBuffer;
}
int QGL_NoDepthBuffer_Type()
{
return QGL::NoDepthBuffer;
}
int QGL_ColorIndex_Type()
{
return QGL::ColorIndex;
}
int QGL_NoAlphaChannel_Type()
{
return QGL::NoAlphaChannel;
}
int QGL_NoAccumBuffer_Type()
{
return QGL::NoAccumBuffer;
}
int QGL_NoStencilBuffer_Type()
{
return QGL::NoStencilBuffer;
}
int QGL_NoStereoBuffers_Type()
{
return QGL::NoStereoBuffers;
}
int QGL_IndirectRendering_Type()
{
return QGL::IndirectRendering;
}
int QGL_NoOverlay_Type()
{
return QGL::NoOverlay;
}
int QGL_NoSampleBuffers_Type()
{
return QGL::NoSampleBuffers;
}
int QGL_NoDeprecatedFunctions_Type()
{
return QGL::NoDeprecatedFunctions;
}

View file

@ -1,93 +0,0 @@
// +build !minimal
package opengl
//#include <stdint.h>
//#include <stdlib.h>
//#include <string.h>
//#include "opengl.h"
import "C"
import (
"unsafe"
)
func cGoUnpackString(s C.struct_QtOpenGL_PackedString) string {
if len := int(s.len); len == -1 {
return C.GoString(s.data)
}
return C.GoStringN(s.data, C.int(s.len))
}
type QGL struct {
ptr unsafe.Pointer
}
type QGL_ITF interface {
QGL_PTR() *QGL
}
func (ptr *QGL) QGL_PTR() *QGL {
return ptr
}
func (ptr *QGL) Pointer() unsafe.Pointer {
if ptr != nil {
return ptr.ptr
}
return nil
}
func (ptr *QGL) SetPointer(p unsafe.Pointer) {
if ptr != nil {
ptr.ptr = p
}
}
func PointerFromQGL(ptr QGL_ITF) unsafe.Pointer {
if ptr != nil {
return ptr.QGL_PTR().Pointer()
}
return nil
}
func NewQGLFromPointer(ptr unsafe.Pointer) *QGL {
var n = new(QGL)
n.SetPointer(ptr)
return n
}
func (ptr *QGL) DestroyQGL() {
if ptr != nil {
C.free(ptr.Pointer())
ptr.SetPointer(nil)
}
}
//go:generate stringer -type=QGL__FormatOption
//QGL::FormatOption
type QGL__FormatOption int64
var (
QGL__DoubleBuffer QGL__FormatOption = QGL__FormatOption(0x0001)
QGL__DepthBuffer QGL__FormatOption = QGL__FormatOption(0x0002)
QGL__Rgba QGL__FormatOption = QGL__FormatOption(0x0004)
QGL__AlphaChannel QGL__FormatOption = QGL__FormatOption(0x0008)
QGL__AccumBuffer QGL__FormatOption = QGL__FormatOption(0x0010)
QGL__StencilBuffer QGL__FormatOption = QGL__FormatOption(0x0020)
QGL__StereoBuffers QGL__FormatOption = QGL__FormatOption(0x0040)
QGL__DirectRendering QGL__FormatOption = QGL__FormatOption(0x0080)
QGL__HasOverlay QGL__FormatOption = QGL__FormatOption(0x0100)
QGL__SampleBuffers QGL__FormatOption = QGL__FormatOption(0x0200)
QGL__DeprecatedFunctions QGL__FormatOption = QGL__FormatOption(0x0400)
QGL__SingleBuffer QGL__FormatOption = QGL__FormatOption(C.QGL_SingleBuffer_Type())
QGL__NoDepthBuffer QGL__FormatOption = QGL__FormatOption(C.QGL_NoDepthBuffer_Type())
QGL__ColorIndex QGL__FormatOption = QGL__FormatOption(C.QGL_ColorIndex_Type())
QGL__NoAlphaChannel QGL__FormatOption = QGL__FormatOption(C.QGL_NoAlphaChannel_Type())
QGL__NoAccumBuffer QGL__FormatOption = QGL__FormatOption(C.QGL_NoAccumBuffer_Type())
QGL__NoStencilBuffer QGL__FormatOption = QGL__FormatOption(C.QGL_NoStencilBuffer_Type())
QGL__NoStereoBuffers QGL__FormatOption = QGL__FormatOption(C.QGL_NoStereoBuffers_Type())
QGL__IndirectRendering QGL__FormatOption = QGL__FormatOption(C.QGL_IndirectRendering_Type())
QGL__NoOverlay QGL__FormatOption = QGL__FormatOption(C.QGL_NoOverlay_Type())
QGL__NoSampleBuffers QGL__FormatOption = QGL__FormatOption(C.QGL_NoSampleBuffers_Type())
QGL__NoDeprecatedFunctions QGL__FormatOption = QGL__FormatOption(C.QGL_NoDeprecatedFunctions_Type())
)

View file

@ -1,32 +0,0 @@
// +build !minimal
#pragma once
#ifndef GO_QTOPENGL_H
#define GO_QTOPENGL_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct QtOpenGL_PackedString { char* data; long long len; };
struct QtOpenGL_PackedList { void* data; long long len; };
int QGL_SingleBuffer_Type();
int QGL_NoDepthBuffer_Type();
int QGL_ColorIndex_Type();
int QGL_NoAlphaChannel_Type();
int QGL_NoAccumBuffer_Type();
int QGL_NoStencilBuffer_Type();
int QGL_NoStereoBuffers_Type();
int QGL_IndirectRendering_Type();
int QGL_NoOverlay_Type();
int QGL_NoSampleBuffers_Type();
int QGL_NoDeprecatedFunctions_Type();
#ifdef __cplusplus
}
#endif
#endif