@@ -857,6 +857,33 @@ fn (b &Builder) cached_called_fn_name_list() []string {
857857 return names
858858}
859859
860+ fn cached_called_fn_names_path (cache_dir string , cache_name string ) string {
861+ return cache_path_join (cache_dir, '${cache_name }.calls' )
862+ }
863+
864+ fn (mut b Builder) load_cached_called_fn_names (cache_dir string , cache_name string ) bool {
865+ data := os.read_file (cached_called_fn_names_path (cache_dir, cache_name)) or { return false }
866+ for line in data.split_into_lines () {
867+ name := line.trim_space ()
868+ if name.len > 0 {
869+ b.cached_called_fn_names[name] = true
870+ }
871+ }
872+ return true
873+ }
874+
875+ fn (mut b Builder) write_cached_called_fn_names (cache_dir string , cache_name string , before map [string ]bool ) {
876+ mut names := []string {}
877+ for name, _ in b.cached_called_fn_names {
878+ if name.len == 0 || name in before {
879+ continue
880+ }
881+ names << name
882+ }
883+ names.sort ()
884+ os.write_file (cached_called_fn_names_path (cache_dir, cache_name), names.join ('\n ' )) or {}
885+ }
886+
860887fn cache_type_module_names (cache_bundle_name string , emit_modules []string ) []string {
861888 if cache_bundle_name == '' {
862889 return emit_modules
@@ -901,6 +928,43 @@ fn (b &Builder) expand_type_modules_with_imports(modules []string) []string {
901928 return unique_sorted_strings (type_modules.keys ())
902929}
903930
931+ fn (b &Builder) has_external_cache_module_name_collision (module_names []string ) bool {
932+ mut module_set := map [string ]bool {}
933+ for module_name in module_names {
934+ if module_name != '' {
935+ module_set[module_name] = true
936+ }
937+ }
938+ mut vlib_modules := map [string ]bool {}
939+ mut external_modules := map [string ]bool {}
940+ for file in b.files {
941+ if file.name == '' || file.name.ends_with ('.vh' ) {
942+ continue
943+ }
944+ module_name := ast_file_module_name (file)
945+ if module_name ! in module_set {
946+ continue
947+ }
948+ if b.is_vlib_source_file (file.name) {
949+ vlib_modules[module_name] = true
950+ } else {
951+ external_modules[module_name] = true
952+ }
953+ }
954+ for module_name, _ in external_modules {
955+ if module_name in vlib_modules {
956+ return true
957+ }
958+ }
959+ return false
960+ }
961+
962+ fn (b &Builder) is_vlib_source_file (file_name string ) bool {
963+ root := if b.pref.vroot.len > 0 { b.pref.vroot } else { os.getwd () }
964+ vlib_root := os.norm_path (os.join_path (root, 'vlib' )) + os.path_separator
965+ return os.norm_path (os.abs_path (file_name)).starts_with (vlib_root)
966+ }
967+
904968fn import_module_name (name string ) string {
905969 return name.all_after_last ('.' ).replace ('.' , '_' )
906970}
@@ -956,13 +1020,21 @@ fn (mut b Builder) gen_cleanc_with_cached_core(output_name string, cc string, cc
9561020 mut optional_cached_cache_names := []string {}
9571021 mut optional_cached_module_names := []string {}
9581022 if veb_cached_module_paths.len > 0 && b.has_module ('veb' ) {
959- veb_obj := b.ensure_cached_module_object (cache_dir, veb_cache_name,
960- veb_cached_module_paths, veb_cached_module_names, cc, cc_flags, cc_link_flags,
961- error_limit_flag, true ) or {
1023+ veb_cache_type_modules := b.expand_type_modules_with_imports ( cache_type_module_names ( veb_cache_name,
1024+ veb_cached_module_names))
1025+ veb_obj := if b. has_external_cache_module_name_collision (veb_cache_type_modules) {
9621026 if os.getenv ('V2_TRACE_CACHE' ) != '' {
963- eprintln ('TRACE_CACHE optional_cache=veb reason=${ err } ' )
1027+ eprintln ('TRACE_CACHE optional_cache=veb reason=external_module_name_collision ' )
9641028 }
9651029 ''
1030+ } else {
1031+ b.ensure_cached_module_object (cache_dir, veb_cache_name, veb_cached_module_paths,
1032+ veb_cached_module_names, cc, cc_flags, cc_link_flags, error_limit_flag, true ) or {
1033+ if os.getenv ('V2_TRACE_CACHE' ) != '' {
1034+ eprintln ('TRACE_CACHE optional_cache=veb reason=${err }' )
1035+ }
1036+ ''
1037+ }
9661038 }
9671039 if veb_obj.len > 0 {
9681040 b.print_cached_bundle_modules (veb_cache_name, veb_cached_module_names)
@@ -1288,20 +1360,26 @@ fn (mut b Builder) ensure_cached_module_object(cache_dir string, cache_name stri
12881360 if os.exists (obj_path) && os.exists (stamp_path) {
12891361 if current_stamp := os.read_file (stamp_path) {
12901362 if current_stamp == expected_stamp {
1291- if os.getenv ('V2VERBOSE' ) != '' {
1292- println ('[*] Reusing ${obj_path }' )
1363+ if b.load_cached_called_fn_names (cache_dir, cache_name) {
1364+ if os.getenv ('V2VERBOSE' ) != '' {
1365+ println ('[*] Reusing ${obj_path }' )
1366+ }
1367+ return obj_path
12931368 }
1294- return obj_path
12951369 }
12961370 }
12971371 }
12981372 if b.used_vh_for_parse {
12991373 if os.exists (obj_path) && os.exists (stamp_path) {
1300- return obj_path
1374+ if b.load_cached_called_fn_names (cache_dir, cache_name) {
1375+ return obj_path
1376+ }
1377+ return error ('missing cached ${cache_name } call metadata for .vh parse' )
13011378 }
13021379 return error ('missing cached ${cache_name } object for .vh parse' )
13031380 }
13041381
1382+ cached_called_before := b.cached_called_fn_names.clone ()
13051383 module_source := b.gen_cleanc_source_for_cache (emit_modules, cache_name, use_markused)
13061384 if module_source == '' {
13071385 return error ('failed to generate C source for ${cache_name }' )
@@ -1310,6 +1388,7 @@ fn (mut b Builder) ensure_cached_module_object(cache_dir string, cache_name stri
13101388
13111389 compile_cmd := '${cc } ${cc_flags } -w -Wno-incompatible-function-pointer-types -c "${c_path }" -o "${obj_path }"${error_limit_flag }'
13121390 run_cc_cmd_or_exit (compile_cmd, 'C compilation' , b.pref.show_cc)
1391+ b.write_cached_called_fn_names (cache_dir, cache_name, cached_called_before)
13131392 os.write_file (stamp_path, expected_stamp)!
13141393 return obj_path
13151394}
@@ -1323,20 +1402,26 @@ fn (mut b Builder) ensure_cached_parsed_module_object(cache_dir string, cache_na
13231402 if os.exists (obj_path) && os.exists (stamp_path) {
13241403 if current_stamp := os.read_file (stamp_path) {
13251404 if current_stamp == expected_stamp {
1326- if os.getenv ('V2VERBOSE' ) != '' {
1327- println ('[*] Reusing ${obj_path }' )
1405+ if b.load_cached_called_fn_names (cache_dir, cache_name) {
1406+ if os.getenv ('V2VERBOSE' ) != '' {
1407+ println ('[*] Reusing ${obj_path }' )
1408+ }
1409+ return obj_path
13281410 }
1329- return obj_path
13301411 }
13311412 }
13321413 }
13331414 if b.used_import_vh_for_parse {
13341415 if os.exists (obj_path) && os.exists (stamp_path) {
1335- return obj_path
1416+ if b.load_cached_called_fn_names (cache_dir, cache_name) {
1417+ return obj_path
1418+ }
1419+ return error ('missing cached ${cache_name } call metadata for .vh parse' )
13361420 }
13371421 return error ('missing cached ${cache_name } object for .vh parse' )
13381422 }
13391423
1424+ cached_called_before := b.cached_called_fn_names.clone ()
13401425 mut module_source := b.gen_cleanc_source_for_cache (module_names, cache_name, use_markused)
13411426 if module_source == '' {
13421427 return error ('failed to generate C source for ${cache_name }' )
@@ -1345,6 +1430,7 @@ fn (mut b Builder) ensure_cached_parsed_module_object(cache_dir string, cache_na
13451430
13461431 compile_cmd := '${cc } ${cc_flags } -w -Wno-incompatible-function-pointer-types -c "${c_path }" -o "${obj_path }"${error_limit_flag }'
13471432 run_cc_cmd_or_exit (compile_cmd, 'C compilation' , b.pref.show_cc)
1433+ b.write_cached_called_fn_names (cache_dir, cache_name, cached_called_before)
13481434 os.write_file (stamp_path, expected_stamp)!
13491435 return obj_path
13501436}
@@ -1358,21 +1444,27 @@ fn (mut b Builder) ensure_cached_virtual_module_object(cache_dir string, groups
13581444 if os.exists (obj_path) && os.exists (stamp_path) {
13591445 if current_stamp := os.read_file (stamp_path) {
13601446 if current_stamp == expected_stamp {
1361- if os.getenv ('V2VERBOSE' ) != '' {
1362- println ('[*] Reusing ${obj_path }' )
1447+ if b.load_cached_called_fn_names (cache_dir, virtuals_cache_name) {
1448+ if os.getenv ('V2VERBOSE' ) != '' {
1449+ println ('[*] Reusing ${obj_path }' )
1450+ }
1451+ return obj_path
13631452 }
1364- return obj_path
13651453 }
13661454 }
13671455 }
13681456 if b.used_virtual_vh_for_parse {
13691457 if os.exists (obj_path) && os.exists (stamp_path) {
1370- return obj_path
1458+ if b.load_cached_called_fn_names (cache_dir, virtuals_cache_name) {
1459+ return obj_path
1460+ }
1461+ return error ('missing cached ${virtuals_cache_name } call metadata for .vh parse' )
13711462 }
13721463 return error ('missing cached ${virtuals_cache_name } object for .vh parse' )
13731464 }
13741465
13751466 emit_files := virtual_module_source_files (groups)
1467+ cached_called_before := b.cached_called_fn_names.clone ()
13761468 mut module_source := b.gen_cleanc_source_for_cache_files (['main' ], emit_files,
13771469 virtuals_cache_name, use_markused)
13781470 if module_source == '' {
@@ -1382,6 +1474,7 @@ fn (mut b Builder) ensure_cached_virtual_module_object(cache_dir string, groups
13821474
13831475 compile_cmd := '${cc } ${cc_flags } -w -Wno-incompatible-function-pointer-types -c "${c_path }" -o "${obj_path }"${error_limit_flag }'
13841476 run_cc_cmd_or_exit (compile_cmd, 'C compilation' , b.pref.show_cc)
1477+ b.write_cached_called_fn_names (cache_dir, virtuals_cache_name, cached_called_before)
13851478 os.write_file (stamp_path, expected_stamp)!
13861479 return obj_path
13871480}
@@ -1738,6 +1831,13 @@ fn parse_flag_directive_line_with_pref(line string, file_path string, prefs &pre
17381831
17391832fn parse_flag_directive_line_with_context (line string , file_path string , target_os string , prefs & pref.Preferences) ? string {
17401833 trimmed := line.trim_space ()
1834+ if trimmed.starts_with ('#pkgconfig' ) {
1835+ if prefs != unsafe { nil } && prefs.is_cross_target () {
1836+ return none
1837+ }
1838+ rest := trimmed['#pkgconfig' .len..].trim_space ()
1839+ return resolve_pkgconfig_directive_flags (rest)
1840+ }
17411841 if ! trimmed.starts_with ('#flag' ) {
17421842 return none
17431843 }
@@ -1772,6 +1872,22 @@ fn parse_flag_directive_line_with_context(line string, file_path string, target_
17721872 return normalize_flag_value_for_file (rest, file_path)
17731873}
17741874
1875+ fn resolve_pkgconfig_directive_flags (value string ) ? string {
1876+ if value == '' {
1877+ return none
1878+ }
1879+ args := if value.contains ('--' ) {
1880+ value.fields ()
1881+ } else {
1882+ '--cflags --libs ${value }' .fields ()
1883+ }
1884+ flags := pref.pkgconfig_result (args) or { return none }
1885+ if flags == '' {
1886+ return none
1887+ }
1888+ return flags
1889+ }
1890+
17751891fn flag_references_missing_file (flag string , include_flags []string ) bool {
17761892 for tok in flag.fields () {
17771893 clean := tok.trim ('"' ).trim ("'" )
@@ -2027,6 +2143,12 @@ fn comptime_cond_matches_with_context(cond string, target_os string, prefs &pref
20272143 }
20282144 return pref.comptime_optional_flag_value (prefs, optional_name)
20292145 }
2146+ if pkg_name := pkgconfig_cond_name (trimmed) {
2147+ if prefs != unsafe { nil } && prefs.is_cross_target () {
2148+ return false
2149+ }
2150+ return pref.comptime_pkgconfig_value (pkg_name)
2151+ }
20302152 if prefs != unsafe { nil } {
20312153 return flag_os_matches (trimmed, target_os) || flag_pref_matches (trimmed, prefs)
20322154 }
@@ -2055,6 +2177,22 @@ fn comptime_cond_matches_with_context(cond string, target_os string, prefs &pref
20552177 }
20562178}
20572179
2180+ fn pkgconfig_cond_name (cond string ) ? string {
2181+ trimmed := cond.trim_space ()
2182+ if ! trimmed.starts_with (r '$pkgconfig(' ) || ! trimmed.ends_with (')' ) {
2183+ return none
2184+ }
2185+ arg := trimmed[r '$pkgconfig(' .len..trimmed.len - 1 ].trim_space ()
2186+ if arg.len < 2 {
2187+ return none
2188+ }
2189+ quote := arg[0 ]
2190+ if (quote != `'` && quote != `"` ) || arg[arg.len - 1 ] != quote {
2191+ return none
2192+ }
2193+ return arg[1 ..arg.len - 1 ]
2194+ }
2195+
20582196fn optional_user_ct_flag_name (cond string ) ? string {
20592197 trimmed := cond.trim_space ()
20602198 if ! trimmed.ends_with ('?' ) {
0 commit comments