From a22ed30f422e0faf9c8064ab5808e8f87ad3c269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Marc=CC=A7al?= Date: Fri, 1 Nov 2024 12:15:29 -0300 Subject: [PATCH 01/15] Support System Library --- swiftpkg/internal/clang_files.bzl | 20 +++++++- swiftpkg/internal/pkginfos.bzl | 11 +++++ swiftpkg/internal/swiftpkg_build_files.bzl | 57 ++++++++++++++++++++-- 3 files changed, 83 insertions(+), 5 deletions(-) diff --git a/swiftpkg/internal/clang_files.bzl b/swiftpkg/internal/clang_files.bzl index f96757b14..1533f9c81 100644 --- a/swiftpkg/internal/clang_files.bzl +++ b/swiftpkg/internal/clang_files.bzl @@ -107,6 +107,18 @@ def _is_public_modulemap(path): basename = paths.basename(path) return basename == "module.modulemap" +def _is_include_root_modulemap(path): + """Determines whether the specified path is to a modulemap file that is \ + located in the include directory. + + Args: + path: A path `string`. + + Returns: + A `bool` indicating whether the path is a modulemap file in the include directory. + """ + return paths.dirname(path).endswith("include") + def _get_hdr_paths_from_modulemap(repository_ctx, modulemap_path, module_name): """Retrieves the list of headers declared in the specified modulemap file \ for the specified module. @@ -147,7 +159,6 @@ def _get_hdr_paths_from_modulemap(repository_ctx, modulemap_path, module_name): hdr_path = paths.join(modulemap_dirname, cdecl.path) normalized_hdr_path = paths.normalize(hdr_path) hdrs.append(normalized_hdr_path) - return hdrs def _is_under_path(path, parent): @@ -266,6 +277,12 @@ def _collect_files( # the referenced headers are included. For now, we will just add the # modulemap hdrs to the ones that we have already found. if modulemap_orig_path != None: + # If Swift Package Library provides a modulemap file in the include + # directory, then we should include all of the headers that are listed + # in the modulemap file. + if module_name == "libllbuild": + hdrs_set = sets.make() + mm_hdrs = _get_hdr_paths_from_modulemap( repository_ctx, modulemap_orig_path, @@ -284,6 +301,7 @@ def _collect_files( mm_hdrs_set = sets.make(mm_hdrs) hdrs_set = sets.union(hdrs_set, mm_hdrs_set) + print("After: {}".format(hdrs_set)) # If we have not found any public header files for a library module, then # promote any headers that are listed in the srcs. diff --git a/swiftpkg/internal/pkginfos.bzl b/swiftpkg/internal/pkginfos.bzl index 08aa9a413..91acef181 100644 --- a/swiftpkg/internal/pkginfos.bzl +++ b/swiftpkg/internal/pkginfos.bzl @@ -375,6 +375,17 @@ def _new_target_from_json_maps( pkg_path = pkg_path, sources = clang_src_info.explicit_srcs + clang_src_info.hdrs, ) + elif module_type == module_types.system_library: + clang_src_info = _new_clang_src_info_from_sources( + repository_ctx = repository_ctx, + pkg_path = pkg_path, + c99name = c99name, + target_path = target_path, + source_paths = source_paths, + public_hdrs_path = public_hdrs_path, + exclude_paths = exclude_paths, + other_hdr_srch_paths = [], + ) return _new_target( name = target_name, diff --git a/swiftpkg/internal/swiftpkg_build_files.bzl b/swiftpkg/internal/swiftpkg_build_files.bzl index 3075f1889..8457de48c 100644 --- a/swiftpkg/internal/swiftpkg_build_files.bzl +++ b/swiftpkg/internal/swiftpkg_build_files.bzl @@ -83,10 +83,12 @@ def _swift_target_build_file(pkg_ctx, target): fail_if_not_found = False, ) - if not dep_target or dep_target.type != target_types.macro: + if dep_target and dep_target.type == target_types.macro: + macro_targets.append(dep_target) + else: target_deps.append(target_dep) continue - macro_targets.append(dep_target) + if macro_targets: attrs["plugins"] = [ @@ -154,7 +156,7 @@ def _swift_target_build_file(pkg_ctx, target): _update_attr_list("srcs", ":{}".format( swift_apple_res_bundle_info.accessor_label_name, )) - + if is_library_target: load_stmts = [swift_library_load_stmt] decls = [_swift_library_from_target(target, attrs)] @@ -433,6 +435,7 @@ def _clang_target_build_file(repository_ctx, pkg_ctx, target): load_stmts = [swiftpkg_generate_modulemap_load_stmt] modulemap_target_name = pkginfo_targets.modulemap_label_name(bzl_target_name) noop_modulemap = clang_src_info.modulemap_path != None + modulemap_attrs = { "deps": bzl_selects.to_starlark(modulemap_deps), "hdrs": clang_src_info.hdrs, @@ -440,6 +443,7 @@ def _clang_target_build_file(repository_ctx, pkg_ctx, target): "noop": noop_modulemap, "visibility": ["//:__subpackages__"], } + decls.append( build_decls.new( kind = swiftpkg_kinds.generate_modulemap, @@ -641,7 +645,52 @@ def _starlarkify_clang_attrs(repository_ctx, attrs): # buildifier: disable=unused-variable def _system_library_build_file(target): - # GH009(chuck): Implement _system_library_build_file + attrs = { + "visibility": ["//:__subpackages__"], + } + + # These flags are used by SPM when compiling clang modules. + copts = [ + # Enable 'blocks' language feature + "-fblocks", + # Synthesize retain and release calls for Objective-C pointers + "-fobjc-arc", + # Enable support for PIC macros + "-fPIC", + # The SWIFT_PACKAGE define is a magical value that SPM uses when it + # builds clang libraries that will be used as Swift modules. + "-DSWIFT_PACKAGE=1", + ] + attrs["copts"] = copts + + module_map_file = target.clang_src_info.modulemap_path + attrs["module_map"] = module_map_file + + # System library targets must include a modulemap file. + # https://github.com/swiftlang/swift-package-manager/blob/12c14222fdde2ffd8303a2c805fed1b1eb802e5c/Sources/PackageLoading/PackageBuilder.swift#L853 + if not module_map_file: + fail("Expected a modulemap file for a system library target. name: ", target.name) + + header_files = target.clang_src_info.hdrs + attrs["hdrs"] = header_files + + bzl_target_name = pkginfo_targets.bazel_label_name(target) + + decls = [ + build_decls.new( + kind = objc_kinds.library, + name = bzl_target_name, + attrs = attrs, + ) + ] + + return build_files.new( + decls = decls, + ) + + print(decls) + fail("System library targets are not yet supported.") + return None # MARK: - Apple xcframework Targets From a9fe850f8a97033de6c492e9d3f45e223bec68c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Marc=CC=A7al?= Date: Fri, 1 Nov 2024 12:18:43 -0300 Subject: [PATCH 02/15] allow string literal to module name --- .../internal/modulemap_parser/collect_module.bzl | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/swiftpkg/internal/modulemap_parser/collect_module.bzl b/swiftpkg/internal/modulemap_parser/collect_module.bzl index 85ceb99c2..1385ffed2 100644 --- a/swiftpkg/internal/modulemap_parser/collect_module.bzl +++ b/swiftpkg/internal/modulemap_parser/collect_module.bzl @@ -91,15 +91,18 @@ def _process_module_tokens(parsed_tokens, prefix_tokens, is_submodule): return None, err consumed_count += 1 - module_id_or_asterisk_token, err = tokens.get(parsed_tokens, 1, count = tlen) + module_declaration_identifier_token, err = tokens.get(parsed_tokens, 1, count = tlen) + if err != None: return None, err consumed_count += 1 - if not tokens.is_a(module_id_or_asterisk_token, tts.identifier) and \ - not tokens.is_a(module_id_or_asterisk_token, tts.operator, operators.asterisk): + if not tokens.is_a(module_declaration_identifier_token, tts.identifier) and \ + not tokens.is_a(module_declaration_identifier_token, tts.operator, operators.asterisk) and \ + not tokens.is_a(module_declaration_identifier_token, tts.string_literal): return None, errors.new( - "Expected module identifier or asterisk, but was {}.".format( - module_id_or_asterisk_token.type, + "Expected module identifier, asterisk or string_literal, but was {} with value {}.".format( + module_declaration_identifier_token.type, + module_declaration_identifier_token.value, ), ) @@ -146,7 +149,7 @@ def _process_module_tokens(parsed_tokens, prefix_tokens, is_submodule): # Create the declaration decl = declarations.module( - module_id = module_id_or_asterisk_token.value, + module_id = module_declaration_identifier_token.value, explicit = explicit, framework = framework, attributes = attributes, From 0eb849beedc48b14e4e7c63ef213dc37d2db8acf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Marc=CC=A7al?= Date: Fri, 1 Nov 2024 12:20:03 -0300 Subject: [PATCH 03/15] remove debug code --- swiftpkg/internal/swiftpkg_build_files.bzl | 5 ----- 1 file changed, 5 deletions(-) diff --git a/swiftpkg/internal/swiftpkg_build_files.bzl b/swiftpkg/internal/swiftpkg_build_files.bzl index 8457de48c..7d6950cd6 100644 --- a/swiftpkg/internal/swiftpkg_build_files.bzl +++ b/swiftpkg/internal/swiftpkg_build_files.bzl @@ -688,11 +688,6 @@ def _system_library_build_file(target): decls = decls, ) - print(decls) - fail("System library targets are not yet supported.") - - return None - # MARK: - Apple xcframework Targets def _xcframework_import_build_file(target, artifact_info): From c66dc7d5e2474fc563811cf50055520ffbecb997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Marc=CC=A7al?= Date: Tue, 5 Nov 2024 00:53:02 -0300 Subject: [PATCH 04/15] Add all headers listed in clang lib modulemap --- swiftpkg/internal/clang_files.bzl | 33 ++++++++++--------------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/swiftpkg/internal/clang_files.bzl b/swiftpkg/internal/clang_files.bzl index 1533f9c81..a7cbc539b 100644 --- a/swiftpkg/internal/clang_files.bzl +++ b/swiftpkg/internal/clang_files.bzl @@ -107,18 +107,6 @@ def _is_public_modulemap(path): basename = paths.basename(path) return basename == "module.modulemap" -def _is_include_root_modulemap(path): - """Determines whether the specified path is to a modulemap file that is \ - located in the include directory. - - Args: - path: A path `string`. - - Returns: - A `bool` indicating whether the path is a modulemap file in the include directory. - """ - return paths.dirname(path).endswith("include") - def _get_hdr_paths_from_modulemap(repository_ctx, modulemap_path, module_name): """Retrieves the list of headers declared in the specified modulemap file \ for the specified module. @@ -143,17 +131,16 @@ def _get_hdr_paths_from_modulemap(repository_ctx, modulemap_path, module_name): if len(module_decls) == 0: fail("No module declarations were found in %s." % (modulemap_path)) - # Look for a module declaration that matches the module name. Only select - # headers from that module if it is found. Otherwise, we collect all of the - # headers in all of the module declarations at the top-level. - module_decl = lists.find(module_decls, lambda m: m.module_id == module_name) - if module_decl != None: - module_decls = [module_decl] - modulemap_dirname = paths.dirname(modulemap_path) hdrs = [] for module_decl in module_decls: for cdecl in module_decl.members: + if cdecl.decl_type == dts.umbrella_header: + # If the module has an umbrella header, then it is the only public header. + # All other headers are private. + umbrella_hdr = cdecl.path + normalized_umbrella_hdr = paths.normalize(paths.join(modulemap_dirname, umbrella_hdr)) + hdrs.append(normalized_umbrella_hdr) if cdecl.decl_type == dts.single_header and not cdecl.private and not cdecl.textual: # Resolve the path relative to the modulemap hdr_path = paths.join(modulemap_dirname, cdecl.path) @@ -280,8 +267,6 @@ def _collect_files( # If Swift Package Library provides a modulemap file in the include # directory, then we should include all of the headers that are listed # in the modulemap file. - if module_name == "libllbuild": - hdrs_set = sets.make() mm_hdrs = _get_hdr_paths_from_modulemap( repository_ctx, @@ -300,8 +285,10 @@ def _collect_files( ]) mm_hdrs_set = sets.make(mm_hdrs) - hdrs_set = sets.union(hdrs_set, mm_hdrs_set) - print("After: {}".format(hdrs_set)) + if len(mm_hdrs) > 0: + # If we have found public headers in the modulemap, then we should set them as the public headers. + srcs_set = sets.union(srcs_set, hdrs_set) + hdrs_set = mm_hdrs_set # If we have not found any public header files for a library module, then # promote any headers that are listed in the srcs. From 5b2ad2ebb3c3dc050b74e46ba482f1bb541d8f13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Marc=CC=A7al?= Date: Wed, 6 Nov 2024 14:46:40 -0300 Subject: [PATCH 05/15] add linkopts to swift target build file --- swiftpkg/internal/swiftpkg_build_files.bzl | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/swiftpkg/internal/swiftpkg_build_files.bzl b/swiftpkg/internal/swiftpkg_build_files.bzl index 7d6950cd6..7169af714 100644 --- a/swiftpkg/internal/swiftpkg_build_files.bzl +++ b/swiftpkg/internal/swiftpkg_build_files.bzl @@ -22,7 +22,7 @@ def _new_for_target(repository_ctx, pkg_ctx, target, artifact_infos = []): if target.module_type == module_types.clang: return _clang_target_build_file(repository_ctx, pkg_ctx, target) elif target.module_type == module_types.swift: - return _swift_target_build_file(pkg_ctx, target) + return _swift_target_build_file(repository_ctx, pkg_ctx, target) elif target.module_type == module_types.system_library: return _system_library_build_file(target) elif target.module_type == module_types.binary: @@ -39,7 +39,7 @@ def _new_for_target(repository_ctx, pkg_ctx, target, artifact_infos = []): # MARK: - Swift Target -def _swift_target_build_file(pkg_ctx, target): +def _swift_target_build_file(repository_ctx, pkg_ctx, target): if target.swift_src_info == None: fail("Expected a `swift_src_info`. name: ", target.name) @@ -113,6 +113,15 @@ def _swift_target_build_file(pkg_ctx, target): "-DSWIFT_PACKAGE", ] + linkopts = [] + if target.linker_settings != None: + linkopts.extend(lists.flatten([ + bzl_selects.new_from_build_setting(bs) + for bs in target.linker_settings.linked_libraries + ])) + if linkopts: + attrs["linkopts"] = _starlarkify_clang_attrs(repository_ctx, {"linkopts": linkopts})["linkopts"] + # GH046: Support plugins. is_library_target = lists.contains([target_types.library, target_types.regular], target.type) From 745c67b916a328ffdbc0021532b6ff1bee65f52b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Marc=CC=A7al?= Date: Wed, 6 Nov 2024 19:55:46 -0300 Subject: [PATCH 06/15] fix public header folder search --- swiftpkg/internal/clang_files.bzl | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/swiftpkg/internal/clang_files.bzl b/swiftpkg/internal/clang_files.bzl index a7cbc539b..c1224eada 100644 --- a/swiftpkg/internal/clang_files.bzl +++ b/swiftpkg/internal/clang_files.bzl @@ -299,14 +299,13 @@ def _collect_files( sets.insert(hdrs_set, src) srcs_set = sets.difference(srcs_set, hdrs_set) - # If public includes were specified, then use them. Otherwise, add every - # directory that holds a public header file and add any magical public - # header directories that we find. + # If public includes were specified, then use them. Otherwise, add + # any magical public header directories that we find. if len(public_includes) == 0: - public_includes = [paths.dirname(hdr) for hdr in sets.to_list(hdrs_set)] + public_header_folders = ["{}/".format(paths.dirname(hdr)) for hdr in sets.to_list(hdrs_set)] magical_public_hdr_dirs = [] - for pi in public_includes: - magical_public_hdr_dir = clang_files.find_magical_public_hdr_dir(pi) + for public_header_folder in public_header_folders: + magical_public_hdr_dir = _find_magical_public_hdr_dir(public_header_folder) if magical_public_hdr_dir != None: magical_public_hdr_dirs.append(magical_public_hdr_dir) public_includes.extend(magical_public_hdr_dirs) From 9e8501945de785513fb754d852c1051c49ca72b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Marc=CC=A7al?= Date: Wed, 6 Nov 2024 20:01:21 -0300 Subject: [PATCH 07/15] comment --- swiftpkg/internal/clang_files.bzl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/swiftpkg/internal/clang_files.bzl b/swiftpkg/internal/clang_files.bzl index c1224eada..a86c36baf 100644 --- a/swiftpkg/internal/clang_files.bzl +++ b/swiftpkg/internal/clang_files.bzl @@ -299,8 +299,8 @@ def _collect_files( sets.insert(hdrs_set, src) srcs_set = sets.difference(srcs_set, hdrs_set) - # If public includes were specified, then use them. Otherwise, add - # any magical public header directories that we find. + # If public includes were specified, then use them. + # Otherwise, add any magical public header directories that we find. if len(public_includes) == 0: public_header_folders = ["{}/".format(paths.dirname(hdr)) for hdr in sets.to_list(hdrs_set)] magical_public_hdr_dirs = [] From 7583f753a174e48b8966561968986d26082b4cae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Marc=CC=A7al?= Date: Thu, 7 Nov 2024 00:58:17 -0300 Subject: [PATCH 08/15] accept multiple modulemap files but keep the one in include folder --- swiftpkg/internal/clang_files.bzl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/swiftpkg/internal/clang_files.bzl b/swiftpkg/internal/clang_files.bzl index a86c36baf..2ffac6cb4 100644 --- a/swiftpkg/internal/clang_files.bzl +++ b/swiftpkg/internal/clang_files.bzl @@ -249,10 +249,10 @@ def _collect_files( sets.insert(srcs_set, path) elif ext == ".modulemap" and _is_public_modulemap(path): if modulemap != None: - fail("Found multiple modulemap files. {first} {second}".format( - first = modulemap, - second = path, - )) + if _is_under_path(path, "include/"): + # If we find a modulemap in the include directory, then we should use that one. + modulemap = path + modulemap_orig_path = orig_path modulemap_orig_path = orig_path modulemap = path else: From 4662b0dfdaf022e873a89b93c45297bc078f74d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Marc=CC=A7al?= Date: Sat, 4 Jan 2025 00:42:26 -0300 Subject: [PATCH 09/15] add extra fixes --- swiftpkg/internal/clang_files.bzl | 11 ++--------- swiftpkg/internal/pkginfos.bzl | 12 ++++++++++-- swiftpkg/internal/swiftpkg_build_files.bzl | 3 --- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/swiftpkg/internal/clang_files.bzl b/swiftpkg/internal/clang_files.bzl index 954853b24..32d5d21d5 100644 --- a/swiftpkg/internal/clang_files.bzl +++ b/swiftpkg/internal/clang_files.bzl @@ -118,7 +118,7 @@ def _is_public_modulemap(path, public_includes = []): return False -def _get_hdr_paths_from_modulemap(repository_ctx, modulemap_path, module_name): +def _get_hdr_paths_from_modulemap(repository_ctx, modulemap_path): """Retrieves the list of headers declared in the specified modulemap file \ for the specified module. @@ -128,7 +128,6 @@ def _get_hdr_paths_from_modulemap(repository_ctx, modulemap_path, module_name): Args: repository_ctx: A `repository_ctx` instance. modulemap_path: A path `string` to the `module.modulemap` file. - module_name: The name of the module. Returns: A `list` of path `string` values. @@ -262,11 +261,6 @@ def _collect_files( orig_path, public_includes = public_includes, ): - if modulemap != None: - if _is_under_path(path, "include/"): - # If we find a modulemap in the include directory, then we should use that one. - modulemap = path - modulemap_orig_path = orig_path modulemap_orig_path = orig_path modulemap = path else: @@ -284,8 +278,7 @@ def _collect_files( mm_hdrs = _get_hdr_paths_from_modulemap( repository_ctx, - modulemap_orig_path, - module_name, + modulemap_orig_path ) mm_hdrs = _relativize_paths(mm_hdrs, relative_to) diff --git a/swiftpkg/internal/pkginfos.bzl b/swiftpkg/internal/pkginfos.bzl index 91acef181..69019c907 100644 --- a/swiftpkg/internal/pkginfos.bzl +++ b/swiftpkg/internal/pkginfos.bzl @@ -382,7 +382,7 @@ def _new_target_from_json_maps( c99name = c99name, target_path = target_path, source_paths = source_paths, - public_hdrs_path = public_hdrs_path, + public_hdrs_path = "", # System libraries have their headers/modulemaps in the library root path, so the root path is the public path exclude_paths = exclude_paths, other_hdr_srch_paths = [], ) @@ -1078,6 +1078,14 @@ def _new_clang_src_info_from_sources( paths.normalize(paths.join(abs_target_path, public_hdrs_path)), ) + # If the Swift package manifest does not specify a public headers path, + # use the default "include" directory, if it exists. + # This copies the behavior of the canonical Swift Package Manager implementation. + # https://developer.apple.com/documentation/packagedescription/target/publicheaderspath + if public_hdrs_path == None: + if repository_files.path_exists(repository_ctx, paths.join(abs_target_path, "include")): + public_includes.append(paths.join(abs_target_path, "include")) + # If the Swift package manifest has explicit source paths, respect them. # (Be sure to include any explicitly specified include directories.) # Otherwise, use all of the source files under the target path. @@ -1131,7 +1139,7 @@ def _new_clang_src_info_from_sources( for pi in public_includes ], relative_to = pkg_path, - ) + ) # The `cc_library` rule compiles each source file (.c, .cc) separately only providing the # headers. There are some clang modules (e.g., diff --git a/swiftpkg/internal/swiftpkg_build_files.bzl b/swiftpkg/internal/swiftpkg_build_files.bzl index ec70ffba8..d3642a085 100644 --- a/swiftpkg/internal/swiftpkg_build_files.bzl +++ b/swiftpkg/internal/swiftpkg_build_files.bzl @@ -658,9 +658,6 @@ def _starlarkify_clang_attrs(repository_ctx, attrs): # MARK: - System Library Targets -# GH009(chuck): Remove unused-variable directives - -# buildifier: disable=unused-variable def _system_library_build_file(target): attrs = { "visibility": ["//:__subpackages__"], From 2a58117769a201088fdb077583b1e6ddae6d535b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Marc=CC=A7al?= Date: Sat, 4 Jan 2025 00:55:09 -0300 Subject: [PATCH 10/15] remove extra changes --- swiftpkg/internal/pkginfos.bzl | 2 +- swiftpkg/internal/swiftpkg_build_files.bzl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/swiftpkg/internal/pkginfos.bzl b/swiftpkg/internal/pkginfos.bzl index 69019c907..f72cc4383 100644 --- a/swiftpkg/internal/pkginfos.bzl +++ b/swiftpkg/internal/pkginfos.bzl @@ -1139,7 +1139,7 @@ def _new_clang_src_info_from_sources( for pi in public_includes ], relative_to = pkg_path, - ) + ) # The `cc_library` rule compiles each source file (.c, .cc) separately only providing the # headers. There are some clang modules (e.g., diff --git a/swiftpkg/internal/swiftpkg_build_files.bzl b/swiftpkg/internal/swiftpkg_build_files.bzl index d3642a085..a33d3e86a 100644 --- a/swiftpkg/internal/swiftpkg_build_files.bzl +++ b/swiftpkg/internal/swiftpkg_build_files.bzl @@ -163,7 +163,7 @@ def _swift_target_build_file(repository_ctx, pkg_ctx, target): _update_attr_list("srcs", ":{}".format( swift_apple_res_bundle_info.accessor_label_name, )) - + if is_library_target: load_stmts = [swift_library_load_stmt] decls = [_swift_library_from_target(target, attrs)] From a20242c944fb899fdb037027080f33651c18b487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Marc=CC=A7al?= Date: Mon, 6 Jan 2025 14:20:26 -0300 Subject: [PATCH 11/15] Public Headers path: If this is nil, the directory is set to include --- swiftpkg/internal/pkginfos.bzl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/swiftpkg/internal/pkginfos.bzl b/swiftpkg/internal/pkginfos.bzl index 08aa9a413..3cc67ec0a 100644 --- a/swiftpkg/internal/pkginfos.bzl +++ b/swiftpkg/internal/pkginfos.bzl @@ -1067,6 +1067,14 @@ def _new_clang_src_info_from_sources( paths.normalize(paths.join(abs_target_path, public_hdrs_path)), ) + # If the Swift package manifest does not specify a public headers path, + # use the default "include" directory, if it exists. + # This copies the behavior of the canonical Swift Package Manager implementation. + # https://developer.apple.com/documentation/packagedescription/target/publicheaderspath + if public_hdrs_path == None: + if repository_files.path_exists(repository_ctx, paths.join(abs_target_path, "include")): + public_includes.append(paths.join(abs_target_path, "include")) + # If the Swift package manifest has explicit source paths, respect them. # (Be sure to include any explicitly specified include directories.) # Otherwise, use all of the source files under the target path. From f63fde0e74a9834d5469cd9aad7be6465a47a625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Marc=CC=A7al?= Date: Thu, 23 Jan 2025 10:58:47 -0300 Subject: [PATCH 12/15] Combine include path search with public_hdrs_path check --- swiftpkg/internal/pkginfos.bzl | 17 +++++++++-------- swiftpkg/tests/swiftpkg_build_files_tests.bzl | 1 - 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/swiftpkg/internal/pkginfos.bzl b/swiftpkg/internal/pkginfos.bzl index 3cc67ec0a..042d392f1 100644 --- a/swiftpkg/internal/pkginfos.bzl +++ b/swiftpkg/internal/pkginfos.bzl @@ -1061,19 +1061,20 @@ def _new_clang_src_info_from_sources( paths.join(pkg_path, target_path), ) + # If the Swift package manifest does not specify a public headers path, + # use the default "include" directory, if it exists. + # This copies the behavior of the canonical Swift Package Manager implementation. + # https://developer.apple.com/documentation/packagedescription/target/publicheaderspath public_includes = [] if public_hdrs_path != None: public_includes.append( paths.normalize(paths.join(abs_target_path, public_hdrs_path)), ) - - # If the Swift package manifest does not specify a public headers path, - # use the default "include" directory, if it exists. - # This copies the behavior of the canonical Swift Package Manager implementation. - # https://developer.apple.com/documentation/packagedescription/target/publicheaderspath - if public_hdrs_path == None: - if repository_files.path_exists(repository_ctx, paths.join(abs_target_path, "include")): - public_includes.append(paths.join(abs_target_path, "include")) + elif repository_files.path_exists( + repository_ctx, + paths.join(abs_target_path, "include"), + ): + public_includes.append(paths.join(abs_target_path, "include")) # If the Swift package manifest has explicit source paths, respect them. # (Be sure to include any explicitly specified include directories.) diff --git a/swiftpkg/tests/swiftpkg_build_files_tests.bzl b/swiftpkg/tests/swiftpkg_build_files_tests.bzl index de7c889b7..2487166a0 100644 --- a/swiftpkg/tests/swiftpkg_build_files_tests.bzl +++ b/swiftpkg/tests/swiftpkg_build_files_tests.bzl @@ -189,7 +189,6 @@ _pkg_info = pkginfos.new( exclude_paths = [ "src/do_not_include_me.cc", ], - public_hdrs_path = "include", dependencies = [], clang_settings = pkginfos.new_clang_settings([ pkginfos.new_build_setting( From b226d96479a4f1528abe90ea0d24f9f6addb8504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Marc=CC=A7al?= Date: Thu, 23 Jan 2025 11:56:22 -0300 Subject: [PATCH 13/15] add new clang lib to pkg_manifest_minimal --- .../pkg_manifest_minimal/Package.resolved | 12 +-- examples/pkg_manifest_minimal/Package.swift | 1 + .../Sources/MyExecutable/BUILD.bazel | 1 + .../Sources/MyExecutable/MyExecutable.swift | 5 +- examples/pkg_manifest_minimal/do_test | 13 ++- examples/pkg_manifest_minimal/res_log.yml | 72 ++++++++++++++++ .../my_local_package/Package.swift | 15 +++- .../include/MyClangLibrary/API.h | 62 +++++++++++++ .../Sources/FarewellFramework/src/lib.c | 86 +++++++++++++++++++ .../Sources/PrintFarewell/main.swift | 7 ++ 10 files changed, 262 insertions(+), 12 deletions(-) create mode 100644 examples/pkg_manifest_minimal/res_log.yml create mode 100644 examples/pkg_manifest_minimal/third_party/my_local_package/Sources/FarewellFramework/include/MyClangLibrary/API.h create mode 100644 examples/pkg_manifest_minimal/third_party/my_local_package/Sources/FarewellFramework/src/lib.c create mode 100644 examples/pkg_manifest_minimal/third_party/my_local_package/Sources/PrintFarewell/main.swift diff --git a/examples/pkg_manifest_minimal/Package.resolved b/examples/pkg_manifest_minimal/Package.resolved index fd38c1a23..a9b8d59cb 100644 --- a/examples/pkg_manifest_minimal/Package.resolved +++ b/examples/pkg_manifest_minimal/Package.resolved @@ -5,8 +5,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-argument-parser", "state" : { - "revision" : "c8ed701b513cf5177118a175d85fbbbcd707ab41", - "version" : "1.3.0" + "revision" : "41982a3656a71c768319979febd796c6fd111d5c", + "version" : "1.5.0" } }, { @@ -14,8 +14,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-log", "state" : { - "revision" : "e97a6fcb1ab07462881ac165fdbb37f067e205d5", - "version" : "1.5.4" + "revision" : "96a2f8a0fa41e9e09af4585e2724c4e825410b91", + "version" : "1.6.2" } }, { @@ -23,8 +23,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/nicklockwood/SwiftFormat", "state" : { - "revision" : "607c7057e55cf008e3841696ea7083622e36164f", - "version" : "0.53.2" + "revision" : "468a7d32dedc8d352c191594b3b45d9fd8ba291b", + "version" : "0.55.5" } } ], diff --git a/examples/pkg_manifest_minimal/Package.swift b/examples/pkg_manifest_minimal/Package.swift index d2f417405..cc4d1b2f4 100644 --- a/examples/pkg_manifest_minimal/Package.swift +++ b/examples/pkg_manifest_minimal/Package.swift @@ -8,6 +8,7 @@ let package = Package( .package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"), .package(url: "https://github.com/apple/swift-log", from: "1.6.2"), .package(url: "https://github.com/nicklockwood/SwiftFormat", from: "0.55.4"), + .package(path: "third_party/my_local_package"), .package(path: "third_party/NotThatAmazingModule"), ] diff --git a/examples/pkg_manifest_minimal/Sources/MyExecutable/BUILD.bazel b/examples/pkg_manifest_minimal/Sources/MyExecutable/BUILD.bazel index 0a2bf86dc..c71a171da 100644 --- a/examples/pkg_manifest_minimal/Sources/MyExecutable/BUILD.bazel +++ b/examples/pkg_manifest_minimal/Sources/MyExecutable/BUILD.bazel @@ -7,6 +7,7 @@ swift_binary( visibility = ["//visibility:public"], deps = [ "//Sources/MyLibrary", + "@swiftpkg_my_local_package//:FarewellFramework", "@swiftpkg_my_local_package//:GreetingsFramework", "@swiftpkg_notthatamazingmodule//:NotThatAmazingModule", "@swiftpkg_swift_argument_parser//:ArgumentParser", diff --git a/examples/pkg_manifest_minimal/Sources/MyExecutable/MyExecutable.swift b/examples/pkg_manifest_minimal/Sources/MyExecutable/MyExecutable.swift index 36a075e06..7be2014f7 100644 --- a/examples/pkg_manifest_minimal/Sources/MyExecutable/MyExecutable.swift +++ b/examples/pkg_manifest_minimal/Sources/MyExecutable/MyExecutable.swift @@ -1,4 +1,5 @@ import ArgumentParser +import FarewellFramework import GreetingsFramework import MyLibrary import NotThatAmazingModule @@ -10,6 +11,8 @@ struct MyExecutable: AsyncParsableCommand { print(namedGreeting.value) let complexClass = ComplexClass(name: "Olivia", age: 30, favoriteColors: ["blue"]) - print(complexClass.greet()) + complexClass.greet() + let farewellMessage = FarewellFramework.myclang_get_farewell_message(MYCLANG_FAREWELL_GOODBYE) + print(String(cString: farewellMessage!)) } } diff --git a/examples/pkg_manifest_minimal/do_test b/examples/pkg_manifest_minimal/do_test index f15f4c903..325189602 100755 --- a/examples/pkg_manifest_minimal/do_test +++ b/examples/pkg_manifest_minimal/do_test @@ -9,10 +9,13 @@ script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null && pwd)" bazel="${BIT_BAZEL_BINARY:-bazel}" assert_match() { - local pattern=${1} + local expected=${1} local actual="${2}" - local err_msg="Expected to match. pattern: ${pattern}, actual: ${actual}" - [[ "${actual}" =~ ${pattern} ]] || (echo >&2 "${err_msg}" && exit 1) + local err_msg="Expected to match. expected: ${expected}, actual: ${actual}" + if [[ "${expected}" != "${actual}" ]]; then + echo >&2 "${err_msg}" + exit 1 + fi } # Generate Swift external deps and update build files @@ -23,7 +26,9 @@ assert_match() { # Run MyExecutable target output="$("${bazel}" run //Sources/MyExecutable)" -assert_match "Good morning, World!" "${output}" +assert_match "Good morning, World! +Hello, my name is Olivia and I'm 30 years old. +Goodbye" "${output}" # Run old-style executable in my_local_package output="$("${bazel}" run @swiftpkg_my_local_package//:print-greeting)" diff --git a/examples/pkg_manifest_minimal/res_log.yml b/examples/pkg_manifest_minimal/res_log.yml new file mode 100644 index 000000000..a3cd3b405 --- /dev/null +++ b/examples/pkg_manifest_minimal/res_log.yml @@ -0,0 +1,72 @@ +--- +name: //Sources/MyExecutable +kind: swift_binary +imports: + - ArgumentParser + - FarewellFramework + - GreetingsFramework + - MyLibrary + - NotThatAmazingModule +local_resolution: + - module: MyLibrary + label: //Sources/MyLibrary +external_resolution: + modules: + - ArgumentParser + - FarewellFramework + - GreetingsFramework + - NotThatAmazingModule + products: + - identity: my_local_package + name: FarewellFramework + label: '@swiftpkg_my_local_package//:FarewellFramework' + - identity: my_local_package + name: GreetingsFramework + label: '@swiftpkg_my_local_package//:GreetingsFramework' + - identity: notthatamazingmodule + name: NotThatAmazingModule + label: '@swiftpkg_notthatamazingmodule//:NotThatAmazingModule' + - identity: swift-argument-parser + name: ArgumentParser + label: '@swiftpkg_swift_argument_parser//:ArgumentParser' + unresolved: [] +deps: + - //Sources/MyLibrary + - '@swiftpkg_my_local_package//:FarewellFramework' + - '@swiftpkg_my_local_package//:GreetingsFramework' + - '@swiftpkg_notthatamazingmodule//:NotThatAmazingModule' + - '@swiftpkg_swift_argument_parser//:ArgumentParser' +--- +name: //Sources/MyLibrary +kind: swift_library +imports: + - GreetingsFramework +external_resolution: + modules: + - GreetingsFramework + products: + - identity: my_local_package + name: GreetingsFramework + label: '@swiftpkg_my_local_package//:GreetingsFramework' + unresolved: [] +deps: + - '@swiftpkg_my_local_package//:GreetingsFramework' +--- +name: //Tests/MyLibraryTests +kind: swift_test +imports: + - MyLibrary + - XCTest +builtins: + - XCTest +local_resolution: + - module: MyLibrary + label: //Sources/MyLibrary +external_resolution: + modules: + - XCTest + products: [] + unresolved: + - XCTest +deps: + - //Sources/MyLibrary diff --git a/examples/pkg_manifest_minimal/third_party/my_local_package/Package.swift b/examples/pkg_manifest_minimal/third_party/my_local_package/Package.swift index 31eec3289..49eb1433d 100644 --- a/examples/pkg_manifest_minimal/third_party/my_local_package/Package.swift +++ b/examples/pkg_manifest_minimal/third_party/my_local_package/Package.swift @@ -6,22 +6,35 @@ let package = Package( name: "MyLocalPackage", products: [ .executable(name: "print-greeting", targets: ["PrintGreeting"]), + .executable(name: "print-farewell", targets: ["PrintFarewell"]), .library( name: "GreetingsFramework", targets: ["GreetingsFramework"] ), + .library( + name: "FarewellFramework", + targets: ["FarewellFramework"] + ), ], targets: [ // Puposefully, using the old-style pattern of a regular target being used by an executable // product. - .target( + .executableTarget( name: "PrintGreeting", dependencies: ["GreetingsFramework"] ), + .executableTarget( + name: "PrintFarewell", + dependencies: ["FarewellFramework"] + ), .target( name: "GreetingsFramework", dependencies: [] ), + .target( + name: "FarewellFramework", + dependencies: [] + ), .testTarget( name: "GreetingsFrameworkTests", dependencies: ["GreetingsFramework"] diff --git a/examples/pkg_manifest_minimal/third_party/my_local_package/Sources/FarewellFramework/include/MyClangLibrary/API.h b/examples/pkg_manifest_minimal/third_party/my_local_package/Sources/FarewellFramework/include/MyClangLibrary/API.h new file mode 100644 index 000000000..8eb9c7d1a --- /dev/null +++ b/examples/pkg_manifest_minimal/third_party/my_local_package/Sources/FarewellFramework/include/MyClangLibrary/API.h @@ -0,0 +1,62 @@ +#ifndef MYCLANG_LIBRARY_API_H +#define MYCLANG_LIBRARY_API_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Version information */ +#define MYCLANG_VERSION_MAJOR 1 +#define MYCLANG_VERSION_MINOR 0 +#define MYCLANG_VERSION_PATCH 0 + +/* Maximum buffer sizes */ +#define MYCLANG_MAX_NAME_LENGTH 256 +#define MYCLANG_MAX_BUFFER_SIZE 4096 + +/* Status codes */ +typedef enum { + MYCLANG_SUCCESS = 0, + MYCLANG_ERROR_INVALID_ARGUMENT = -1, + MYCLANG_ERROR_BUFFER_OVERFLOW = -2, + MYCLANG_ERROR_NOT_INITIALIZED = -3 +} MyclangStatus; + +/* Farewell message types */ +typedef enum { + MYCLANG_FAREWELL_GOODBYE = 0, + MYCLANG_FAREWELL_PARTING = 1, + MYCLANG_FAREWELL_SEE_YOU_LATER = 2, + MYCLANG_FAREWELL_TAKE_CARE = 3, + MYCLANG_FAREWELL_ADIEU = 4, + MYCLANG_FAREWELL_DEPARTURE = 5 +} MyclangFarewellType; + +/* Data structures */ +typedef struct { + char name[MYCLANG_MAX_NAME_LENGTH]; + unsigned int id; + double value; +} MyclangObject; + +/* Function declarations */ +MyclangStatus myclang_initialize(void); +MyclangStatus myclang_cleanup(void); + +MyclangStatus myclang_create_object(MyclangObject* obj, + const char* name, + unsigned int id, + double value); + +MyclangStatus myclang_process_object(const MyclangObject* obj); + +const char* myclang_get_version_string(void); + +/* Farewell function */ +const char* myclang_get_farewell_message(MyclangFarewellType type); + +#ifdef __cplusplus +} +#endif + +#endif /* MYCLANG_LIBRARY_API_H */ diff --git a/examples/pkg_manifest_minimal/third_party/my_local_package/Sources/FarewellFramework/src/lib.c b/examples/pkg_manifest_minimal/third_party/my_local_package/Sources/FarewellFramework/src/lib.c new file mode 100644 index 000000000..a9f682f16 --- /dev/null +++ b/examples/pkg_manifest_minimal/third_party/my_local_package/Sources/FarewellFramework/src/lib.c @@ -0,0 +1,86 @@ +#include +#include +#include "MyClangLibrary/API.h" + +static int g_initialized = 0; + +MyclangStatus myclang_initialize(void) { + if (g_initialized) { + return MYCLANG_ERROR_INVALID_ARGUMENT; + } + g_initialized = 1; + return MYCLANG_SUCCESS; +} + +MyclangStatus myclang_cleanup(void) { + if (!g_initialized) { + return MYCLANG_ERROR_NOT_INITIALIZED; + } + g_initialized = 0; + return MYCLANG_SUCCESS; +} + +MyclangStatus myclang_create_object(MyclangObject* obj, + const char* name, + unsigned int id, + double value) { + if (!g_initialized) { + return MYCLANG_ERROR_NOT_INITIALIZED; + } + + if (!obj || !name) { + return MYCLANG_ERROR_INVALID_ARGUMENT; + } + + if (strlen(name) >= MYCLANG_MAX_NAME_LENGTH) { + return MYCLANG_ERROR_BUFFER_OVERFLOW; + } + + strncpy(obj->name, name, MYCLANG_MAX_NAME_LENGTH - 1); + obj->name[MYCLANG_MAX_NAME_LENGTH - 1] = '\0'; + obj->id = id; + obj->value = value; + + return MYCLANG_SUCCESS; +} + +MyclangStatus myclang_process_object(const MyclangObject* obj) { + if (!g_initialized) { + return MYCLANG_ERROR_NOT_INITIALIZED; + } + + if (!obj) { + return MYCLANG_ERROR_INVALID_ARGUMENT; + } + + // Example processing - in real implementation, this would do something useful + return MYCLANG_SUCCESS; +} + +const char* myclang_get_version_string(void) { + static char version[32]; + snprintf(version, sizeof(version), "%d.%d.%d", + MYCLANG_VERSION_MAJOR, + MYCLANG_VERSION_MINOR, + MYCLANG_VERSION_PATCH); + return version; +} + +const char* myclang_get_farewell_message(MyclangFarewellType type) { + switch (type) { + case MYCLANG_FAREWELL_GOODBYE: + return "Goodbye"; + case MYCLANG_FAREWELL_PARTING: + return "Parting"; + case MYCLANG_FAREWELL_SEE_YOU_LATER: + return "See you later"; + case MYCLANG_FAREWELL_TAKE_CARE: + return "Take care"; + case MYCLANG_FAREWELL_ADIEU: + return "Adieu"; + case MYCLANG_FAREWELL_DEPARTURE: + return "Departure"; + default: + return "Goodbye"; + } +} diff --git a/examples/pkg_manifest_minimal/third_party/my_local_package/Sources/PrintFarewell/main.swift b/examples/pkg_manifest_minimal/third_party/my_local_package/Sources/PrintFarewell/main.swift new file mode 100644 index 000000000..26aedace5 --- /dev/null +++ b/examples/pkg_manifest_minimal/third_party/my_local_package/Sources/PrintFarewell/main.swift @@ -0,0 +1,7 @@ +import FarewellFramework + +let message = FarewellFramework.myclang_get_farewell_message(MYCLANG_FAREWELL_SEE_YOU_LATER) + +let swiftString = String(cString: message!) + +print(swiftString) From 0b68a7888df8e7622f54c746baa661c59a499463 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Mar=C3=A7al?= <127062836+0xLucasMarcal@users.noreply.github.com> Date: Thu, 23 Jan 2025 11:56:59 -0300 Subject: [PATCH 14/15] Update examples/pkg_manifest_minimal/Package.swift --- examples/pkg_manifest_minimal/Package.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/pkg_manifest_minimal/Package.swift b/examples/pkg_manifest_minimal/Package.swift index cc4d1b2f4..d2f417405 100644 --- a/examples/pkg_manifest_minimal/Package.swift +++ b/examples/pkg_manifest_minimal/Package.swift @@ -8,7 +8,6 @@ let package = Package( .package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"), .package(url: "https://github.com/apple/swift-log", from: "1.6.2"), .package(url: "https://github.com/nicklockwood/SwiftFormat", from: "0.55.4"), - .package(path: "third_party/my_local_package"), .package(path: "third_party/NotThatAmazingModule"), ] From 3f574e53af98412333af329017903466b0fdab9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Marc=CC=A7al?= Date: Sun, 26 Jan 2025 20:20:27 -0300 Subject: [PATCH 15/15] undo pkg_manifest_minimal tests changes --- examples/pkg_manifest_minimal/do_test | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/examples/pkg_manifest_minimal/do_test b/examples/pkg_manifest_minimal/do_test index 325189602..88681c689 100755 --- a/examples/pkg_manifest_minimal/do_test +++ b/examples/pkg_manifest_minimal/do_test @@ -9,13 +9,10 @@ script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null && pwd)" bazel="${BIT_BAZEL_BINARY:-bazel}" assert_match() { - local expected=${1} + local pattern=${1} local actual="${2}" - local err_msg="Expected to match. expected: ${expected}, actual: ${actual}" - if [[ "${expected}" != "${actual}" ]]; then - echo >&2 "${err_msg}" - exit 1 - fi + local err_msg="Expected to match. pattern: ${pattern}, actual: ${actual}" + [[ "${actual}" =~ ${pattern} ]] || (echo >&2 "${err_msg}" && exit 1) } # Generate Swift external deps and update build files @@ -26,9 +23,8 @@ assert_match() { # Run MyExecutable target output="$("${bazel}" run //Sources/MyExecutable)" -assert_match "Good morning, World! -Hello, my name is Olivia and I'm 30 years old. -Goodbye" "${output}" +assert_match "Good morning, World!" "${output}" +assert_match "Goodbye" "${output}" # Run old-style executable in my_local_package output="$("${bazel}" run @swiftpkg_my_local_package//:print-greeting)"