@dry-software/cmake-js 7.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +402 -0
- package/bin/cmake-js +343 -0
- package/changelog.md +225 -0
- package/lib/appCMakeJSConfig.js +58 -0
- package/lib/buildSystem.js +123 -0
- package/lib/cMake.js +362 -0
- package/lib/cmLog.js +61 -0
- package/lib/cpp/win_delay_load_hook.cc +52 -0
- package/lib/dist.js +176 -0
- package/lib/downloader.js +92 -0
- package/lib/environment.js +97 -0
- package/lib/import/Find-VisualStudio.cs +250 -0
- package/lib/import/LICENSE +24 -0
- package/lib/import/README +6 -0
- package/lib/import/find-visualstudio.js +439 -0
- package/lib/import/util.js +70 -0
- package/lib/index.js +12 -0
- package/lib/locateNAN.js +63 -0
- package/lib/locateNodeApi.js +18 -0
- package/lib/npmConfig.js +31 -0
- package/lib/processHelpers.js +53 -0
- package/lib/runtimePaths.js +95 -0
- package/lib/targetOptions.js +33 -0
- package/lib/toolset.js +224 -0
- package/package.json +76 -0
package/lib/dist.js
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
const environment = require('./environment')
|
|
3
|
+
const path = require('path')
|
|
4
|
+
const urljoin = require('url-join')
|
|
5
|
+
const fs = require('fs-extra')
|
|
6
|
+
const CMLog = require('./cmLog')
|
|
7
|
+
const TargetOptions = require('./targetOptions')
|
|
8
|
+
const runtimePaths = require('./runtimePaths')
|
|
9
|
+
const Downloader = require('./downloader')
|
|
10
|
+
const os = require('os')
|
|
11
|
+
|
|
12
|
+
function testSum(sums, sum, fPath) {
|
|
13
|
+
const serverSum = sums.find(function (s) {
|
|
14
|
+
return s.getPath === fPath
|
|
15
|
+
})
|
|
16
|
+
if (serverSum && serverSum.sum === sum) {
|
|
17
|
+
return
|
|
18
|
+
}
|
|
19
|
+
throw new Error("SHA sum of file '" + fPath + "' mismatch!")
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
class Dist {
|
|
23
|
+
get internalPath() {
|
|
24
|
+
const cacheDirectory = '.cmake-js'
|
|
25
|
+
const runtimeArchDirectory = this.targetOptions.runtime + '-' + this.targetOptions.arch
|
|
26
|
+
const runtimeVersionDirectory = 'v' + this.targetOptions.runtimeVersion
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
this.options.runtimeDirectory ||
|
|
30
|
+
path.join(os.homedir(), cacheDirectory, runtimeArchDirectory, runtimeVersionDirectory)
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
get externalPath() {
|
|
34
|
+
return runtimePaths.get(this.targetOptions).externalPath
|
|
35
|
+
}
|
|
36
|
+
get downloaded() {
|
|
37
|
+
let headers = false
|
|
38
|
+
let libs = true
|
|
39
|
+
let stat = getStat(this.internalPath)
|
|
40
|
+
if (stat.isDirectory()) {
|
|
41
|
+
if (this.headerOnly) {
|
|
42
|
+
stat = getStat(path.join(this.internalPath, 'include/node/node.h'))
|
|
43
|
+
headers = stat.isFile()
|
|
44
|
+
} else {
|
|
45
|
+
stat = getStat(path.join(this.internalPath, 'src/node.h'))
|
|
46
|
+
if (stat.isFile()) {
|
|
47
|
+
stat = getStat(path.join(this.internalPath, 'deps/v8/include/v8.h'))
|
|
48
|
+
headers = stat.isFile()
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (environment.isWin) {
|
|
52
|
+
for (const libPath of this.winLibs) {
|
|
53
|
+
stat = getStat(libPath)
|
|
54
|
+
libs = libs && stat.isFile()
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return headers && libs
|
|
59
|
+
|
|
60
|
+
function getStat(path) {
|
|
61
|
+
try {
|
|
62
|
+
return fs.statSync(path)
|
|
63
|
+
} catch (e) {
|
|
64
|
+
return {
|
|
65
|
+
isFile: () => false,
|
|
66
|
+
isDirectory: () => false,
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
get winLibs() {
|
|
72
|
+
const libs = runtimePaths.get(this.targetOptions).winLibs
|
|
73
|
+
const result = []
|
|
74
|
+
for (const lib of libs) {
|
|
75
|
+
result.push(path.join(this.internalPath, lib.dir, lib.name))
|
|
76
|
+
}
|
|
77
|
+
return result
|
|
78
|
+
}
|
|
79
|
+
get headerOnly() {
|
|
80
|
+
return runtimePaths.get(this.targetOptions).headerOnly
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
constructor(options) {
|
|
84
|
+
this.options = options || {}
|
|
85
|
+
this.log = new CMLog(this.options)
|
|
86
|
+
this.targetOptions = new TargetOptions(this.options)
|
|
87
|
+
this.downloader = new Downloader(this.options)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async ensureDownloaded() {
|
|
91
|
+
if (!this.downloaded) {
|
|
92
|
+
await this.download()
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async download() {
|
|
96
|
+
const log = this.log
|
|
97
|
+
log.info('DIST', 'Downloading distribution files to: ' + this.internalPath)
|
|
98
|
+
await fs.ensureDir(this.internalPath)
|
|
99
|
+
const sums = await this._downloadShaSums()
|
|
100
|
+
await Promise.all([this._downloadLibs(sums), this._downloadTar(sums)])
|
|
101
|
+
}
|
|
102
|
+
async _downloadShaSums() {
|
|
103
|
+
if (this.targetOptions.runtime === 'node') {
|
|
104
|
+
const sumUrl = urljoin(this.externalPath, 'SHASUMS256.txt')
|
|
105
|
+
const log = this.log
|
|
106
|
+
log.http('DIST', '\t- ' + sumUrl)
|
|
107
|
+
return (await this.downloader.downloadString(sumUrl))
|
|
108
|
+
.split('\n')
|
|
109
|
+
.map(function (line) {
|
|
110
|
+
const parts = line.split(/\s+/)
|
|
111
|
+
return {
|
|
112
|
+
getPath: parts[1],
|
|
113
|
+
sum: parts[0],
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
.filter(function (i) {
|
|
117
|
+
return i.getPath && i.sum
|
|
118
|
+
})
|
|
119
|
+
} else {
|
|
120
|
+
return null
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async _downloadTar(sums) {
|
|
124
|
+
const log = this.log
|
|
125
|
+
const self = this
|
|
126
|
+
const tarLocalPath = runtimePaths.get(self.targetOptions).tarPath
|
|
127
|
+
const tarUrl = urljoin(self.externalPath, tarLocalPath)
|
|
128
|
+
log.http('DIST', '\t- ' + tarUrl)
|
|
129
|
+
|
|
130
|
+
const sum = await this.downloader.downloadTgz(tarUrl, {
|
|
131
|
+
hash: sums ? 'sha256' : null,
|
|
132
|
+
cwd: self.internalPath,
|
|
133
|
+
strip: 1,
|
|
134
|
+
filter: function (entryPath) {
|
|
135
|
+
if (entryPath === self.internalPath) {
|
|
136
|
+
return true
|
|
137
|
+
}
|
|
138
|
+
const ext = path.extname(entryPath)
|
|
139
|
+
return ext && ext.toLowerCase() === '.h'
|
|
140
|
+
},
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
if (sums) {
|
|
144
|
+
testSum(sums, sum, tarLocalPath)
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
async _downloadLibs(sums) {
|
|
148
|
+
const log = this.log
|
|
149
|
+
const self = this
|
|
150
|
+
if (!environment.isWin) {
|
|
151
|
+
return
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const paths = runtimePaths.get(self.targetOptions)
|
|
155
|
+
for (const dirs of paths.winLibs) {
|
|
156
|
+
const subDir = dirs.dir
|
|
157
|
+
const fn = dirs.name
|
|
158
|
+
const fPath = subDir ? urljoin(subDir, fn) : fn
|
|
159
|
+
const libUrl = urljoin(self.externalPath, fPath)
|
|
160
|
+
log.http('DIST', '\t- ' + libUrl)
|
|
161
|
+
|
|
162
|
+
await fs.ensureDir(path.join(self.internalPath, subDir))
|
|
163
|
+
|
|
164
|
+
const sum = await this.downloader.downloadFile(libUrl, {
|
|
165
|
+
path: path.join(self.internalPath, fPath),
|
|
166
|
+
hash: sums ? 'sha256' : null,
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
if (sums) {
|
|
170
|
+
testSum(sums, sum, fPath)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
module.exports = Dist
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
const crypto = require('crypto')
|
|
3
|
+
const axios = require('axios')
|
|
4
|
+
const MemoryStream = require('memory-stream')
|
|
5
|
+
const zlib = require('zlib')
|
|
6
|
+
const tar = require('tar')
|
|
7
|
+
const fs = require('fs')
|
|
8
|
+
const CMLog = require('./cmLog')
|
|
9
|
+
|
|
10
|
+
class Downloader {
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.options = options || {}
|
|
13
|
+
this.log = new CMLog(this.options)
|
|
14
|
+
}
|
|
15
|
+
downloadToStream(url, stream, hash) {
|
|
16
|
+
const self = this
|
|
17
|
+
const shasum = hash ? crypto.createHash(hash) : null
|
|
18
|
+
return new Promise(function (resolve, reject) {
|
|
19
|
+
let length = 0
|
|
20
|
+
let done = 0
|
|
21
|
+
let lastPercent = 0
|
|
22
|
+
axios
|
|
23
|
+
.get(url, { responseType: 'stream' })
|
|
24
|
+
.then(function (response) {
|
|
25
|
+
length = parseInt(response.headers['content-length'])
|
|
26
|
+
if (typeof length !== 'number') {
|
|
27
|
+
length = 0
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
response.data.on('data', function (chunk) {
|
|
31
|
+
if (shasum) {
|
|
32
|
+
shasum.update(chunk)
|
|
33
|
+
}
|
|
34
|
+
if (length) {
|
|
35
|
+
done += chunk.length
|
|
36
|
+
let percent = (done / length) * 100
|
|
37
|
+
percent = Math.round(percent / 10) * 10 + 10
|
|
38
|
+
if (percent > lastPercent) {
|
|
39
|
+
self.log.verbose('DWNL', '\t' + lastPercent + '%')
|
|
40
|
+
lastPercent = percent
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
response.data.pipe(stream)
|
|
46
|
+
})
|
|
47
|
+
.catch(function (err) {
|
|
48
|
+
reject(err)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
stream.once('error', function (err) {
|
|
52
|
+
reject(err)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
stream.once('finish', function () {
|
|
56
|
+
resolve(shasum ? shasum.digest('hex') : undefined)
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
}
|
|
60
|
+
async downloadString(url) {
|
|
61
|
+
const result = new MemoryStream()
|
|
62
|
+
await this.downloadToStream(url, result)
|
|
63
|
+
return result.toString()
|
|
64
|
+
}
|
|
65
|
+
async downloadFile(url, options) {
|
|
66
|
+
if (typeof options === 'string') {
|
|
67
|
+
options.path = options
|
|
68
|
+
}
|
|
69
|
+
const result = fs.createWriteStream(options.path)
|
|
70
|
+
const sum = await this.downloadToStream(url, result, options.hash)
|
|
71
|
+
this.testSum(url, sum, options)
|
|
72
|
+
return sum
|
|
73
|
+
}
|
|
74
|
+
async downloadTgz(url, options) {
|
|
75
|
+
if (typeof options === 'string') {
|
|
76
|
+
options.cwd = options
|
|
77
|
+
}
|
|
78
|
+
const gunzip = zlib.createGunzip()
|
|
79
|
+
const extractor = tar.extract(options)
|
|
80
|
+
gunzip.pipe(extractor)
|
|
81
|
+
const sum = await this.downloadToStream(url, gunzip, options.hash)
|
|
82
|
+
this.testSum(url, sum, options)
|
|
83
|
+
return sum
|
|
84
|
+
}
|
|
85
|
+
testSum(url, sum, options) {
|
|
86
|
+
if (options.hash && sum && options.sum && options.sum !== sum) {
|
|
87
|
+
throw new Error(options.hash.toUpperCase() + " sum of download '" + url + "' mismatch!")
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
module.exports = Downloader
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
const os = require('os')
|
|
3
|
+
const which = require('which')
|
|
4
|
+
|
|
5
|
+
const environment = (module.exports = {
|
|
6
|
+
cmakeJsVersion: require('../package.json').version,
|
|
7
|
+
platform: os.platform(),
|
|
8
|
+
isWin: os.platform() === 'win32',
|
|
9
|
+
isLinux: os.platform() === 'linux',
|
|
10
|
+
isOSX: os.platform() === 'darwin',
|
|
11
|
+
arch: os.arch(),
|
|
12
|
+
isX86: os.arch() === 'ia32' || os.arch() === 'x86',
|
|
13
|
+
isX64: os.arch() === 'x64',
|
|
14
|
+
isArm: os.arch() === 'arm',
|
|
15
|
+
isArm64: os.arch() === 'arm64',
|
|
16
|
+
runtime: 'node',
|
|
17
|
+
runtimeVersion: process.versions.node,
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
Object.defineProperties(environment, {
|
|
21
|
+
_isNinjaAvailable: {
|
|
22
|
+
value: null,
|
|
23
|
+
writable: true,
|
|
24
|
+
},
|
|
25
|
+
isNinjaAvailable: {
|
|
26
|
+
get: function () {
|
|
27
|
+
if (this._isNinjaAvailable === null) {
|
|
28
|
+
this._isNinjaAvailable = false
|
|
29
|
+
try {
|
|
30
|
+
if (which.sync('ninja')) {
|
|
31
|
+
this._isNinjaAvailable = true
|
|
32
|
+
}
|
|
33
|
+
} catch (e) {
|
|
34
|
+
// Ignore
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return this._isNinjaAvailable
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
_isMakeAvailable: {
|
|
41
|
+
value: null,
|
|
42
|
+
writable: true,
|
|
43
|
+
},
|
|
44
|
+
isMakeAvailable: {
|
|
45
|
+
get: function () {
|
|
46
|
+
if (this._isMakeAvailable === null) {
|
|
47
|
+
this._isMakeAvailable = false
|
|
48
|
+
try {
|
|
49
|
+
if (which.sync('make')) {
|
|
50
|
+
this._isMakeAvailable = true
|
|
51
|
+
}
|
|
52
|
+
} catch (e) {
|
|
53
|
+
// Ignore
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return this._isMakeAvailable
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
_isGPPAvailable: {
|
|
60
|
+
value: null,
|
|
61
|
+
writable: true,
|
|
62
|
+
},
|
|
63
|
+
isGPPAvailable: {
|
|
64
|
+
get: function () {
|
|
65
|
+
if (this._isGPPAvailable === null) {
|
|
66
|
+
this._isGPPAvailable = false
|
|
67
|
+
try {
|
|
68
|
+
if (which.sync('g++')) {
|
|
69
|
+
this._isGPPAvailable = true
|
|
70
|
+
}
|
|
71
|
+
} catch (e) {
|
|
72
|
+
// Ignore
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return this._isGPPAvailable
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
_isClangAvailable: {
|
|
79
|
+
value: null,
|
|
80
|
+
writable: true,
|
|
81
|
+
},
|
|
82
|
+
isClangAvailable: {
|
|
83
|
+
get: function () {
|
|
84
|
+
if (this._isClangAvailable === null) {
|
|
85
|
+
this._isClangAvailable = false
|
|
86
|
+
try {
|
|
87
|
+
if (which.sync('clang++')) {
|
|
88
|
+
this._isClangAvailable = true
|
|
89
|
+
}
|
|
90
|
+
} catch (e) {
|
|
91
|
+
// Ignore
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return this._isClangAvailable
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
})
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
// Copyright 2017 - Refael Ackermann
|
|
2
|
+
// Distributed under MIT style license
|
|
3
|
+
// See accompanying file LICENSE at https://github.com/node4good/windows-autoconf
|
|
4
|
+
|
|
5
|
+
// Usage:
|
|
6
|
+
// powershell -ExecutionPolicy Unrestricted -Command "Add-Type -Path Find-VisualStudio.cs; [VisualStudioConfiguration.Main]::PrintJson()"
|
|
7
|
+
// This script needs to be compatible with PowerShell v2 to run on Windows 2008R2 and Windows 7.
|
|
8
|
+
|
|
9
|
+
using System;
|
|
10
|
+
using System.Text;
|
|
11
|
+
using System.Runtime.InteropServices;
|
|
12
|
+
using System.Collections.Generic;
|
|
13
|
+
|
|
14
|
+
namespace VisualStudioConfiguration
|
|
15
|
+
{
|
|
16
|
+
[Flags]
|
|
17
|
+
public enum InstanceState : uint
|
|
18
|
+
{
|
|
19
|
+
None = 0,
|
|
20
|
+
Local = 1,
|
|
21
|
+
Registered = 2,
|
|
22
|
+
NoRebootRequired = 4,
|
|
23
|
+
NoErrors = 8,
|
|
24
|
+
Complete = 4294967295,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
[Guid("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")]
|
|
28
|
+
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
29
|
+
[ComImport]
|
|
30
|
+
public interface IEnumSetupInstances
|
|
31
|
+
{
|
|
32
|
+
|
|
33
|
+
void Next([MarshalAs(UnmanagedType.U4), In] int celt,
|
|
34
|
+
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface), Out] ISetupInstance[] rgelt,
|
|
35
|
+
[MarshalAs(UnmanagedType.U4)] out int pceltFetched);
|
|
36
|
+
|
|
37
|
+
void Skip([MarshalAs(UnmanagedType.U4), In] int celt);
|
|
38
|
+
|
|
39
|
+
void Reset();
|
|
40
|
+
|
|
41
|
+
[return: MarshalAs(UnmanagedType.Interface)]
|
|
42
|
+
IEnumSetupInstances Clone();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
[Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")]
|
|
46
|
+
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
47
|
+
[ComImport]
|
|
48
|
+
public interface ISetupConfiguration
|
|
49
|
+
{
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
[Guid("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")]
|
|
53
|
+
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
54
|
+
[ComImport]
|
|
55
|
+
public interface ISetupConfiguration2 : ISetupConfiguration
|
|
56
|
+
{
|
|
57
|
+
|
|
58
|
+
[return: MarshalAs(UnmanagedType.Interface)]
|
|
59
|
+
IEnumSetupInstances EnumInstances();
|
|
60
|
+
|
|
61
|
+
[return: MarshalAs(UnmanagedType.Interface)]
|
|
62
|
+
ISetupInstance GetInstanceForCurrentProcess();
|
|
63
|
+
|
|
64
|
+
[return: MarshalAs(UnmanagedType.Interface)]
|
|
65
|
+
ISetupInstance GetInstanceForPath([MarshalAs(UnmanagedType.LPWStr), In] string path);
|
|
66
|
+
|
|
67
|
+
[return: MarshalAs(UnmanagedType.Interface)]
|
|
68
|
+
IEnumSetupInstances EnumAllInstances();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
[Guid("B41463C3-8866-43B5-BC33-2B0676F7F42E")]
|
|
72
|
+
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
73
|
+
[ComImport]
|
|
74
|
+
public interface ISetupInstance
|
|
75
|
+
{
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
[Guid("89143C9A-05AF-49B0-B717-72E218A2185C")]
|
|
79
|
+
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
80
|
+
[ComImport]
|
|
81
|
+
public interface ISetupInstance2 : ISetupInstance
|
|
82
|
+
{
|
|
83
|
+
[return: MarshalAs(UnmanagedType.BStr)]
|
|
84
|
+
string GetInstanceId();
|
|
85
|
+
|
|
86
|
+
[return: MarshalAs(UnmanagedType.Struct)]
|
|
87
|
+
System.Runtime.InteropServices.ComTypes.FILETIME GetInstallDate();
|
|
88
|
+
|
|
89
|
+
[return: MarshalAs(UnmanagedType.BStr)]
|
|
90
|
+
string GetInstallationName();
|
|
91
|
+
|
|
92
|
+
[return: MarshalAs(UnmanagedType.BStr)]
|
|
93
|
+
string GetInstallationPath();
|
|
94
|
+
|
|
95
|
+
[return: MarshalAs(UnmanagedType.BStr)]
|
|
96
|
+
string GetInstallationVersion();
|
|
97
|
+
|
|
98
|
+
[return: MarshalAs(UnmanagedType.BStr)]
|
|
99
|
+
string GetDisplayName([MarshalAs(UnmanagedType.U4), In] int lcid);
|
|
100
|
+
|
|
101
|
+
[return: MarshalAs(UnmanagedType.BStr)]
|
|
102
|
+
string GetDescription([MarshalAs(UnmanagedType.U4), In] int lcid);
|
|
103
|
+
|
|
104
|
+
[return: MarshalAs(UnmanagedType.BStr)]
|
|
105
|
+
string ResolvePath([MarshalAs(UnmanagedType.LPWStr), In] string pwszRelativePath);
|
|
106
|
+
|
|
107
|
+
[return: MarshalAs(UnmanagedType.U4)]
|
|
108
|
+
InstanceState GetState();
|
|
109
|
+
|
|
110
|
+
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)]
|
|
111
|
+
ISetupPackageReference[] GetPackages();
|
|
112
|
+
|
|
113
|
+
ISetupPackageReference GetProduct();
|
|
114
|
+
|
|
115
|
+
[return: MarshalAs(UnmanagedType.BStr)]
|
|
116
|
+
string GetProductPath();
|
|
117
|
+
|
|
118
|
+
[return: MarshalAs(UnmanagedType.VariantBool)]
|
|
119
|
+
bool IsLaunchable();
|
|
120
|
+
|
|
121
|
+
[return: MarshalAs(UnmanagedType.VariantBool)]
|
|
122
|
+
bool IsComplete();
|
|
123
|
+
|
|
124
|
+
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)]
|
|
125
|
+
ISetupPropertyStore GetProperties();
|
|
126
|
+
|
|
127
|
+
[return: MarshalAs(UnmanagedType.BStr)]
|
|
128
|
+
string GetEnginePath();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
[Guid("DA8D8A16-B2B6-4487-A2F1-594CCCCD6BF5")]
|
|
132
|
+
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
133
|
+
[ComImport]
|
|
134
|
+
public interface ISetupPackageReference
|
|
135
|
+
{
|
|
136
|
+
|
|
137
|
+
[return: MarshalAs(UnmanagedType.BStr)]
|
|
138
|
+
string GetId();
|
|
139
|
+
|
|
140
|
+
[return: MarshalAs(UnmanagedType.BStr)]
|
|
141
|
+
string GetVersion();
|
|
142
|
+
|
|
143
|
+
[return: MarshalAs(UnmanagedType.BStr)]
|
|
144
|
+
string GetChip();
|
|
145
|
+
|
|
146
|
+
[return: MarshalAs(UnmanagedType.BStr)]
|
|
147
|
+
string GetLanguage();
|
|
148
|
+
|
|
149
|
+
[return: MarshalAs(UnmanagedType.BStr)]
|
|
150
|
+
string GetBranch();
|
|
151
|
+
|
|
152
|
+
[return: MarshalAs(UnmanagedType.BStr)]
|
|
153
|
+
string GetType();
|
|
154
|
+
|
|
155
|
+
[return: MarshalAs(UnmanagedType.BStr)]
|
|
156
|
+
string GetUniqueId();
|
|
157
|
+
|
|
158
|
+
[return: MarshalAs(UnmanagedType.VariantBool)]
|
|
159
|
+
bool GetIsExtension();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
[Guid("c601c175-a3be-44bc-91f6-4568d230fc83")]
|
|
163
|
+
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
164
|
+
[ComImport]
|
|
165
|
+
public interface ISetupPropertyStore
|
|
166
|
+
{
|
|
167
|
+
|
|
168
|
+
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
|
|
169
|
+
string[] GetNames();
|
|
170
|
+
|
|
171
|
+
object GetValue([MarshalAs(UnmanagedType.LPWStr), In] string pwszName);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
[Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")]
|
|
175
|
+
[CoClass(typeof(SetupConfigurationClass))]
|
|
176
|
+
[ComImport]
|
|
177
|
+
public interface SetupConfiguration : ISetupConfiguration2, ISetupConfiguration
|
|
178
|
+
{
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
[Guid("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D")]
|
|
182
|
+
[ClassInterface(ClassInterfaceType.None)]
|
|
183
|
+
[ComImport]
|
|
184
|
+
public class SetupConfigurationClass
|
|
185
|
+
{
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
public static class Main
|
|
189
|
+
{
|
|
190
|
+
public static void PrintJson()
|
|
191
|
+
{
|
|
192
|
+
ISetupConfiguration query = new SetupConfiguration();
|
|
193
|
+
ISetupConfiguration2 query2 = (ISetupConfiguration2)query;
|
|
194
|
+
IEnumSetupInstances e = query2.EnumAllInstances();
|
|
195
|
+
|
|
196
|
+
int pceltFetched;
|
|
197
|
+
ISetupInstance2[] rgelt = new ISetupInstance2[1];
|
|
198
|
+
List<string> instances = new List<string>();
|
|
199
|
+
while (true)
|
|
200
|
+
{
|
|
201
|
+
e.Next(1, rgelt, out pceltFetched);
|
|
202
|
+
if (pceltFetched <= 0)
|
|
203
|
+
{
|
|
204
|
+
Console.WriteLine(String.Format("[{0}]", string.Join(",", instances.ToArray())));
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
try
|
|
209
|
+
{
|
|
210
|
+
instances.Add(InstanceJson(rgelt[0]));
|
|
211
|
+
}
|
|
212
|
+
catch (COMException)
|
|
213
|
+
{
|
|
214
|
+
// Ignore instances that can't be queried.
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
private static string JsonString(string s)
|
|
220
|
+
{
|
|
221
|
+
return "\"" + s.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"";
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
private static string InstanceJson(ISetupInstance2 setupInstance2)
|
|
225
|
+
{
|
|
226
|
+
// Visual Studio component directory:
|
|
227
|
+
// https://docs.microsoft.com/en-us/visualstudio/install/workload-and-component-ids
|
|
228
|
+
|
|
229
|
+
StringBuilder json = new StringBuilder();
|
|
230
|
+
json.Append("{");
|
|
231
|
+
|
|
232
|
+
string path = JsonString(setupInstance2.GetInstallationPath());
|
|
233
|
+
json.Append(String.Format("\"path\":{0},", path));
|
|
234
|
+
|
|
235
|
+
string version = JsonString(setupInstance2.GetInstallationVersion());
|
|
236
|
+
json.Append(String.Format("\"version\":{0},", version));
|
|
237
|
+
|
|
238
|
+
List<string> packages = new List<string>();
|
|
239
|
+
foreach (ISetupPackageReference package in setupInstance2.GetPackages())
|
|
240
|
+
{
|
|
241
|
+
string id = JsonString(package.GetId());
|
|
242
|
+
packages.Add(id);
|
|
243
|
+
}
|
|
244
|
+
json.Append(String.Format("\"packages\":[{0}]", string.Join(",", packages.ToArray())));
|
|
245
|
+
|
|
246
|
+
json.Append("}");
|
|
247
|
+
return json.ToString();
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
(The MIT License)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person
|
|
6
|
+
obtaining a copy of this software and associated documentation
|
|
7
|
+
files (the "Software"), to deal in the Software without
|
|
8
|
+
restriction, including without limitation the rights to use,
|
|
9
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the
|
|
11
|
+
Software is furnished to do so, subject to the following
|
|
12
|
+
conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be
|
|
15
|
+
included in all copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
19
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
20
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
21
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
22
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
23
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
24
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
This is a copy of some files from node-gyp, with some minor modifications.
|
|
2
|
+
|
|
3
|
+
Currently based on v10.0.1
|
|
4
|
+
|
|
5
|
+
node-gyp has a decent strategy for finding Visual Studio, and has a lot more developer time behind them to make a good and robust solution.
|
|
6
|
+
We may as well benefit from their solution than reinvent it
|