Proposal: Platform-aware configuration and generation in llcppg
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 30/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- go
- Lĩnh vực
- build-system, tooling
Hướng nghiên cứu
Read tool/gen.go to trace configuration selection and generation, then inspect tool.Config.NewPackage and clang/clang.go for target argument propagation. Check xtool/env/cstdlib/stdlib.go for standard library discovery and require explicit Stdlib for recognized platform configurations. Done means ordinary and single-platform inputs retain their behavior, direct platform children generate into per-platform destinations with errors collected across failures, and the specified target and header rules are honored.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
1. Summary
Introduce a platform-aware configuration and generation model in llcppg for C/C++ libraries whose bindings vary by target. Organize platform configurations in directories named GOOS-GOARCH[-<option>], each containing llcppg.cfg. Use the existing command arguments to select an ordinary configuration, one platform configuration, or a platform collection. A root llcppg.cfg selects single-configuration processing; only its absence triggers discovery in direct platform child directories. llarhub/libc is a concrete use case for this general model.
2. User Stories / Motivation
A binding maintainer may need separate configurations when a C/C++ library exposes different headers, declarations, macro values, or type layouts for different targets.
llarhub/libc illustrates this need: platforms can use different libc implementations, and the same implementation can expose different declarations or macro values under different target macros. For example, headers may select different branches for __x86_64__ and __aarch64__.
The generation input therefore needs both a target platform and matching library and system headers. Clang can parse for another target when given these inputs; a matching host machine is not required.
Maintainers need to select either an entire platform collection or one platform directly. Existing ordinary configurations must remain usable. For the initial libc use case, each platform uses its documented default libc; an optional suffix allows musl or another implementation to be distinguished later.
3. Current Workaround
Separate configurations can already be selected through llcppg's source-directory argument, one invocation at a time. However, the configuration-to-parser path does not currently pass a target to libclang. The proposal adds the association between directory and target, plus automatic discovery of a platform collection.
4. Goals
- Keep each platform identity, generation configuration, and target header environment together.
- Support ordinary, single-platform, and automatic platform-collection input through the existing positional arguments.
- Preserve ordinary generation and the destination behavior of single-configuration invocations.
5. Out of Scope
- The
llcppg -mergealgorithm. - GCC support and implementation of musl bindings; musl illustrates the naming extension.
- Automatic Git commits, pushes, or branch switches.
Automatic processing writes each platform to <dest>/<platform>, continues after a platform fails, and returns the collected errors after processing the remaining platforms.
6. Proposal
6.1 Design Rule
The selected configuration provides generation settings and matching headers. When it belongs to a platform directory, that directory provides the target identity. The target and headers determine preprocessing and type parsing independently of the host running llcppg.
Configuration count and target selection are separate decisions: a directly selected platform directory is a single-configuration invocation with an explicit directory-derived target.
6.2 Syntax / API / Interface
Retain the existing command form and positional argument order:
llcppg <dest-gopkg-dir> [<src-header-files-and-cfg-dir>]
The second argument defaults to the current directory. No new argument or flag is introduced.
Configuration selection follows this order:
- Look for
llcppg.cfgdirectly in the selected source directory. If present, load that configuration through the existing single-configuration path. Do not scan child directories. - Only if that root configuration does not exist, inspect direct child directories for platform configurations. A child qualifies when its name is one of the initially supported platform names listed in section 6.5 and it contains
llcppg.cfg. - If one or more qualifying children exist, enter automatic platform-collection mode and process those configurations.
- If neither a root configuration nor qualifying platform configurations exist, report that no configuration was found.
A root configuration read error or invalid configuration is an error, not evidence that the directory is a platform collection.
6.3 Examples as Specification
Use the following example layout. single contains an ordinary configuration; platforms has no root llcppg.cfg and contains two platform configurations.
workspace/
single/
llcppg.cfg
platforms/
linux-amd64/
llcppg.cfg
darwin-arm64/
llcppg.cfg
All six calls below supply the same destination, workspace/generated. The relative spelling changes with the working directory.
| Case | Working directory | Command | Selected input |
|---|---|---|---|
| Ordinary configuration, explicit source | workspace/ |
llcppg ./generated ./single |
single/llcppg.cfg |
| Ordinary configuration, source omitted | workspace/single/ |
llcppg ../generated |
The current directory's llcppg.cfg |
| Automatic platform collection, explicit source | workspace/ |
llcppg ./generated ./platforms |
Both direct platform configurations |
| Automatic platform collection, source omitted | workspace/platforms/ |
llcppg ../generated |
Both direct platform configurations in the current directory |
| One platform, explicit source | workspace/ |
llcppg ./generated ./platforms/linux-amd64 |
Only linux-amd64/llcppg.cfg, with its directory-derived target |
| One platform, source omitted | workspace/platforms/linux-amd64/ |
llcppg ../../generated |
The current directory's llcppg.cfg, with the linux-amd64 target |
In each omitted-source form, adding . as the second argument selects the same source directory. The destination argument is still required.
The ordinary calls retain existing configuration and Pkgs behavior. The collection calls automatically process both qualifying direct platform children because the selected directory has no root configuration. The single-platform calls find a root configuration in the selected directory and process only that one; its platform name supplies the target.
Single-configuration calls write directly to the supplied destination, retaining existing subpackage behavior. Collection calls write each platform under <dest>/<platform>. For the collection example above:
generated/
linux-amd64/
...generated files
llcppg.pub
darwin-arm64/
...generated files
llcppg.pub
To regenerate just the Linux result in that layout, explicitly select its destination:
llcppg ./generated/linux-amd64 ./platforms/linux-amd64
Configured subpackages remain below the platform's destination, for example generated/linux-amd64/adt/. These are filesystem paths; generation does not select, switch, commit, or push Git branches.
6.4 Boundary Cases
| Condition | Behavior |
|---|---|
Root llcppg.cfg and platform children coexist |
Root configuration takes precedence; children are not automatically processed |
| Configurations exist only below deeper descendants | Do not recursively discover them |
| Root configuration is unreadable or invalid | Report the error; do not switch modes |
A child directory qualifies only when both its platform name is recognized and its llcppg.cfg exists.
6.5 Platform Names and Mapping
Use GOOS-GOARCH[-<option>], with Go's platform spellings and an optional target-environment choice. The libc mappings below illustrate the option: linux-amd64-musl identifies Linux, amd64, and musl. Omitting the option uses the documented platform default, independently of the host.
Platform names remain independent of compiler-specific target spelling. The Clang mapping is:
| Platform directory | Target platform | libc selection | Clang target |
|---|---|---|---|
linux-amd64 |
Linux / amd64 | glibc | x86_64-unknown-linux-gnu |
linux-arm64 |
Linux / arm64 | glibc | aarch64-unknown-linux-gnu |
darwin-amd64 |
Darwin / amd64 | System default | x86_64-apple-darwin |
darwin-arm64 |
Darwin / arm64 | System default | arm64-apple-darwin |
linux-amd64-musl |
Linux / amd64 | musl | x86_64-unknown-linux-musl |
linux-arm64-musl |
Linux / arm64 | musl | aarch64-unknown-linux-musl |
The initial implementation recognizes exactly linux-amd64, linux-arm64, darwin-amd64, and darwin-arm64. Linux defaults to glibc. The musl rows illustrate a future naming extension and are not recognized platform configurations in this increment.
6.6 Target Headers and Stdlib
The target selects compiler-provided platform macros and type/ABI interpretation. The headers supply the C/C++ declarations and target-specific definitions being interpreted. For example, a musl target needs musl headers; a target string does not provide them.
| Input | Responsibility |
|---|---|
| Platform directory name | Target OS, architecture, and optional target-environment choice |
Dir / Files |
Headers whose bindings are generated |
Stdlib |
Matching standard-library include directory needed during parsing |
Relative Dir and Stdlib paths remain relative to the selected configuration directory; Files remains relative to Dir. When generating libc itself, these inputs can reference the same prepared header tree.
An empty Stdlib currently triggers local Clang include discovery. A recognized platform configuration must explicitly provide Stdlib; omission returns an error instead of using the host's default header directories. Ordinary configurations retain the existing default discovery behavior. Stdlib remains an include directory, not a sysroot.
6.7 Generation and Module Responsibilities
For a selected darwin-arm64 configuration:
- Load its
llcppg.cfg. - Map the platform name to
arm64-apple-darwin. - Resolve
Dir,Files, andStdlibto the selected headers and matching target environment. - Pass
-target arm64-apple-darwinalongside language and include arguments to libclang. Conditional compilation, macros, and types are interpreted for that target before Go generation. - Generate bindings from the resulting translation units.
The existing Index.ParseTranslationUnit forwards arguments to libclang. The integration needed is target propagation through the configuration-driven path. CFlags currently serves wrapper compilation, not header parsing.
The command selects configuration directories and discovers platform collections. tool.Config.NewPackage derives the target from the basename of its existing workDir argument and supplies the corresponding libclang arguments. No Target field, new CLI option, or public method parameter is added. cl consumes translation units without knowing platform directory names or Git branches.
Automatic processing reuses the existing generation functions in the same process. Each platform receives its own <dest>/<platform> destination. A failed platform contributes an error, while the remaining platforms continue. The existing global ignore-diagnostic settings are saved and restored for each generation call so one configuration cannot silence diagnostics in the next.
6.8 Example: llarhub/libc Repository Workflow
llarhub/libc applies this configuration model to its branch organization:
c branch:
<platform>/llcppg.cfg
|
| generate with that platform's inputs
v
raw branch:
<platform>/llcppg.cfg
<platform>/...generated bindings
|
| llcppg -merge (later work)
v
main branch:
...merged bindings
Configurations are maintained on c; each configuration and its generated bindings are committed under the corresponding platform name on raw. The later merge produces main. This repository workflow is external to the generator. The generator writes directories; separate Git operations determine which branch records those files.
7. Error Handling
| Condition | Behavior |
|---|---|
| Neither input layout supplies a configuration | Report that no configuration was found |
Root llcppg.cfg cannot be read or parsed |
Preserve the error; do not try platform discovery as a fallback |
| A selected platform configuration cannot be read or parsed | Report its configuration error |
A recognized platform configuration omits Stdlib |
Report the missing explicit target-header directory |
| One platform fails during automatic processing | Continue the remaining platforms and return errors labeled with their platform names |
FailFast reaches its diagnostic limit |
Stop the current cl.NewPackage call and return an error instead of exiting the process |
8. Compatibility
Keep the positional arguments, ordinary configuration behavior, Pkgs handling, and single-configuration destination semantics. Add automatic discovery only when the root configuration is absent; collection output is placed under <dest>/<platform>.
Existing public function signatures remain unchanged. A FailFast limit now returns an error from cl.NewPackage; a single CLI invocation still reports failure through its existing error path. Unexpected panics remain panics and are not converted into platform errors.
9. Alternatives Considered
| Alternative | Reason for the directory-based design |
|---|---|
| Organize libc configurations only by libc implementation | The same implementation can expose different interfaces under different target macros |
| Pass the target separately on the command line | Platform directories keep the target identity attached to its configuration |
| Use compiler triples as directory names | Go platform names keep repository organization independent of compiler-specific spelling |
| Require generation on each target host | Target parameters and matching headers allow cross-target parsing |
10. Testing Strategy
| Case | Expected result |
|---|---|
| Ordinary root configuration, including one with platform children | Preserve existing generation and Pkgs; select only the root configuration |
| Missing root with qualifying direct platform children | Process those configurations and write each result under <dest>/<platform> |
| No qualifying configuration | Report a missing configuration |
| Unreadable or invalid root configuration | Report the error without switching modes |
| Direct platform invocation | Select one configuration, derive its target, and preserve the explicit destination |
| Omitted source argument | Apply the same selection rules to the current directory |
| Deeper nested configurations | Do not recursively discover them |
| Target-specific parsing | Check OS/architecture macros, header selection, and pointer size for all four targets in C and C++ |
Platform configuration without Stdlib |
Return an error without host-header discovery |
Configuration error or FailFast in a collection |
Return the platform errors and still produce the successful platform's output |
| Consecutive configurations with different ignore settings | Restore diagnostic settings between calls |
FailFast during loading or compilation |
Return an error with no partial package; preserve unrelated panics |
Use llgo test for implementation tests. The implementation has passed llgo test -v ./... on macOS arm64 with LLGo v1.0.9 and LLVM 22.1.8, including the six CLI input forms and C/C++ generation fixtures for all four targets. These fixtures validate target behavior with supplied test headers; they do not establish complete libc/SDK binding coverage or execution on a Linux host.
The table's six target strings were checked with Clang 22.1.8 on macOS and produced matching OS/architecture macros. This verifies target selection only; complete libc generation remains unverified. See Clang's cross-compilation documentation.
11. Summary of Changes
| Area | Change |
|---|---|
| Input selection | Root-configuration precedence; otherwise discover direct platform children |
| Target inputs | Associate each selected platform configuration with its target and matching headers |
| Parsing integration | Carry that target into the existing libclang argument path |
llarhub/libc use case |
Maintain platform configurations on c and corresponding configurations and results on raw |
| CLI | Keep positional arguments; write collection output under <dest>/<platform> and aggregate failures |
| Failure boundary | Return FailFast as a package-generation error and restore per-call diagnostic settings |
12. Open Questions
- How should target SDK/libc headers be prepared or distributed for real platform configurations? The generator currently requires callers to provide the matching
Stdlibdirectory. - Which additional platform/environment options, such as musl, should be implemented after the initial four targets?
- Ngôn ngữ chính
- Go
- Star
- 40
- Fork
- 13
- Merge trung bình
- 2 giờ
- Pull request đã merge (30 ngày)
- 150
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của goplus/llcppg
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 64/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 70/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 38/100
goplus/llcppg#1136 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của goplus/llcppg
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
apache/arrow-swift#209 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
orchestrator: NFS-cache "cache path is not set" WARN logged on every build/launch instead of onceCó thể đã có người làm Có pull request liên kết đang mở hoặc đã được merge. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 2 ngày
-
Độ khó 1/5 1-3 giờ Mức phù hợp với người mới 65/100
influxdata/telegraf#20031 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
pkg/registry/file no longer builds for GOOS=windows: unguarded syscall.Stat_t in qualified_resource_migration.goCó thể đã có người làm @AnshulPatil2005 đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
OneBusAway/maglev#1914 ·
Maintainer thường phản hồi trong vòng 2 ngày