@@ -523,13 +523,116 @@ mut:
523523 other_flags []string
524524}
525525
526+ fn strip_quotes (value string ) string {
527+ if value.len > = 2 && value[0 ] == `"` && value[value.len - 1 ] == `"` {
528+ return value[1 ..value.len - 1 ]
529+ }
530+ return value
531+ }
532+
533+ fn apply_gnu_flag_to_msvc (value string , mut inc_paths []string , mut lib_paths []string , mut real_libs []string ) bool {
534+ v := strip_quotes (value)
535+ if v.starts_with ('-I' ) && v.len > 2 {
536+ path := v[2 ..]
537+ inc_paths << '/I"${os .real_path (path )}"'
538+ return true
539+ }
540+ if v.starts_with ('-L' ) && v.len > 2 {
541+ path := v[2 ..]
542+ lib_paths << path
543+ lib_paths << path + os.path_separator + 'msvc'
544+ return true
545+ }
546+ if v.starts_with ('-l' ) && v.len > 2 {
547+ mut lib := v[2 ..]
548+ if lib.starts_with (':' ) && lib.len > 1 {
549+ lib = lib[1 ..]
550+ }
551+ if ! lib.ends_with ('.lib' ) {
552+ lib + = '.lib'
553+ }
554+ real_libs << lib
555+ return true
556+ }
557+ if v.starts_with ('-Wl,' ) {
558+ mut consumed := false
559+ for part in v[4 ..].split (',' ) {
560+ if apply_gnu_flag_to_msvc (part, mut inc_paths, mut lib_paths, mut real_libs) {
561+ consumed = true
562+ }
563+ }
564+ return consumed
565+ }
566+ return false
567+ }
568+
569+ fn split_and_apply_gnu_flags (value string , mut inc_paths []string , mut lib_paths []string , mut real_libs []string ) (bool , string ) {
570+ if ! value.contains (' ' ) {
571+ if apply_gnu_flag_to_msvc (value, mut inc_paths, mut lib_paths, mut real_libs) {
572+ return true , ''
573+ }
574+ return false , value
575+ }
576+ parts := split_quoted_flags (value)
577+ mut consumed := false
578+ mut leftovers := []string {}
579+ for part in parts {
580+ if part == '' {
581+ continue
582+ }
583+ if apply_gnu_flag_to_msvc (part, mut inc_paths, mut lib_paths, mut real_libs) {
584+ consumed = true
585+ } else {
586+ leftovers << strip_quotes (part)
587+ }
588+ }
589+ if consumed {
590+ return true , leftovers.join (' ' )
591+ }
592+ return false , value
593+ }
594+
595+ fn split_quoted_flags (value string ) []string {
596+ mut parts := []string {}
597+ mut buf := []u8 {}
598+ mut in_quote := false
599+ for ch in value {
600+ if ch == `"` {
601+ in_quote = ! in_quote
602+ continue
603+ }
604+ if ! in_quote && ch == ` ` {
605+ if buf.len > 0 {
606+ parts << buf.bytestr ()
607+ buf = []u8 {}
608+ }
609+ continue
610+ }
611+ buf << ch
612+ }
613+ if buf.len > 0 {
614+ parts << buf.bytestr ()
615+ }
616+ return parts
617+ }
618+
526619pub fn (mut v Builder) msvc_string_flags (cflags []cflag.CFlag) MsvcStringFlags {
527620 mut real_libs := []string {}
528621 mut inc_paths := []string {}
529622 mut lib_paths := []string {}
530623 mut defines := []string {}
531624 mut other_flags := []string {}
532625 for flag in cflags {
626+ if flag.name == '' {
627+ consumed , leftover := split_and_apply_gnu_flags (flag.value, mut inc_paths, mut
628+ lib_paths, mut real_libs)
629+ if consumed {
630+ if leftover != '' {
631+ other_flags << strip_quotes (leftover)
632+ }
633+ continue
634+ }
635+ }
533636 // println('fl: ${flag.name} | flag arg: ${flag.value}')
534637 // We need to see if the flag contains -l
535638 // -l isnt recognised and these libs will be passed straight to the linker
@@ -540,14 +643,29 @@ pub fn (mut v Builder) msvc_string_flags(cflags []cflag.CFlag) MsvcStringFlags {
540643 }
541644 // MSVC has no method of linking against a .dll
542645 // TODO: we should look for .defs aswell
543- lib_lib := flag.value + '.lib'
544- real_libs << lib_lib
646+ parts := split_quoted_flags (flag.value)
647+ if parts.len > 0 {
648+ mut lib := strip_quotes (parts[0 ])
649+ if lib.starts_with (':' ) && lib.len > 1 {
650+ lib = lib[1 ..]
651+ }
652+ if ! lib.ends_with ('.lib' ) {
653+ lib + = '.lib'
654+ }
655+ real_libs << lib
656+ if parts.len > 1 {
657+ _ , leftover := split_and_apply_gnu_flags (parts[1 ..].join (' ' ), mut
658+ inc_paths, mut lib_paths, mut real_libs)
659+ if leftover != '' {
660+ other_flags << strip_quotes (leftover)
661+ }
662+ }
663+ }
545664 } else if flag.name == '-I' {
546- inc_paths << flag. format () or { continue }
665+ inc_paths << '/I"${ os . real_path ( flag . value )}"'
547666 } else if flag.name == '-D' {
548667 defines << '/D${flag .value }'
549668 } else if flag.name == '-L' {
550- // TODO: use flag.format() here as well; `#flag -L$when_first_existing(...)` is a more explicit way to achieve the same
551669 lib_paths << flag.value
552670 lib_paths << flag.value + os.path_separator + 'msvc'
553671 // The above allows putting msvc specific .lib files in a subfolder msvc/ ,
@@ -567,7 +685,15 @@ pub fn (mut v Builder) msvc_string_flags(cflags []cflag.CFlag) MsvcStringFlags {
567685 } else if flag.value.starts_with ('-D' ) {
568686 defines << '/D${flag .value [2 ..]}'
569687 } else {
570- other_flags << flag.value
688+ consumed , leftover := split_and_apply_gnu_flags (flag.value, mut inc_paths, mut
689+ lib_paths, mut real_libs)
690+ if consumed {
691+ if leftover != '' {
692+ other_flags << strip_quotes (leftover)
693+ }
694+ continue
695+ }
696+ other_flags << strip_quotes (flag.value)
571697 }
572698 }
573699 mut lpaths := []string {}
0 commit comments