<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="rss.xsl"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>GOOSE Blog</title>
        <link>https://kumo-pub.github.io/goose/blog</link>
        <description>GOOSE Blog</description>
        <lastBuildDate>Fri, 01 Aug 2025 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[why cmake tools]]></title>
            <link>https://kumo-pub.github.io/goose/blog/mdx-blog</link>
            <guid>https://kumo-pub.github.io/goose/blog/mdx-blog</guid>
            <pubDate>Fri, 01 Aug 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[If you’re a C++ developer, you’ve probably drowned in the abyss of "build hell" spending half a month troubleshooting dependencies, debugging compile flags, and barely getting a third-party library to work, only to face the "works on my machine" curse. Must building a C++ project require becoming a "build tool expert" first?]]></description>
            <content:encoded><![CDATA[<p>If you’re a C++ developer, you’ve probably drowned in the abyss of "build hell": scratching your head over nested Makefile syntax, sifting through hundreds of lines to modify a single compile flag; getting tangled in CMake’s <code>target_link_libraries</code> PUBLIC/PRIVATE logic, where writing a simple library configuration file takes longer than the business code itself; or daring to try Bazel, Blade, or Xmake, only to find each tool has its own "jargon system" that demands hours of learning—let alone the ultimate production nightmare: spending half a month troubleshooting dependencies, debugging compile flags, and barely getting a third-party library to work, only to face the "works on my machine" curse. Must building a C++ project require becoming a "build tool expert" first?</p>
<p>It wasn’t until I reexamined the problem through the lens of first principles that I realized we’re all held hostage by tools: what we need is never "mastering CMake," but "quickly setting up runnable, integrable, and deployable projects"—and the efficiency to avoid wasting half a month on a single library. Thus, kmcmake was born: a CMake framework designed around CMake’s underlying workflow, taming complex logic into a 5-minute setup with zero intrusion. Its core mission? End the absurdity of "spending half a month compiling one library" while letting you understand the "why" behind it, not just blindly using it.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="first-understand-cmakes-underlying-workflow-the-foundation-of-first-principles">First, Understand CMake’s Underlying Workflow (The Foundation of First Principles)<a href="https://kumo-pub.github.io/goose/blog/mdx-blog#first-understand-cmakes-underlying-workflow-the-foundation-of-first-principles" class="hash-link" aria-label="Direct link to First, Understand CMake’s Underlying Workflow (The Foundation of First Principles)" title="Direct link to First, Understand CMake’s Underlying Workflow (The Foundation of First Principles)" translate="no">​</a></h2>
<p>First principles boil down to "returning to fundamentals and eliminating redundancy." For CMake, its essence is an "organizer of cross-platform build processes"—it doesn’t compile code directly, but generates platform-specific build files (Makefiles, Visual Studio solutions, etc.) in fixed phases. To simplify building, you must first dissect these <strong>three core phases</strong>, understanding the responsibilities and operational logic of each:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="phase-1-configuration-phase--find-stuff--define-rules">Phase 1: Configuration Phase – "Find Stuff + Define Rules"<a href="https://kumo-pub.github.io/goose/blog/mdx-blog#phase-1-configuration-phase--find-stuff--define-rules" class="hash-link" aria-label="Direct link to Phase 1: Configuration Phase – &quot;Find Stuff + Define Rules&quot;" title="Direct link to Phase 1: Configuration Phase – &quot;Find Stuff + Define Rules&quot;" translate="no">​</a></h3>
<ul>
<li class=""><strong>Core Tasks</strong>: Parse CMakeLists.txt, locate dependent libraries, set compile options, define targets (libraries/executables), and configure installation rules.</li>
<li class=""><strong>Key Operations</strong>:<!-- -->
<ol>
<li class="">Dependency Discovery: Use <code>find_package</code>, <code>find_library</code>, or <code>find_path</code> to locate third-party libraries (e.g., spdlog, Protobuf), determining library and header file paths.</li>
<li class="">Target Definition: Create targets with <code>add_library</code>/<code>add_executable</code>, set include directories with <code>target_include_directories</code>, and link dependencies with <code>target_link_libraries</code>.</li>
<li class="">Variable Configuration: Set core variables like <code>CMAKE_BUILD_TYPE</code> (Debug/Release), <code>CMAKE_INSTALL_PREFIX</code> (installation root), and <code>CMAKE_CXX_STANDARD</code> (C++ standard).</li>
<li class="">Conditional Logic: Use <code>if-else</code> to adapt to different platforms (Linux/macOS/Windows) and compilers (GCC/Clang/MSVC).</li>
</ol>
</li>
<li class=""><strong>Production Pitfalls</strong>: I once spent 2 days manually setting <code>CMAKE_PREFIX_PATH</code>, <code>PROTOBUF_INCLUDE_DIR</code>, and <code>PROTOBUF_LIBRARY</code> to locate a custom-installed Protobuf library. Another time, confusing CMake’s <code>CONFIG</code> and <code>MODULE</code> modes for <code>find_package</code> caused CI to fail, taking a week to diagnose.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="phase-2-generation-phase--write-files">Phase 2: Generation Phase – "Write Files"<a href="https://kumo-pub.github.io/goose/blog/mdx-blog#phase-2-generation-phase--write-files" class="hash-link" aria-label="Direct link to Phase 2: Generation Phase – &quot;Write Files&quot;" title="Direct link to Phase 2: Generation Phase – &quot;Write Files&quot;" translate="no">​</a></h3>
<ul>
<li class=""><strong>Core Tasks</strong>: Generate platform-specific build files (e.g., Makefiles for Linux, Xcode projects for macOS, VS solutions for Windows) based on rules defined in the configuration phase.</li>
<li class=""><strong>Key Operations</strong>:<!-- -->
<ol>
<li class="">Auto-generate Compile Commands: Convert flags from <code>target_compile_options</code> into <code>CXXFLAGS</code> in Makefiles.</li>
<li class="">Generate Dependency Graphs: Translate <code>target_link_libraries</code> dependencies into link commands in Makefiles, handling static/shared library dependency propagation.</li>
<li class="">Generate Installation Rules: Convert <code>install</code> directives into <code>install</code> targets in Makefiles, defining paths for headers, libraries, and executables.</li>
</ol>
</li>
<li class=""><strong>Production Pitfalls</strong>: When writing <code>install</code> rules in raw CMake, I ignored platform differences in <code>CMAKE_INSTALL_LIBDIR</code> (library install directory) and <code>CMAKE_INSTALL_INCLUDEDIR</code> (header install directory). This worked on Linux but misaligned paths on macOS, leaving third-party projects unable to find headers.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="phase-3-buildinstall-phase--execute-commands">Phase 3: Build/Install Phase – "Execute Commands"<a href="https://kumo-pub.github.io/goose/blog/mdx-blog#phase-3-buildinstall-phase--execute-commands" class="hash-link" aria-label="Direct link to Phase 3: Build/Install Phase – &quot;Execute Commands&quot;" title="Direct link to Phase 3: Build/Install Phase – &quot;Execute Commands&quot;" translate="no">​</a></h3>
<ul>
<li class=""><strong>Core Tasks</strong>: Invoke compilers (GCC/Clang/MSVC) to compile code, link libraries, and generate final targets (libraries/executables); copy files to specified directories during <code>make install</code>.</li>
<li class=""><strong>Key Operations</strong>:<!-- -->
<ol>
<li class="">Compilation: Execute compile commands from generated build files to turn source code (.cc/.cpp) into object files (.o/.obj).</li>
<li class="">Linking: Link object files and dependencies into static libraries (.a/.lib), shared libraries (.so/.dll), or executables.</li>
<li class="">Installation: Copy libraries, headers, and executables to paths specified by <code>CMAKE_INSTALL_PREFIX</code> (e.g., <code>/usr/local/lib</code>, <code>/usr/local/include</code>).</li>
</ol>
</li>
<li class=""><strong>Production Pitfalls</strong>: Misconfiguring <code>PUBLIC</code>/<code>PRIVATE</code> in <code>target_link_libraries</code> once broke dependency propagation for a shared library. My library compiled fine, but third-party projects linking to it failed to find spdlog—turns out I’d used <code>PRIVATE</code> instead of <code>PUBLIC</code>, preventing spdlog’s link information from being passed along.</li>
</ul>
<p>These phases are interdependent; a mistake in any step leads to build failure. First principles teach us: <strong>Build tools should be servants, not teachers</strong>. We shouldn’t need to learn their syntax—we just need to tell them "what library I want, what code to compile, and where to deploy it," and let them handle the rest. Every design decision in kmcmake adheres strictly to CMake’s underlying workflow, with "precision encapsulation" at each phase. It preserves CMake’s native logic while simplifying complex operations—turning CMake from a "must-learn skill" into an "invisible implementation detail," and integrating a library from a "half-month project" into a "5-minute task."</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-core-goals-how-kmcmake-implements-first-principles-on-cmakes-workflow">7 Core Goals: How kmcmake Implements First Principles on CMake’s Workflow<a href="https://kumo-pub.github.io/goose/blog/mdx-blog#7-core-goals-how-kmcmake-implements-first-principles-on-cmakes-workflow" class="hash-link" aria-label="Direct link to 7 Core Goals: How kmcmake Implements First Principles on CMake’s Workflow" title="Direct link to 7 Core Goals: How kmcmake Implements First Principles on CMake’s Workflow" translate="no">​</a></h2>
<p>My core requirements are clear—end frustration and boost efficiency. kmcmake is a "direct translation" of these goals into CMake’s three phases, with every feature mapped to specific CMake operations, no ambiguity:</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-5-minute-project-setup-modular-encapsulation-in-the-configuration-phase">1. 5-Minute Project Setup: Modular Encapsulation in the Configuration Phase<a href="https://kumo-pub.github.io/goose/blog/mdx-blog#1-5-minute-project-setup-modular-encapsulation-in-the-configuration-phase" class="hash-link" aria-label="Direct link to 1. 5-Minute Project Setup: Modular Encapsulation in the Configuration Phase" title="Direct link to 1. 5-Minute Project Setup: Modular Encapsulation in the Configuration Phase" translate="no">​</a></h3>
<p>Raw CMake requires writing dozens of lines for basic library configuration: <code>add_library</code>, <code>target_include_directories</code>, <code>target_link_libraries</code>, <code>install</code>, plus handling static/shared library toggles, aliases, and dependency propagation. For example, creating a project supporting both static and shared libraries in raw CMake needs:</p>
<div class="language-cmake codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cmake codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Raw CMake: Static + Shared Library + Installation + Alias (50+ lines)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">option(BUILD_SHARED_LIBS "Build shared library" ON)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">add_library(my_lib src/my_lib.cc)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">add_library(my_lib::my_lib ALIAS my_lib)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">target_include_directories(my_lib</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  PUBLIC</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    $&lt;BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include&gt;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    $&lt;INSTALL_INTERFACE:include&gt;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">target_link_libraries(my_lib PRIVATE spdlog::spdlog)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">target_compile_features(my_lib PUBLIC cxx_std_17)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">install(TARGETS my_lib</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  EXPORT my_lib_targets</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">install(EXPORT my_lib_targets</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  FILE my_libTargets.cmake</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  NAMESPACE my_lib::</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/my_lib</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">)</span><br></span></code></pre></div></div>
<p>Adding compile options or conditional logic only increases complexity. kmcmake’s modular encapsulation condenses all this into one macro during the configuration phase. You just specify "target name, sources, include paths, dependencies"—kmcmake handles the rest:</p>
<div class="language-cmake codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cmake codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># kmcmake: One macro for all configuration phase operations (5-minute setup)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kmcmake_cc_library(</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    NAME my_lib</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    SOURCES src/my_lib.cc</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    INCLUDES include</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    LINKS spdlog::spdlog</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    CXXOPTS -std=c++17</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">)</span><br></span></code></pre></div></div>
<ul>
<li class=""><strong>Underlying Logic</strong>: During configuration, kmcmake automatically:<!-- -->
<ol>
<li class="">Calls <code>add_library</code> and supports <code>BUILD_SHARED_LIBS</code> for static/shared toggling.</li>
<li class="">Sets <code>target_include_directories</code> with <code>BUILD_INTERFACE</code> and <code>INSTALL_INTERFACE</code>—no manual generator expressions.</li>
<li class="">Creates <code>{NAME}::{NAME}</code> aliases for consistent target referencing.</li>
<li class="">Adds <code>install</code> rules following <code>GNUInstallDirs</code>—no need to manage <code>CMAKE_INSTALL_LIBDIR</code>.</li>
<li class="">Smartly propagates dependencies: <code>LINKS</code> automatically distinguishes <code>PUBLIC</code>/<code>PRIVATE</code> (private for library dependencies, public for toolchain dependencies).</li>
</ol>
</li>
</ul>
<p>I once spent 3 hours writing and debugging 50+ lines of raw CMake for a static/shared library project. With kmcmake, it’s done in 5 minutes—no more generator expression mistakes or path misalignments.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-seamless-ci-integration-cross-platform-auto-adaptation-in-the-configuration-phase">2. Seamless CI Integration: Cross-Platform Auto-Adaptation in the Configuration Phase<a href="https://kumo-pub.github.io/goose/blog/mdx-blog#2-seamless-ci-integration-cross-platform-auto-adaptation-in-the-configuration-phase" class="hash-link" aria-label="Direct link to 2. Seamless CI Integration: Cross-Platform Auto-Adaptation in the Configuration Phase" title="Direct link to 2. Seamless CI Integration: Cross-Platform Auto-Adaptation in the Configuration Phase" translate="no">​</a></h3>
<p>The biggest CI/CD pain is "cross-platform configuration adaptation"—differences in dependency paths and compile options across Unix-like systems require endless <code>if-else</code> in raw CMake. For example, adapting compile options for GCC and Clang:</p>
<div class="language-cmake codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cmake codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Raw CMake: Cross-platform compile option adaptation (verbose + error-prone)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  target_compile_options(my_lib PRIVATE -Wall -Wextra -Werror)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  target_compile_options(my_lib PRIVATE -Wall -Wextra -Werror -Wno-gnu-zero-variadic-macro-arguments)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">endif()</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Dependency path adaptation</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">if(UNIX AND NOT APPLE)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  set(PROTOBUF_LIBRARY_PATH /usr/lib/x86_64-linux-gnu)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">elseif(APPLE)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  set(PROTOBUF_LIBRARY_PATH /usr/local/lib)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">endif()</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">find_library(PROTOBUF_LIBRARY protobuf PATHS ${PROTOBUF_LIBRARY_PATH})</span><br></span></code></pre></div></div>
<p>kmcmake’s cross-platform auto-adaptation directly hooks into CMake’s platform-detection APIs during configuration:</p>
<ul>
<li class="">Auto-detects <code>CMAKE_CXX_COMPILER_ID</code> and embeds common flags for GCC/Clang—no manual <code>if-else</code>.</li>
<li class="">Follows <code>GNUInstallDirs</code> and prioritizes <code>find_package</code>’s <code>CONFIG</code> mode (falling back to <code>MODULE</code>), letting CMake handle cross-platform path differences natively.</li>
<li class="">Embeds test macros like <code>kmcmake_cc_test</code> that auto-register test targets during configuration—just add <code>-DKMCMAKE_BUILD_TEST=ON</code> in CI, no manual <code>add_test</code>.</li>
</ul>
<p>I once spent a week adapting <code>protoc</code> paths and compile options for a Protobuf-dependent project in CI. With kmcmake, the CI script is simplified to:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Configure + Build + Test + Install—no extra steps</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">cmake --preset default -DKMCMAKE_BUILD_TEST=ON</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">cmake --build build</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">ctest --test-dir build</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">cmake --install build</span><br></span></code></pre></div></div>
<p>No more cross-platform headaches—kmcmake encapsulates all adaptation logic in the configuration phase.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-effortless-deployment-rule-automation-in-generation--installation-phases">3. Effortless Deployment: Rule Automation in Generation + Installation Phases<a href="https://kumo-pub.github.io/goose/blog/mdx-blog#3-effortless-deployment-rule-automation-in-generation--installation-phases" class="hash-link" aria-label="Direct link to 3. Effortless Deployment: Rule Automation in Generation + Installation Phases" title="Direct link to 3. Effortless Deployment: Rule Automation in Generation + Installation Phases" translate="no">​</a></h3>
<p>Deployment success means "third-party projects can find your library." This requires generating <code>Config.cmake</code> during the generation phase and copying files correctly during installation. Raw CMake needs:</p>
<div class="language-cmake codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cmake codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Raw CMake: Generate Config.cmake (verbose + error-prone)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">include(CMakePackageConfigHelpers)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">write_basic_package_version_file(</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  my_libConfigVersion.cmake</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  VERSION 1.0.0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  COMPATIBILITY SameMajorVersion</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">configure_package_config_file(</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  ${CMAKE_CURRENT_SOURCE_DIR}/my_libConfig.cmake.in</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  ${CMAKE_CURRENT_BINARY_DIR}/my_libConfig.cmake</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/my_lib</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  PATH_VARS CMAKE_INSTALL_INCLUDEDIR CMAKE_INSTALL_LIBDIR</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">install(</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  FILES</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    ${CMAKE_CURRENT_BINARY_DIR}/my_libConfig.cmake</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    ${CMAKE_CURRENT_BINARY_DIR}/my_libConfigVersion.cmake</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/my_lib</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">)</span><br></span></code></pre></div></div>
<p>You also need to manually create a <code>my_libConfig.cmake.in</code> template—one mistake breaks <code>find_package</code> for third parties. kmcmake’s solution:</p>
<ul>
<li class=""><strong>Generation Phase</strong>: Automatically calls <code>write_basic_package_version_file</code> and <code>configure_package_config_file</code> to generate <code>Config.cmake</code> and <code>ConfigVersion.cmake</code>—no manual templates.</li>
<li class=""><strong>Installation Phase</strong>: Auto-installs config files to <code>${CMAKE_INSTALL_LIBDIR}/cmake/{NAME}</code>, ensuring third parties can find your library via <code>find_package</code>.</li>
<li class=""><strong>Underlying Logic</strong>: kmcmake extracts target include paths, dependencies, and compile options during generation, writing them to config files. When third parties call <code>find_package</code>, CMake loads this information for "one-click linking."</li>
</ul>
<p>I once spent hours debugging a library where users couldn’t link to it—turns out I’d messed up <code>Config.cmake</code>. With kmcmake, <code>make install</code> is all you need; third parties just use <code>find_package(my_lib REQUIRED)</code> to link, no more "library not found" issues.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-no-hidden-rules-transparent-logic-in-the-configuration-phase">4. No Hidden Rules: Transparent Logic in the Configuration Phase<a href="https://kumo-pub.github.io/goose/blog/mdx-blog#4-no-hidden-rules-transparent-logic-in-the-configuration-phase" class="hash-link" aria-label="Direct link to 4. No Hidden Rules: Transparent Logic in the Configuration Phase" title="Direct link to 4. No Hidden Rules: Transparent Logic in the Configuration Phase" translate="no">​</a></h3>
<p>Most CMake newbies struggle with "configuration phase execution order" and "variable scope": <code>find_package</code> must come before <code>add_library</code>, <code>PUBLIC</code>/<code>PRIVATE</code> in <code>target_include_directories</code> must be correctly used—these "hidden rules" are daunting. kmcmake’s "transparent logic" follows CMake’s native execution order with no secrets:</p>
<ul>
<li class=""><strong>Clear Parameters</strong>: <code>INCLUDES</code> maps to <code>target_include_directories(PUBLIC)</code>, <code>PINCLUDES</code> to <code>PRIVATE</code>; <code>LINKS</code> to <code>target_link_libraries(PUBLIC)</code>, <code>PLINKS</code> to <code>PRIVATE</code>—no ambiguity.</li>
<li class=""><strong>Fixed Execution Order</strong>: kmcmake macros first run <code>find_package</code> (if dependencies exist), then <code>add_library</code>, and finally <code>target_*</code> commands—aligning perfectly with CMake’s native flow.</li>
<li class=""><strong>Clear Error Messages</strong>: If a dependency is missing, kmcmake directly prints "Could not find XXX—please install or set XXX path" instead of failing silently, simplifying debugging.</li>
</ul>
<p>I once wasted hours troubleshooting a <code>find_package</code> failure—turns out I’d misconfigured <code>CMAKE_INSTALL_PREFIX</code>. These hidden rules are impossible for newbies to guess, but kmcmake makes all logic explicit: configure intuitively, and it works.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-unix-like-system-compatibility-standard-adaption-in-configuration--generation-phases">5. Unix-like System Compatibility: Standard Adaption in Configuration + Generation Phases<a href="https://kumo-pub.github.io/goose/blog/mdx-blog#5-unix-like-system-compatibility-standard-adaption-in-configuration--generation-phases" class="hash-link" aria-label="Direct link to 5. Unix-like System Compatibility: Standard Adaption in Configuration + Generation Phases" title="Direct link to 5. Unix-like System Compatibility: Standard Adaption in Configuration + Generation Phases" translate="no">​</a></h3>
<p>Compatibility issues on Unix-like systems stem from differences in "dependency discovery" (configuration phase) and "path rules" (generation phase). kmcmake’s solution:</p>
<ul>
<li class=""><strong>Configuration Phase</strong>: Auto-includes <code>GNUInstallDirs</code>, using standard variables like <code>CMAKE_INSTALL_LIBDIR</code> and <code>CMAKE_INSTALL_INCLUDEDIR</code>—no manual path setting.</li>
<li class=""><strong>Generation Phase</strong>: Generated Makefiles follow Unix-like compile standards, installing libraries to <code>/usr/local/lib</code> and headers to <code>/usr/local/include</code>—matching default third-party library search paths.</li>
<li class=""><strong>Dependency Discovery</strong>: Prioritizes <code>find_package</code>’s standard modes and supports <code>CMAKE_PREFIX_PATH</code>, eliminating manual dependency path setting on Unix-like systems.</li>
</ul>
<p>I once wrote two sets of <code>if-else</code> in raw CMake to adapt dependency paths for Linux and macOS. With kmcmake, one configuration works for both—no system-specific logic needed.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="6-zero-intrusion-native-compatibility-in-the-configuration-phase">6. Zero Intrusion: Native Compatibility in the Configuration Phase<a href="https://kumo-pub.github.io/goose/blog/mdx-blog#6-zero-intrusion-native-compatibility-in-the-configuration-phase" class="hash-link" aria-label="Direct link to 6. Zero Intrusion: Native Compatibility in the Configuration Phase" title="Direct link to 6. Zero Intrusion: Native Compatibility in the Configuration Phase" translate="no">​</a></h3>
<p>kmcmake’s core is "encapsulation, not replacement"—it’s fully compatible with raw CMake directives. You can extend configurations with native CMake after kmcmake macros without breaking existing logic:</p>
<div class="language-cmake codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-cmake codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># kmcmake macro + raw CMake: zero-intrusion extension</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kmcmake_cc_library(</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    NAME my_lib</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    SOURCES src/my_lib.cc</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    INCLUDES include</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Raw CMake extension: add custom compile options (runs during configuration)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">target_compile_options(my_lib PRIVATE -Wno-unused-parameter)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Raw CMake extension: add conditional logic (runs during configuration)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">if(BUILD_TESTING)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  add_subdirectory(tests)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">endif()</span><br></span></code></pre></div></div>
<ul>
<li class=""><strong>Underlying Logic</strong>: kmcmake creates standard CMake targets (e.g., <code>my_lib</code>) that can be modified with subsequent raw <code>target_*</code> commands—fully aligning with CMake’s target management.</li>
</ul>
<p>I once used a framework that forced source code into a <code>src</code> directory, requiring a week of project restructuring. kmcmake imposes no directory structure rules—it doesn’t hold your project hostage; add or modify as needed.</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="7-no-new-tools-a-wrapper-layer-on-cmakes-native-workflow">7. No New Tools: A Wrapper Layer on CMake’s Native Workflow<a href="https://kumo-pub.github.io/goose/blog/mdx-blog#7-no-new-tools-a-wrapper-layer-on-cmakes-native-workflow" class="hash-link" aria-label="Direct link to 7. No New Tools: A Wrapper Layer on CMake’s Native Workflow" title="Direct link to 7. No New Tools: A Wrapper Layer on CMake’s Native Workflow" translate="no">​</a></h3>
<p>First principles emphasize "avoiding redundancy": CMake is an industry standard with a mature ecosystem supporting all Unix-like systems. Building a new build tool is unnecessary (time-consuming, labor-intensive, and adoption-challenged). kmcmake positions itself as a "wrapper layer" for CMake, with all features built on its three core phases:</p>
<ul>
<li class="">It doesn’t modify CMake’s native workflow—only automates repetitive <code>target_*</code> and <code>install</code> commands during configuration.</li>
<li class="">It requires no extra tools—just CMake 3.21+—no additional binary installations.</li>
<li class="">It doesn’t break CMake’s ecosystem—supports all libraries discoverable via <code>find_package</code> and all native CMake variables/directives.</li>
</ul>
<p>You don’t need to understand chip design to use a phone, and you don’t need to master CMake’s underlying workflow to use kmcmake—but if you want to, every feature maps to specific CMake operations, fully credible and transparent.</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="conclusion-first-principles--cmake-workflow--simplified-building">Conclusion: First Principles + CMake Workflow = Simplified Building<a href="https://kumo-pub.github.io/goose/blog/mdx-blog#conclusion-first-principles--cmake-workflow--simplified-building" class="hash-link" aria-label="Direct link to Conclusion: First Principles + CMake Workflow = Simplified Building" title="Direct link to Conclusion: First Principles + CMake Workflow = Simplified Building" translate="no">​</a></h2>
<p>We find C++ project building cumbersome because we confuse "tool syntax" with "core needs"—we don’t need to "master CMake’s three phases and all directives," but to "avoid spending half a month on a single library"; we don’t need to "grasp complex concepts like generator expressions and dependency propagation," but to "set up projects in 5 minutes, integrate with CI seamlessly, and deploy effortlessly."</p>
<p>First principles help us cut through the noise and return to CMake’s workflow essence: modularizing and automating complex operations at each phase, so developers focus on "end goals" instead of "phase details." kmcmake doesn’t invent new build logic—it translates CMake’s three core phases into simple, usable interfaces via first principles. Every macro corresponds to a series of standard CMake operations in configuration, generation, and installation—precise, transparent, and unambiguous.</p>
<p>Now, you no longer need to spend weeks learning CMake, struggle with Makefile syntax, worry about toolchain migration costs, or waste half a month integrating a library—kmcmake handles it all. You can focus on writing great business code.</p>
<p>After all, we’re C++ developers, not "build tool engineers." Let tools return to their essence (automating repetitive work via underlying workflows), and let us return to ours (focusing on business logic)—that’s the true power of first principles.</p>
<p>If you’re tired of build tool chaos and the pain of spending half a month compiling one library, give kmcmake a try—5-minute setup, zero learning curve, and C++ project building as easy as breathing, with full transparency into the "why" behind it.</p>]]></content:encoded>
            <category>CMake</category>
        </item>
    </channel>
</rss>