2020-04-07 00:44:19 +02:00
|
|
|
module builder
|
2019-07-23 23:23:13 +02:00
|
|
|
|
2020-03-07 22:26:26 +01:00
|
|
|
import os
|
2020-07-21 18:45:50 +02:00
|
|
|
import time
|
2020-04-03 17:38:41 +02:00
|
|
|
import v.pref
|
2020-04-18 16:29:43 +02:00
|
|
|
import v.cflag
|
2019-07-23 23:23:13 +02:00
|
|
|
|
2019-07-24 13:49:00 +02:00
|
|
|
#flag windows -l shell32
|
2019-12-20 00:19:21 +01:00
|
|
|
#flag windows -l dbghelp
|
2019-10-11 02:55:54 +02:00
|
|
|
#flag windows -l advapi32
|
2019-07-23 23:23:13 +02:00
|
|
|
struct MsvcResult {
|
2019-12-19 22:29:37 +01:00
|
|
|
full_cl_exe_path string
|
|
|
|
exe_path string
|
|
|
|
um_lib_path string
|
|
|
|
ucrt_lib_path string
|
|
|
|
vs_lib_path string
|
|
|
|
um_include_path string
|
|
|
|
ucrt_include_path string
|
|
|
|
vs_include_path string
|
2019-08-12 13:17:26 +02:00
|
|
|
shared_include_path string
|
2020-07-27 12:15:29 +02:00
|
|
|
valid bool
|
2019-07-23 23:23:13 +02:00
|
|
|
}
|
|
|
|
|
2019-12-20 00:35:07 +01:00
|
|
|
// shell32 for RegOpenKeyExW etc
|
2019-07-25 12:29:24 +02:00
|
|
|
// Mimics a HKEY
|
|
|
|
type RegKey voidptr
|
2020-04-26 09:17:13 +02:00
|
|
|
|
2019-07-25 12:29:24 +02:00
|
|
|
// Taken from the windows SDK
|
|
|
|
const (
|
2020-05-22 17:36:09 +02:00
|
|
|
hkey_local_machine = RegKey(0x80000002)
|
|
|
|
key_query_value = (0x0001)
|
|
|
|
key_wow64_32key = (0x0200)
|
|
|
|
key_enumerate_sub_keys = (0x0008)
|
2019-07-25 12:29:24 +02:00
|
|
|
)
|
2020-04-26 09:17:13 +02:00
|
|
|
|
2019-10-07 00:31:01 +02:00
|
|
|
// Given a root key look for one of the subkeys in 'versions' and get the path
|
2019-08-10 10:26:42 +02:00
|
|
|
fn find_windows_kit_internal(key RegKey, versions []string) ?string {
|
2019-08-12 13:17:26 +02:00
|
|
|
$if windows {
|
2020-02-22 12:41:24 +01:00
|
|
|
unsafe {
|
|
|
|
for version in versions {
|
|
|
|
required_bytes := 0 // TODO mut
|
|
|
|
result := C.RegQueryValueEx(key, version.to_wide(), 0, 0, 0, &required_bytes)
|
|
|
|
length := required_bytes / 2
|
|
|
|
if result != 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
alloc_length := (required_bytes + 2)
|
2020-04-26 09:33:40 +02:00
|
|
|
mut value := &u16(malloc(alloc_length))
|
2020-02-22 12:41:24 +01:00
|
|
|
if isnil(value) {
|
|
|
|
continue
|
|
|
|
}
|
2020-04-26 09:33:40 +02:00
|
|
|
//
|
2020-07-27 12:15:29 +02:00
|
|
|
else {
|
|
|
|
}
|
2020-02-22 12:41:24 +01:00
|
|
|
result2 := C.RegQueryValueEx(key, version.to_wide(), 0, 0, value, &alloc_length)
|
|
|
|
if result2 != 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
// We might need to manually null terminate this thing
|
|
|
|
// So just make sure that we do that
|
2020-03-28 10:19:38 +01:00
|
|
|
if value[length - 1] != u16(0) {
|
2020-02-22 12:41:24 +01:00
|
|
|
value[length] = u16(0)
|
|
|
|
}
|
2020-04-02 13:44:46 +02:00
|
|
|
res := string_from_wide(value)
|
|
|
|
return res
|
2019-08-12 13:17:26 +02:00
|
|
|
}
|
|
|
|
}
|
2019-08-10 10:26:42 +02:00
|
|
|
}
|
|
|
|
return error('windows kit not found')
|
2019-07-23 23:23:13 +02:00
|
|
|
}
|
|
|
|
|
2019-07-25 12:29:24 +02:00
|
|
|
struct WindowsKit {
|
2019-12-19 22:29:37 +01:00
|
|
|
um_lib_path string
|
|
|
|
ucrt_lib_path string
|
|
|
|
um_include_path string
|
|
|
|
ucrt_include_path string
|
2019-07-25 12:29:24 +02:00
|
|
|
shared_include_path string
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try and find the root key for installed windows kits
|
2019-10-16 01:54:35 +02:00
|
|
|
fn find_windows_kit_root(host_arch string) ?WindowsKit {
|
2019-08-12 13:17:26 +02:00
|
|
|
$if windows {
|
|
|
|
root_key := RegKey(0)
|
2020-04-02 13:24:23 +02:00
|
|
|
path := 'SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots'
|
2020-05-22 17:36:09 +02:00
|
|
|
rc := C.RegOpenKeyEx(hkey_local_machine, path.to_wide(), 0, key_query_value | key_wow64_32key |
|
|
|
|
key_enumerate_sub_keys, &root_key)
|
2019-12-19 22:29:37 +01:00
|
|
|
defer {
|
|
|
|
C.RegCloseKey(root_key)
|
|
|
|
}
|
2019-08-12 13:17:26 +02:00
|
|
|
if rc != 0 {
|
|
|
|
return error('Unable to open root key')
|
|
|
|
}
|
|
|
|
// Try and find win10 kit
|
2020-04-26 09:17:13 +02:00
|
|
|
kit_root := find_windows_kit_internal(root_key, ['KitsRoot10', 'KitsRoot81']) or {
|
2019-08-12 13:17:26 +02:00
|
|
|
return error('Unable to find a windows kit')
|
|
|
|
}
|
|
|
|
kit_lib := kit_root + 'Lib'
|
|
|
|
// println(kit_lib)
|
2020-08-05 12:22:10 +02:00
|
|
|
files := os.ls(kit_lib)?
|
2019-08-12 13:17:26 +02:00
|
|
|
mut highest_path := ''
|
|
|
|
mut highest_int := 0
|
|
|
|
for f in files {
|
|
|
|
no_dot := f.replace('.', '')
|
|
|
|
v_int := no_dot.int()
|
|
|
|
if v_int > highest_int {
|
|
|
|
highest_int = v_int
|
|
|
|
highest_path = f
|
|
|
|
}
|
2019-07-23 23:23:13 +02:00
|
|
|
}
|
2019-08-12 13:17:26 +02:00
|
|
|
kit_lib_highest := kit_lib + '\\$highest_path'
|
|
|
|
kit_include_highest := kit_lib_highest.replace('Lib', 'Include')
|
|
|
|
// println('$kit_lib_highest $kit_include_highest')
|
2019-12-19 22:29:37 +01:00
|
|
|
return WindowsKit{
|
2019-10-16 01:54:35 +02:00
|
|
|
um_lib_path: kit_lib_highest + '\\um\\$host_arch'
|
|
|
|
ucrt_lib_path: kit_lib_highest + '\\ucrt\\$host_arch'
|
2019-08-12 13:17:26 +02:00
|
|
|
um_include_path: kit_include_highest + '\\um'
|
|
|
|
ucrt_include_path: kit_include_highest + '\\ucrt'
|
|
|
|
shared_include_path: kit_include_highest + '\\shared'
|
|
|
|
}
|
2019-07-25 12:29:24 +02:00
|
|
|
}
|
2020-06-08 09:19:31 +02:00
|
|
|
return error('Host OS does not support finding a windows kit')
|
2019-07-25 12:29:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
struct VsInstallation {
|
|
|
|
include_path string
|
2019-12-19 22:29:37 +01:00
|
|
|
lib_path string
|
|
|
|
exe_path string
|
2019-07-25 12:29:24 +02:00
|
|
|
}
|
|
|
|
|
2020-04-26 09:17:13 +02:00
|
|
|
fn find_vs(vswhere_dir, host_arch string) ?VsInstallation {
|
2019-08-12 13:17:26 +02:00
|
|
|
$if !windows {
|
2020-06-08 09:19:31 +02:00
|
|
|
return error('Host OS does not support finding a Visual Studio installation')
|
2019-08-12 13:17:26 +02:00
|
|
|
}
|
2019-07-25 12:29:24 +02:00
|
|
|
// Emily:
|
|
|
|
// VSWhere is guaranteed to be installed at this location now
|
2019-10-07 00:31:01 +02:00
|
|
|
// If its not there then end user needs to update their visual studio
|
2019-07-25 12:29:24 +02:00
|
|
|
// installation!
|
2020-04-26 09:17:13 +02:00
|
|
|
res := os.exec('"$vswhere_dir\\Microsoft Visual Studio\\Installer\\vswhere.exe" -latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath') or {
|
2019-08-10 10:26:42 +02:00
|
|
|
return error(err)
|
2019-08-08 07:30:05 +02:00
|
|
|
}
|
2020-08-28 18:48:18 +02:00
|
|
|
res_output := res.output.trim_space().trim_right('\r\n')
|
2019-07-25 12:29:24 +02:00
|
|
|
// println('res: "$res"')
|
2020-06-15 14:16:37 +02:00
|
|
|
version := os.read_file('$res_output\\VC\\Auxiliary\\Build\\Microsoft.VCToolsVersion.default.txt') or {
|
2020-07-27 12:15:29 +02:00
|
|
|
// println('Unable to find msvc version')
|
2019-07-25 12:29:24 +02:00
|
|
|
return error('Unable to find vs installation')
|
|
|
|
}
|
2020-03-20 20:35:00 +01:00
|
|
|
version2 := version // TODO remove. cgen option bug if expr
|
2019-07-25 12:29:24 +02:00
|
|
|
// println('version: $version')
|
2020-04-26 09:17:13 +02:00
|
|
|
v := if version.ends_with('\n') { version2[..version.len - 2] } else { version2 }
|
2019-10-16 01:54:35 +02:00
|
|
|
lib_path := '$res.output\\VC\\Tools\\MSVC\\$v\\lib\\$host_arch'
|
2019-08-17 19:21:59 +02:00
|
|
|
include_path := '$res.output\\VC\\Tools\\MSVC\\$v\\include'
|
2019-12-04 21:03:12 +01:00
|
|
|
if os.exists('$lib_path\\vcruntime.lib') {
|
2019-10-16 01:54:35 +02:00
|
|
|
p := '$res.output\\VC\\Tools\\MSVC\\$v\\bin\\Host$host_arch\\$host_arch'
|
2019-07-25 12:29:24 +02:00
|
|
|
// println('$lib_path $include_path')
|
|
|
|
return VsInstallation{
|
|
|
|
exe_path: p
|
|
|
|
lib_path: lib_path
|
|
|
|
include_path: include_path
|
2019-07-23 23:23:13 +02:00
|
|
|
}
|
2019-07-25 12:29:24 +02:00
|
|
|
}
|
|
|
|
println('Unable to find vs installation (attempted to use lib path "$lib_path")')
|
|
|
|
return error('Unable to find vs exe folder')
|
|
|
|
}
|
2019-07-23 23:23:13 +02:00
|
|
|
|
2019-07-25 12:29:24 +02:00
|
|
|
fn find_msvc() ?MsvcResult {
|
|
|
|
$if windows {
|
2019-10-16 01:54:35 +02:00
|
|
|
processor_architecture := os.getenv('PROCESSOR_ARCHITECTURE')
|
2019-12-19 22:29:37 +01:00
|
|
|
vswhere_dir := if processor_architecture == 'x86' { '%ProgramFiles%' } else { '%ProgramFiles(x86)%' }
|
|
|
|
host_arch := if processor_architecture == 'x86' { 'X86' } else { 'X64' }
|
2020-04-26 09:17:13 +02:00
|
|
|
wk := find_windows_kit_root(host_arch) or {
|
2019-07-25 12:29:24 +02:00
|
|
|
return error('Unable to find windows sdk')
|
|
|
|
}
|
2020-04-26 09:17:13 +02:00
|
|
|
vs := find_vs(vswhere_dir, host_arch) or {
|
2019-07-25 12:29:24 +02:00
|
|
|
return error('Unable to find visual studio')
|
|
|
|
}
|
2019-12-19 22:29:37 +01:00
|
|
|
return MsvcResult{
|
2020-03-20 16:41:18 +01:00
|
|
|
full_cl_exe_path: os.real_path(vs.exe_path + os.path_separator + 'cl.exe')
|
2019-12-19 22:29:37 +01:00
|
|
|
exe_path: vs.exe_path
|
|
|
|
um_lib_path: wk.um_lib_path
|
|
|
|
ucrt_lib_path: wk.ucrt_lib_path
|
|
|
|
vs_lib_path: vs.lib_path
|
|
|
|
um_include_path: wk.um_include_path
|
|
|
|
ucrt_include_path: wk.ucrt_include_path
|
|
|
|
vs_include_path: vs.include_path
|
|
|
|
shared_include_path: wk.shared_include_path
|
2020-07-07 20:35:49 +02:00
|
|
|
valid: true
|
2019-07-23 23:23:13 +02:00
|
|
|
}
|
2019-12-19 22:29:37 +01:00
|
|
|
} $else {
|
2019-08-29 02:30:17 +02:00
|
|
|
return error('msvc not found')
|
2019-07-23 23:23:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-26 09:17:13 +02:00
|
|
|
pub fn (mut v Builder) cc_msvc() {
|
2020-07-07 20:35:49 +02:00
|
|
|
r := v.cached_msvc
|
|
|
|
if r.valid == false {
|
2019-09-25 16:59:50 +02:00
|
|
|
verror('Cannot find MSVC on this OS')
|
2019-08-29 02:30:17 +02:00
|
|
|
return
|
2019-07-25 12:29:24 +02:00
|
|
|
}
|
2020-03-20 16:41:18 +01:00
|
|
|
out_name_obj := os.real_path(v.out_name_c + '.obj')
|
2020-06-26 17:16:15 +02:00
|
|
|
out_name_pdb := os.real_path(v.out_name_c + '.pdb')
|
2020-07-08 14:50:17 +02:00
|
|
|
out_name_cmd_line := os.real_path(v.out_name_c + '.rsp')
|
2019-07-25 12:29:24 +02:00
|
|
|
// Default arguments
|
2019-08-12 13:17:26 +02:00
|
|
|
// volatile:ms enables atomic volatile (gcc _Atomic)
|
|
|
|
// -w: no warnings
|
|
|
|
// 2 unicode defines
|
|
|
|
// /Fo sets the object file name - needed so we can clean up after ourselves properly
|
2019-09-17 13:56:32 +02:00
|
|
|
mut a := ['-w', '/we4013', '/volatile:ms', '/Fo"$out_name_obj"']
|
2019-07-23 23:23:13 +02:00
|
|
|
if v.pref.is_prod {
|
|
|
|
a << '/O2'
|
|
|
|
a << '/MD'
|
2019-10-04 15:09:45 +02:00
|
|
|
a << '/DNDEBUG'
|
2020-04-26 09:17:13 +02:00
|
|
|
} else {
|
2019-07-23 23:23:13 +02:00
|
|
|
a << '/MDd'
|
|
|
|
}
|
2020-06-26 17:16:15 +02:00
|
|
|
if v.pref.is_debug {
|
|
|
|
// /Zi generates a .pdb
|
|
|
|
// /Fd sets the pdb file name (so its not just vc140 all the time)
|
|
|
|
a << ['/Zi', '/Fd"$out_name_pdb"']
|
|
|
|
}
|
2020-04-18 17:46:23 +02:00
|
|
|
if v.pref.is_shared {
|
2020-02-09 10:08:04 +01:00
|
|
|
if !v.pref.out_name.ends_with('.dll') {
|
|
|
|
v.pref.out_name += '.dll'
|
2019-07-23 23:23:13 +02:00
|
|
|
}
|
|
|
|
// Build dll
|
|
|
|
a << '/LD'
|
2020-04-26 09:17:13 +02:00
|
|
|
} else if !v.pref.out_name.ends_with('.exe') {
|
2020-02-09 10:08:04 +01:00
|
|
|
v.pref.out_name += '.exe'
|
2019-07-23 23:23:13 +02:00
|
|
|
}
|
2020-03-20 16:41:18 +01:00
|
|
|
v.pref.out_name = os.real_path(v.pref.out_name)
|
2020-04-26 16:25:54 +02:00
|
|
|
// alibs := []string{} // builtin.o os.o http.o etc
|
2019-09-10 16:36:14 +02:00
|
|
|
if v.pref.build_mode == .build_module {
|
2019-11-09 21:49:15 +01:00
|
|
|
// Compile only
|
|
|
|
a << '/c'
|
2020-04-26 09:17:13 +02:00
|
|
|
} else if v.pref.build_mode == .default_mode {
|
2019-10-09 06:10:33 +02:00
|
|
|
/*
|
2020-04-03 17:38:41 +02:00
|
|
|
b := os.real_path( '${pref.default_module_path}/vlib/builtin.obj' )
|
2019-09-03 15:09:43 +02:00
|
|
|
alibs << '"$b"'
|
2019-12-04 21:03:12 +01:00
|
|
|
if !os.exists(b) {
|
2019-07-23 23:23:13 +02:00
|
|
|
println('`builtin.obj` not found')
|
|
|
|
exit(1)
|
|
|
|
}
|
|
|
|
for imp in v.table.imports {
|
|
|
|
if imp == 'webview' {
|
|
|
|
continue
|
|
|
|
}
|
2020-04-03 17:38:41 +02:00
|
|
|
alibs << '"' + os.real_path( '${pref.default_module_path}/vlib/${imp}.obj' ) + '"'
|
2019-07-23 23:23:13 +02:00
|
|
|
}
|
2019-10-09 06:10:33 +02:00
|
|
|
*/
|
2019-07-23 23:23:13 +02:00
|
|
|
}
|
|
|
|
if v.pref.sanitize {
|
|
|
|
println('Sanitize not supported on msvc.')
|
|
|
|
}
|
|
|
|
// The C file we are compiling
|
2019-12-19 22:29:37 +01:00
|
|
|
// a << '"$TmpPath/$v.out_name_c"'
|
2020-03-20 16:41:18 +01:00
|
|
|
a << '"' + os.real_path(v.out_name_c) + '"'
|
2019-08-12 13:17:26 +02:00
|
|
|
// Emily:
|
|
|
|
// Not all of these are needed (but the compiler should discard them if they are not used)
|
|
|
|
// these are the defaults used by msbuild and visual studio
|
2019-12-27 09:27:19 +01:00
|
|
|
mut real_libs := ['kernel32.lib', 'user32.lib', 'advapi32.lib']
|
2020-07-27 12:15:29 +02:00
|
|
|
// sflags := v.get_os_cflags().msvc_string_flags()
|
2020-05-28 15:23:17 +02:00
|
|
|
sflags := msvc_string_flags(v.get_os_cflags())
|
2019-12-19 22:29:37 +01:00
|
|
|
real_libs << sflags.real_libs
|
|
|
|
inc_paths := sflags.inc_paths
|
|
|
|
lib_paths := sflags.lib_paths
|
2020-07-22 16:24:12 +02:00
|
|
|
defines := sflags.defines
|
2019-09-22 23:51:59 +02:00
|
|
|
other_flags := sflags.other_flags
|
2019-07-23 23:23:13 +02:00
|
|
|
// Include the base paths
|
2019-09-08 11:02:03 +02:00
|
|
|
a << '-I "$r.ucrt_include_path"'
|
|
|
|
a << '-I "$r.vs_include_path"'
|
|
|
|
a << '-I "$r.um_include_path"'
|
|
|
|
a << '-I "$r.shared_include_path"'
|
2020-07-22 16:24:12 +02:00
|
|
|
a << defines
|
2019-09-03 15:09:43 +02:00
|
|
|
a << inc_paths
|
2019-07-23 23:23:13 +02:00
|
|
|
a << other_flags
|
2019-08-12 13:17:26 +02:00
|
|
|
// Libs are passed to cl.exe which passes them to the linker
|
2019-07-23 23:23:13 +02:00
|
|
|
a << real_libs.join(' ')
|
|
|
|
a << '/link'
|
|
|
|
a << '/NOLOGO'
|
2020-02-09 10:08:04 +01:00
|
|
|
a << '/OUT:"$v.pref.out_name"'
|
2019-07-23 23:23:13 +02:00
|
|
|
a << '/LIBPATH:"$r.ucrt_lib_path"'
|
|
|
|
a << '/LIBPATH:"$r.um_lib_path"'
|
|
|
|
a << '/LIBPATH:"$r.vs_lib_path"'
|
2019-10-04 15:09:45 +02:00
|
|
|
a << '/DEBUG:FULL' // required for prod builds to generate PDB
|
|
|
|
if v.pref.is_prod {
|
|
|
|
a << '/INCREMENTAL:NO' // Disable incremental linking
|
|
|
|
a << '/OPT:REF'
|
|
|
|
a << '/OPT:ICF'
|
2019-07-23 23:23:13 +02:00
|
|
|
}
|
2019-09-22 23:51:59 +02:00
|
|
|
a << lib_paths
|
2019-07-23 23:23:13 +02:00
|
|
|
args := a.join(' ')
|
2020-07-08 14:50:17 +02:00
|
|
|
// write args to a file so that we dont smash createprocess
|
|
|
|
os.write_file(out_name_cmd_line, args) or {
|
|
|
|
verror('Unable to write response file to "$out_name_cmd_line"')
|
|
|
|
}
|
|
|
|
cmd := '"$r.full_cl_exe_path" @$out_name_cmd_line'
|
2019-10-07 00:31:01 +02:00
|
|
|
// It is hard to see it at first, but the quotes above ARE balanced :-| ...
|
2019-09-03 15:09:43 +02:00
|
|
|
// Also the double quotes at the start ARE needed.
|
2020-04-07 00:44:19 +02:00
|
|
|
if v.pref.is_verbose {
|
2019-09-03 15:09:43 +02:00
|
|
|
println('\n========== cl cmd line:')
|
2019-08-30 23:59:21 +02:00
|
|
|
println(cmd)
|
2019-09-03 15:09:43 +02:00
|
|
|
println('==========\n')
|
2019-08-30 23:59:21 +02:00
|
|
|
}
|
2019-07-23 23:23:13 +02:00
|
|
|
// println('$cmd')
|
2020-07-21 18:45:50 +02:00
|
|
|
ticks := time.ticks()
|
2020-04-26 09:17:13 +02:00
|
|
|
res := os.exec(cmd) or {
|
2020-08-28 18:27:41 +02:00
|
|
|
println(err.trim_space())
|
2019-09-23 23:40:34 +02:00
|
|
|
verror('msvc error')
|
2019-08-29 02:30:17 +02:00
|
|
|
return
|
2019-07-23 23:23:13 +02:00
|
|
|
}
|
2020-07-21 18:45:50 +02:00
|
|
|
diff := time.ticks() - ticks
|
2020-07-25 09:32:29 +02:00
|
|
|
v.timing_message('C msvc', diff)
|
2019-08-28 12:06:25 +02:00
|
|
|
if res.exit_code != 0 {
|
2020-08-28 18:27:41 +02:00
|
|
|
verror(res.output.trim_space())
|
2019-08-28 12:06:25 +02:00
|
|
|
}
|
2019-08-08 07:30:05 +02:00
|
|
|
// println(res)
|
|
|
|
// println('C OUTPUT:')
|
2019-08-20 15:32:15 +02:00
|
|
|
// Always remove the object file - it is completely unnecessary
|
2019-09-03 15:09:43 +02:00
|
|
|
os.rm(out_name_obj)
|
2019-07-23 23:23:13 +02:00
|
|
|
}
|
2019-12-19 22:29:37 +01:00
|
|
|
|
2020-07-07 20:35:49 +02:00
|
|
|
fn (mut v Builder) build_thirdparty_obj_file_with_msvc(path string, moduleflags []cflag.CFlag) {
|
|
|
|
msvc := v.cached_msvc
|
|
|
|
if msvc.valid == false {
|
|
|
|
verror('Cannot find MSVC on this OS')
|
2019-07-25 12:29:24 +02:00
|
|
|
return
|
|
|
|
}
|
2019-09-06 14:12:04 +02:00
|
|
|
// msvc expects .obj not .o
|
|
|
|
mut obj_path := '${path}bj'
|
2020-03-20 16:41:18 +01:00
|
|
|
obj_path = os.real_path(obj_path)
|
2019-12-04 21:03:12 +01:00
|
|
|
if os.exists(obj_path) {
|
2020-07-07 20:35:49 +02:00
|
|
|
// println('$obj_path already built.')
|
2019-10-07 00:31:01 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
println('$obj_path not found, building it (with msvc)...')
|
2020-07-07 20:35:49 +02:00
|
|
|
cfiles := '${path[..path.len-2]}.c'
|
|
|
|
flags := msvc_string_flags(moduleflags)
|
|
|
|
inc_dirs := flags.inc_paths.join(' ')
|
|
|
|
defines := flags.defines.join(' ')
|
|
|
|
include_string := '-I "$msvc.ucrt_include_path" -I "$msvc.vs_include_path" -I "$msvc.um_include_path" -I "$msvc.shared_include_path" $inc_dirs'
|
2019-12-19 22:29:37 +01:00
|
|
|
// println('cfiles: $cfiles')
|
2020-07-07 20:35:49 +02:00
|
|
|
cmd := '"$msvc.full_cl_exe_path" /volatile:ms /DNDEBUG $defines $include_string /c $cfiles /Fo"$obj_path"'
|
2019-12-19 22:29:37 +01:00
|
|
|
// NB: the quotes above ARE balanced.
|
2020-07-07 20:35:49 +02:00
|
|
|
// println('thirdparty cmd line: $cmd')
|
2020-04-26 09:17:13 +02:00
|
|
|
res := os.exec(cmd) or {
|
2019-10-28 10:43:57 +01:00
|
|
|
println('msvc: failed thirdparty object build cmd: $cmd')
|
2020-08-28 18:27:41 +02:00
|
|
|
verror(err.trim_space())
|
2019-08-29 02:30:17 +02:00
|
|
|
return
|
2019-08-08 07:30:05 +02:00
|
|
|
}
|
2019-10-28 10:43:57 +01:00
|
|
|
if res.exit_code != 0 {
|
|
|
|
println('msvc: failed thirdparty object build cmd: $cmd')
|
2020-08-28 18:27:41 +02:00
|
|
|
verror(res.output.trim_space())
|
2019-10-28 10:43:57 +01:00
|
|
|
return
|
|
|
|
}
|
2020-08-28 18:27:41 +02:00
|
|
|
println(res.output.trim_space())
|
2019-08-12 13:17:26 +02:00
|
|
|
}
|
2019-07-25 15:05:44 +02:00
|
|
|
|
2019-09-22 23:51:59 +02:00
|
|
|
struct MsvcStringFlags {
|
|
|
|
mut:
|
2019-12-19 22:29:37 +01:00
|
|
|
real_libs []string
|
|
|
|
inc_paths []string
|
|
|
|
lib_paths []string
|
2020-07-07 20:35:49 +02:00
|
|
|
defines []string
|
2019-09-22 23:51:59 +02:00
|
|
|
other_flags []string
|
|
|
|
}
|
|
|
|
|
2020-07-27 12:15:29 +02:00
|
|
|
// pub fn (cflags []CFlag) msvc_string_flags() MsvcStringFlags {
|
2020-05-28 15:23:17 +02:00
|
|
|
pub fn msvc_string_flags(cflags []cflag.CFlag) MsvcStringFlags {
|
2020-04-26 09:17:13 +02:00
|
|
|
mut real_libs := []string{}
|
|
|
|
mut inc_paths := []string{}
|
|
|
|
mut lib_paths := []string{}
|
2020-07-07 20:35:49 +02:00
|
|
|
mut defines := []string{}
|
2020-04-26 09:17:13 +02:00
|
|
|
mut other_flags := []string{}
|
2019-09-22 23:51:59 +02:00
|
|
|
for flag in cflags {
|
2019-12-19 22:29:37 +01:00
|
|
|
// println('fl: $flag.name | flag arg: $flag.value')
|
2019-09-22 23:51:59 +02:00
|
|
|
// We need to see if the flag contains -l
|
|
|
|
// -l isnt recognised and these libs will be passed straight to the linker
|
|
|
|
// by the compiler
|
|
|
|
if flag.name == '-l' {
|
|
|
|
if flag.value.ends_with('.dll') {
|
2019-09-23 23:40:34 +02:00
|
|
|
verror('MSVC cannot link against a dll (`#flag -l $flag.value`)')
|
2019-09-22 23:51:59 +02:00
|
|
|
}
|
|
|
|
// MSVC has no method of linking against a .dll
|
|
|
|
// TODO: we should look for .defs aswell
|
|
|
|
lib_lib := flag.value + '.lib'
|
|
|
|
real_libs << lib_lib
|
2020-04-26 09:17:13 +02:00
|
|
|
} else if flag.name == '-I' {
|
2019-09-22 23:51:59 +02:00
|
|
|
inc_paths << flag.format()
|
2020-04-26 09:17:13 +02:00
|
|
|
} else if flag.name == '-L' {
|
2019-09-22 23:51:59 +02:00
|
|
|
lib_paths << flag.value
|
2020-03-07 22:26:26 +01:00
|
|
|
lib_paths << flag.value + os.path_separator + 'msvc'
|
2019-09-22 23:51:59 +02:00
|
|
|
// The above allows putting msvc specific .lib files in a subfolder msvc/ ,
|
|
|
|
// where gcc will NOT find them, but cl will do...
|
|
|
|
// NB: gcc is smart enough to not need .lib files at all in most cases, the .dll is enough.
|
|
|
|
// When both a msvc .lib file and .dll file are present in the same folder,
|
|
|
|
// as for example for glfw3, compilation with gcc would fail.
|
2020-04-26 09:17:13 +02:00
|
|
|
} else if flag.value.ends_with('.o') {
|
2019-09-22 23:51:59 +02:00
|
|
|
// msvc expects .obj not .o
|
|
|
|
other_flags << '"${flag.value}bj"'
|
2020-07-07 20:35:49 +02:00
|
|
|
} else if flag.value.starts_with('-D') {
|
|
|
|
defines << '/D${flag.value[2..]}'
|
2020-04-26 09:17:13 +02:00
|
|
|
} else {
|
2019-09-22 23:51:59 +02:00
|
|
|
other_flags << flag.value
|
|
|
|
}
|
|
|
|
}
|
2020-04-26 09:17:13 +02:00
|
|
|
mut lpaths := []string{}
|
2019-09-22 23:51:59 +02:00
|
|
|
for l in lib_paths {
|
2020-03-20 16:41:18 +01:00
|
|
|
lpaths << '/LIBPATH:"' + os.real_path(l) + '"'
|
2019-09-22 23:51:59 +02:00
|
|
|
}
|
2019-12-19 22:29:37 +01:00
|
|
|
return MsvcStringFlags{
|
2020-04-26 09:17:13 +02:00
|
|
|
real_libs: real_libs
|
|
|
|
inc_paths: inc_paths
|
|
|
|
lib_paths: lpaths
|
2020-07-07 20:35:49 +02:00
|
|
|
defines: defines
|
2020-04-26 09:17:13 +02:00
|
|
|
other_flags: other_flags
|
2020-02-18 17:29:47 +01:00
|
|
|
}
|
2019-09-22 23:51:59 +02:00
|
|
|
}
|