Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
> 本文件追踪 `mcpp-community/mcpp` 公开仓的版本演进。
> 格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/)。

## [0.0.38] — 2026-05-31

### 新增

- 支持包描述拥有自己的 `ldflags`,依赖包声明的链接参数会随包源码编译
一起进入最终链接命令,消费方项目不再需要手动补齐第三方 C/C++
库的私有链接参数。

## [0.0.37] — 2026-05-31

### 修复
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ import mcpplibs.cmdline;
- Ninja 后端:自动生成 build.ninja,并行编译
- compile_commands.json 自动生成(clangd / ccls 即用)
- C 语言一等支持:`.c` 文件自动检测,混合 C/C++ 项目
- 用户自定义 cflags / cxxflags / c_standard
- 用户自定义 cflags / cxxflags / ldflags / c_standard

</details>

Expand Down
1 change: 1 addition & 0 deletions docs/05-mcpp-toml.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ include_dirs = ["include", "third_party/include"] # 头文件搜索路径
c_standard = "c11" # C 源文件的标准(默认 c11)
cflags = ["-DFOO=1"] # 额外 C 编译参数
cxxflags = ["-DBAR=2"] # 额外 C++ 编译参数
ldflags = ["-lfoo"] # 额外链接参数
static_stdlib = true # 静态链接 libstdc++(默认 true)
```

Expand Down
2 changes: 1 addition & 1 deletion mcpp.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mcpp"
version = "0.0.37"
version = "0.0.38"
description = "Modern C++ build & package management tool"
license = "Apache-2.0"
authors = ["mcpp-community"]
Expand Down
3 changes: 2 additions & 1 deletion src/build/compile_commands.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ namespace mcpp::build {
namespace {

bool is_c_source(const std::filesystem::path& src) {
return src.extension() == ".c";
auto ext = src.extension();
return ext == ".c" || ext == ".m";
}

// Split a flag string into individual tokens AND un-escape ninja-style
Expand Down
33 changes: 29 additions & 4 deletions src/build/flags.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,26 @@ std::string escape_path(const std::filesystem::path& p) {
return out;
}

std::string normalize_ldflag(const std::filesystem::path& root, const std::string& flag) {
auto absolute_path = [&](std::string_view raw) {
std::filesystem::path p{std::string(raw)};
if (p.is_absolute() || raw.starts_with("$")) return p;
return root / p;
};

if (flag.starts_with("-L") && flag.size() > 2) {
return "-L" + escape_path(absolute_path(std::string_view(flag).substr(2)));
}

constexpr std::string_view rpathPrefix = "-Wl,-rpath,";
if (flag.starts_with(rpathPrefix) && flag.size() > rpathPrefix.size()) {
return std::string(rpathPrefix)
+ escape_path(absolute_path(std::string_view(flag).substr(rpathPrefix.size())));
}

return flag;
}

} // namespace

CompileFlags compute_flags(const BuildPlan& plan) {
Expand Down Expand Up @@ -192,6 +212,11 @@ CompileFlags compute_flags(const BuildPlan& plan) {
};
std::string user_cxxflags = join(plan.manifest.buildConfig.cxxflags);
std::string user_cflags = join(plan.manifest.buildConfig.cflags);
std::string user_ldflags;
for (auto const& flag : plan.manifest.buildConfig.ldflags) {
user_ldflags += ' ';
user_ldflags += normalize_ldflag(plan.projectRoot, flag);
}

// C standard
std::string c_std =
Expand Down Expand Up @@ -257,12 +282,12 @@ CompileFlags compute_flags(const BuildPlan& plan) {
}

if constexpr (mcpp::platform::is_windows) {
f.ld = "";
f.ld = user_ldflags;
} else if constexpr (mcpp::platform::needs_explicit_libcxx) {
f.ld = std::format("{}{}{} -lc++", full_static, static_stdlib, b_flag);
f.ld = std::format("{}{}{} -lc++{}", full_static, static_stdlib, b_flag, user_ldflags);
} else {
f.ld = std::format("{}{}{}{}{}{}", full_static, static_stdlib, link_toolchain_flags, b_flag,
runtime_dirs, payload_ld);
f.ld = std::format("{}{}{}{}{}{}{}", full_static, static_stdlib, link_toolchain_flags, b_flag,
runtime_dirs, payload_ld, user_ldflags);
}

return f;
Expand Down
19 changes: 15 additions & 4 deletions src/build/ninja_backend.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ std::filesystem::path mcpp_exe_path() {
}

bool is_c_source(const std::filesystem::path& src) {
return src.extension() == ".c";
auto ext = src.extension();
return ext == ".c" || ext == ".m";
}

std::string ltrim_copy(std::string_view s) {
Expand Down Expand Up @@ -360,15 +361,15 @@ std::string emit_ninja_string(const BuildPlan& plan) {
}

append("rule cxx_link\n");
append(" command = $cxx $in -o $out $ldflags\n");
append(" command = $cxx $in -o $out $ldflags $unit_ldflags\n");
append(" description = LINK $out\n\n");

append("rule cxx_archive\n");
append(" command = $ar rcs $out $in\n");
append(" description = AR $out\n\n");

append("rule cxx_shared\n");
append(" command = $cxx -shared $in -o $out $ldflags\n");
append(" command = $cxx -shared $in -o $out $ldflags $unit_ldflags\n");
append(" description = SHARED $out\n\n");

if (dyndep) {
Expand Down Expand Up @@ -609,7 +610,17 @@ std::string emit_ninja_string(const BuildPlan& plan) {
rule = "cxx_shared";
break;
}
append(std::format("build {} : {}{}\n", escape_ninja_path(lu.output), rule, ins));
std::string implicit;
for (auto& input : lu.implicitInputs) {
implicit += " " + escape_ninja_path(input);
}

std::string out_line = std::format("build {} : {}{}{}\n",
escape_ninja_path(lu.output), rule, ins,
implicit.empty() ? std::string{} : " |" + implicit);
if (auto flags = join_flags(lu.linkFlags); !flags.empty())
out_line += " unit_ldflags =" + flags + "\n";
append(std::move(out_line));
}
append("\n");

Expand Down
Loading
Loading