forked from go-qamel/qamel
/
deps-linux.go
160 lines (134 loc) · 3.81 KB
/
deps-linux.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package generator
import (
"bufio"
"bytes"
"fmt"
"os"
"os/exec"
fp "path/filepath"
"strings"
)
// copyLinuxPlugins copies Linux plugins to output directory
func copyLinuxPlugins(qtPluginsDir string, outputDir string) error {
dstPluginsDir := fp.Join(outputDir, "plugins")
plugins := []string{
"platforms/libqxcb.so",
"platforminputcontexts",
"imageformats",
"xcbglintegrations",
"iconengines/libqsvgicon.so"}
for _, plugin := range plugins {
srcPath := fp.Join(qtPluginsDir, plugin)
dstPath := fp.Join(dstPluginsDir, plugin)
if !fileDirExists(srcPath) {
continue
}
err := copyFileDir(srcPath, dstPath, nil)
if err != nil {
return err
}
}
return nil
}
// copyLinuxLibs copies Linux libraries to output directory
func copyLinuxLibs(qtLibsDir string, outputPath string) error {
// Get list of files to check.
// The first one is the output binary file
filesToCheck := []string{outputPath}
// The plugins and qml libraries (*.so) which copied before
// must be checked as well
outputDir := fp.Dir(outputPath)
fp.Walk(outputDir, func(path string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}
fileExt := fp.Ext(info.Name())
if strings.HasPrefix(fileExt, ".so") {
filesToCheck = append(filesToCheck, path)
}
return nil
})
// Get list of dependency of the files
mapDependencies := map[string]string{}
filesAlreadyChecked := map[string]struct{}{}
for {
// Keep checking until there are no file left
if len(filesToCheck) == 0 {
break
}
fileName := filesToCheck[0]
// If this file has been checked before, skip
if _, checked := filesAlreadyChecked[fileName]; checked {
filesToCheck = filesToCheck[1:]
continue
}
// Fetch dependencies using ldd
cmdLdd := exec.Command("ldd", fileName)
lddResult, err := cmdLdd.CombinedOutput()
if err != nil {
return fmt.Errorf("%v: %s", err, lddResult)
}
// Parse ldd results
// It will look like this: libname.so => /path/to/lib (memory address)
buffer := bytes.NewBuffer(lddResult)
scanner := bufio.NewScanner(buffer)
for scanner.Scan() {
lib := strings.TrimSpace(scanner.Text())
libName := strings.SplitN(lib, " ", 2)[0]
libName = fp.Base(libName)
if libName == "" {
continue
}
libPath := fp.Join(qtLibsDir, libName)
if !fileExists(libPath) {
continue
}
filesToCheck = append(filesToCheck, libPath)
mapDependencies[libName] = libPath
}
// Save this files as been already checked, then move to next
filesAlreadyChecked[fileName] = struct{}{}
filesToCheck = filesToCheck[1:]
}
// Copy all dependency libs to output dir
var err error
dstLibsDir := fp.Join(outputDir, "libs")
for libName, libPath := range mapDependencies {
err = copyFile(libPath, fp.Join(dstLibsDir, libName))
if err != nil {
return err
}
}
return nil
}
// createLinuxScripts creates wrapper script to run the executable
func createLinuxScript(outputPath string) error {
// Prepare content of the script
scriptContent := "" +
"#!/bin/bash\n" +
"appname=`basename $0 | sed s,\\.sh$,,`\n\n" +
"dirname=`dirname $0`\n" +
"tmp=\"${dirname#?}\"\n\n" +
"if [ \"${dirname%$tmp}\" != \"/\" ]; then\n" +
"dirname=$PWD/$dirname\n" +
"fi\n" +
"export LD_LIBRARY_PATH=\"$dirname/libs\"\n" +
"export QT_PLUGIN_PATH=\"$dirname/plugins\"\n" +
"export QML_IMPORT_PATH=\"$dirname/qml\"\n" +
"export QML2_IMPORT_PATH=\"$dirname/qml\"\n" +
"$dirname/$appname \"$@\"\n"
// Write script to file. If it already exists, remove it.
scriptPath := strings.TrimSuffix(outputPath, fp.Ext(outputPath))
scriptPath += ".sh"
os.Remove(scriptPath)
dstFile, err := os.OpenFile(scriptPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777)
if err != nil {
return err
}
defer dstFile.Close()
_, err = dstFile.WriteString(scriptContent)
if err != nil {
return err
}
return dstFile.Sync()
}