<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>binaries &#8211; Best DevOps</title>
	<atom:link href="https://www.bestdevops.com/tag/binaries/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.bestdevops.com</link>
	<description>Lets Learn, Do it &#38; Share! Thats a Best DevOps!!!</description>
	<lastBuildDate>Tue, 13 Oct 2026 07:46:00 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.3</generator>
	<item>
		<title>The Pipeline-Driven Organization: Enabling True Continuous Delivery</title>
		<link>https://www.bestdevops.com/the-pipeline-driven-organization-enabling-true-continuous-delivery/</link>
					<comments>https://www.bestdevops.com/the-pipeline-driven-organization-enabling-true-continuous-delivery/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Sat, 20 Jul 2019 05:33:03 +0000</pubDate>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[binaries]]></category>
		<category><![CDATA[CI/CD Servers]]></category>
		<category><![CDATA[deployed application]]></category>
		<category><![CDATA[log]]></category>
		<category><![CDATA[pipelines and culture]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=6338</guid>

					<description><![CDATA[What does it take to deploy like Netflix, Amazon, or Google? The answer is a pipeline-driven culture—one where automated pipelines make tactical decisions and remove human bottlenecks from the path to production.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><em>This article is based on concepts originally published on <a href="https://www.infoq.com" rel="noopener">InfoQ</a>, attributed to Roy Osherove.</em></p>



<h2 class="wp-block-heading">What Separates High-Velocity Engineering Organizations?</h2>



<p class="wp-block-paragraph">Organizations like Netflix, Amazon, and Google deploy changes to production many times per day. Most medium and large companies aspire to that cadence but never reach it. The gap is rarely a tooling problem. The difference is almost always cultural—specifically, how teams relate to their delivery pipelines and what decisions they allow those pipelines to make autonomously.</p>



<p class="wp-block-paragraph">This article explores the concept of the <strong>pipeline-driven organization</strong>: a model in which automated pipelines handle tactical, day-to-day software delivery decisions, freeing engineers to focus on strategic work and on improving the pipelines themselves.</p>



<h2 class="wp-block-heading">Understanding Pipelines</h2>



<p class="wp-block-paragraph">A pipeline is a sequence of one or more automated tasks (often called <em>jobs</em> or <em>steps</em>) that run in a defined order to produce a result. Every pipeline produces two types of output:</p>



<ul class="wp-block-list">
<li><strong>A judgment result:</strong> the pipeline either passed or failed. Inconclusive results should be treated as failures—ambiguity is the enemy of automation.</li>
<li><strong>Artifacts:</strong> deployed applications, compiled binaries, test reports, log files, or any other output that the team cares about.</li>
</ul>



<h3 class="wp-block-heading">Tasks: The Building Blocks</h3>



<p class="wp-block-paragraph">At the core of every pipeline is a <em>task</em>—a shell script or program that runs automatically on a machine (local or cloud-hosted). The task executes one or more operations (compiling code, running tests, scanning for vulnerabilities) and returns an <strong>exit code</strong>:</p>



<ul class="wp-block-list">
<li><strong>Exit code 0:</strong> success.</li>
<li><strong>Any non-zero exit code:</strong> failure.</li>
</ul>



<p class="wp-block-paragraph">This binary signal is the foundation on which all pipeline automation is built. Everything—from a unit test suite to a security scan to a deployment script—ultimately communicates its result through this mechanism.</p>



<h3 class="wp-block-heading">CI/CD Servers: The Orchestration Layer</h3>



<p class="wp-block-paragraph">Tools such as Jenkins, GitLab CI, GitHub Actions, and CircleCI act as an orchestration layer on top of individual tasks. A CI/CD server:</p>



<ul class="wp-block-list">
<li>Triggers tasks automatically based on code commits, pull requests, schedules, or other events.</li>
<li>Listens to exit codes and captures log output.</li>
<li>Presents results in a UI, highlighting failures and surfacing artifacts.</li>
<li>Runs tasks in parallel across multiple agents or machines.</li>
<li>Manages dependencies between tasks—ensuring step B only runs when step A passes.</li>
</ul>



<p class="wp-block-paragraph">CI/CD servers transform individual scripts into a coherent, observable, and manageable delivery system.</p>



<h2 class="wp-block-heading">What Does &#8220;Pipeline-Driven&#8221; Actually Mean?</h2>



<p class="wp-block-paragraph">Being pipeline-driven means deliberately shifting as many <em>tactical</em> decisions as possible from humans to the pipeline itself, and then allowing the pipeline to act on those decisions autonomously.</p>



<p class="wp-block-paragraph">To understand why this matters, it helps to distinguish between two categories of decisions in software development:</p>



<figure class="wp-block-table"><table><thead><tr><th>Decision Type</th><th>Examples</th><th>Best Made By</th></tr></thead><tbody><tr><td><strong>Strategic</strong></td><td>&#8220;Should we build this product?&#8221; &#8220;Which feature do we prioritize next?&#8221;</td><td>Humans</td></tr><tr><td><strong>Tactical</strong></td><td>&#8220;Should we merge this branch?&#8221; &#8220;Is the app ready to deploy?&#8221; &#8220;Did we introduce new bugs?&#8221; &#8220;Is the build secure?&#8221;</td><td>Pipelines</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">Strategic decisions require judgment, context, business acumen, and creative thinking—all things humans excel at. Tactical decisions require repeatability, speed, and freedom from bias or fatigue—all things machines excel at.</p>



<h2 class="wp-block-heading">Why Pipelines Make Better Tactical Decisions</h2>



<h3 class="wp-block-heading">Speed</h3>



<p class="wp-block-paragraph">A pipeline can evaluate hundreds of test results and metrics in seconds. A human reviewing the same information takes minutes or hours—and that delay compounds across every release cycle. Additionally, humans hesitate. The psychological weight of approving a production deployment introduces latency that pipelines simply do not experience.</p>



<h3 class="wp-block-heading">Reliability and Repeatability</h3>



<p class="wp-block-paragraph">Humans forget steps, especially during repetitive, low-stimulation tasks. A pipeline executes the same checklist in the same order every single time. It does not skip the security scan because the release is running late. It does not approve a deployment because it trusts the developer who wrote the code. It checks what it was taught to check, without exception.</p>



<h3 class="wp-block-heading">Reduced Stress</h3>



<p class="wp-block-paragraph">Consider the pressure on a QA lead who must verbally approve a major production release in front of senior leadership. That person is the last human gate between potentially broken code and millions of users. The stress of that position is real and significant—and it does not improve decision quality. When a pipeline makes that call based on objective criteria, the human element of anxiety, social pressure, and fear of blame is removed from the equation.</p>



<h2 class="wp-block-heading">Teaching a Pipeline to Drive</h2>



<p class="wp-block-paragraph">Trusting a pipeline to make autonomous decisions requires first teaching it how to judge correctly. This is done by embedding automated steps, scripts, and <em>quality gates</em> into the pipeline—each configured to pass or fail based on specific, measurable criteria.</p>



<p class="wp-block-paragraph">Common quality gate patterns include:</p>



<ul class="wp-block-list">
<li><strong>Test results:</strong> fail the pipeline if any automated test fails.</li>
<li><strong>Coverage thresholds:</strong> fail if code coverage drops below a defined percentage.</li>
<li><strong>Static analysis:</strong> fail if a linter or security scanner reports issues above a severity threshold.</li>
<li><strong>Performance metrics:</strong> fail if a performance test shows regression beyond an acceptable margin.</li>
<li><strong>Sub-pipeline results:</strong> fail if any parallel or child pipeline fails.</li>
<li><strong>Log analysis:</strong> fail if specific error patterns appear in output logs.</li>
</ul>



<p class="wp-block-paragraph">Every quality gate you add is one less human bottleneck on the path to production. The goal is to encode the collective knowledge and standards of your engineering organization directly into the pipeline.</p>



<h2 class="wp-block-heading">Traditional vs. Pipeline-Driven Flows</h2>



<h3 class="wp-block-heading">Traditional (Human-Gated) Flow</h3>



<p class="wp-block-paragraph">In a traditional flow, the pipeline completes a stage and then <em>notifies</em> a human. That human reviews the output, makes a judgment call, and manually triggers the next stage. Each handoff between stages is a potential delay—waiting for the right person to be available, to feel confident enough to approve, or to prioritize the review over other work.</p>



<p class="wp-block-paragraph">Knowledge is siloed. The Dev team owns the build pipeline. The QA team owns the test approval. The Ops team owns the deployment trigger. Each transition between silos introduces friction, miscommunication, and delay.</p>



<h3 class="wp-block-heading">Pipeline-Driven Flow</h3>



<p class="wp-block-paragraph">In a pipeline-driven flow, each stage triggers the next automatically if the quality gates pass. The pipeline does not wait for a human to approve the move from testing to staging, or from staging to production. Decision logic that was previously held in people&#8217;s heads is now encoded as automated steps within the pipeline itself.</p>



<p class="wp-block-paragraph">Each knowledge silo—Dev, QA, Ops, Security—contributes its expertise to the pipeline rather than acting as a manual gatekeeper. The pipeline becomes the shared artifact that encodes organizational standards and executes them without delay.</p>



<h2 class="wp-block-heading">New Skills Required for a Pipeline-Driven World</h2>



<p class="wp-block-paragraph">Moving to a pipeline-driven model changes what skills are valuable across all engineering roles. The silos that typically separate Dev, QA, Ops, and Security must become more permeable.</p>



<ul class="wp-block-list">
<li><strong>Development skills (for everyone):</strong> Pipelines are code. Contributing to a pipeline—adding steps, fixing failures, improving performance—requires basic scripting and programming ability. Engineers in all disciplines need enough coding literacy to read and modify pipeline definitions.</li>
<li><strong>Testing skills (for developers and ops):</strong> A pipeline is, at its core, a large automated test suite. Every step either passes or fails. Contributing meaningfully to a pipeline requires a testing mindset: the ability to envision how to verify something automatically rather than checking it manually.</li>
<li><strong>Operations skills (for developers and QA):</strong> Understanding how pipelines are configured, how to read their outputs, how to add or remove steps, and how to debug failures is no longer exclusive to Ops. Anyone who touches the pipeline needs this operational literacy.</li>
<li><strong>Security skills (for everyone):</strong> Security can no longer live exclusively in its own silo. When everyone has the ability to write code that runs in a pipeline, security awareness and secure coding practices must be distributed across all roles. Security specialists shift from gatekeepers to educators and pipeline contributors.</li>
</ul>



<h2 class="wp-block-heading">Enabling True Continuous Delivery</h2>



<p class="wp-block-paragraph">Continuous Delivery is the practice of keeping software in a state where it can be reliably released at any time. Many organizations adopt the vocabulary of CD without achieving its substance—because they retain human bottlenecks between pipeline stages.</p>



<p class="wp-block-paragraph">True continuous delivery requires removing those bottlenecks. If a pipeline passes all quality gates, the deployment happens automatically. If it fails, nothing deploys. No meetings, no approvals, no heroics.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>&#8220;If a pipeline fails—no deployment. If it passes—we deploy. No humans involved.&#8221;</p></blockquote>



<p class="wp-block-paragraph">This is the model that organizations operating at scale have embraced. Rather than relying on human judgment at every stage, they invest in teaching their pipelines to make those judgments correctly. Engineers become pipeline educators rather than pipeline gatekeepers.</p>



<h2 class="wp-block-heading">Summary: The Business Case for Pipeline-Driven Culture</h2>



<p class="wp-block-paragraph">Becoming pipeline-driven is not simply a technical choice—it is a competitive one. Organizations that can deliver software continuously and reliably can respond faster to market changes, resolve production issues sooner, and iterate on product features more quickly than those constrained by manual approval chains.</p>



<p class="wp-block-paragraph">The path there requires:</p>



<ol class="wp-block-list">
<li><strong>Identifying every human decision point</strong> in your current delivery process.</li>
<li><strong>Determining which of those are tactical</strong>—repeatable, measurable, automatable.</li>
<li><strong>Encoding the decision logic</strong> for those tactical steps into the pipeline as quality gates.</li>
<li><strong>Building trust in the pipeline</strong> by starting with lower-risk environments and progressively extending automation toward production.</li>
<li><strong>Upskilling all engineering roles</strong> to be able to contribute to, read, and improve the pipeline.</li>
</ol>



<p class="wp-block-paragraph">The engineers who will thrive in this environment are those who can code, test, think in systems, and share knowledge across traditional role boundaries. The organizations that will thrive are those that invest in pipeline quality the same way they invest in product quality—because in a pipeline-driven world, the two are inseparable.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/the-pipeline-driven-organization-enabling-true-continuous-delivery/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Habitat Application Portability and Understanding Dynamic Linking of ELF Binaries</title>
		<link>https://www.bestdevops.com/habitat-application-portability-and-understanding-dynamic-linking-of-elf-binaries/</link>
					<comments>https://www.bestdevops.com/habitat-application-portability-and-understanding-dynamic-linking-of-elf-binaries/#respond</comments>
		
		<dc:creator><![CDATA[anil]]></dc:creator>
		<pubDate>Fri, 13 Jan 2017 16:51:07 +0000</pubDate>
				<category><![CDATA[Continuous Delivery]]></category>
		<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[DevOps Updates]]></category>
		<category><![CDATA[application]]></category>
		<category><![CDATA[binaries]]></category>
		<category><![CDATA[Chef]]></category>
		<category><![CDATA[configuration management]]></category>
		<category><![CDATA[dynamic]]></category>
		<category><![CDATA[linking]]></category>
		<category><![CDATA[portability]]></category>
		<guid isPermaLink="false">http://www.bestdevops.com/?p=335</guid>

					<description><![CDATA[Learn how Chef Habitat uses dynamic linking and ELF binary metadata to guarantee that the exact dependencies linked at build time are loaded at runtime, enabling true application portability across Linux environments.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><em>This article is based on a post originally published on blog.chef.io and expanded for a DevOps engineering audience.</em></p>



<h2 class="wp-block-heading">Background: Why Native Binary Dependencies Are Complicated</h2>



<p class="wp-block-paragraph">If your primary experience is with managed-runtime languages — Java, C#, Ruby — or with Windows development, you may never have had to think deeply about how a compiled binary finds its dependencies at runtime on Linux. On Windows, finding a missing low-level dependency usually means downloading an MSI and moving on. The situation on Linux is meaningfully different, and understanding it is essential for anyone building software with <a href="https://www.habitat.sh/">Chef Habitat</a>.</p>



<p class="wp-block-paragraph">This article explains the fundamentals of ELF binaries, static versus dynamic linking, and how Habitat exploits dynamic linking to deliver genuine, dependency-complete application portability.</p>



<h2 class="wp-block-heading">What Is an ELF Binary?</h2>



<p class="wp-block-paragraph"><strong>ELF</strong> stands for <strong>Executable and Linkable Format</strong>. It is the standard binary format used for executables, shared libraries, and object files on Linux and most Unix-like systems. An ELF file is structured as a set of headers followed by named sections (commonly <code>.text</code> for machine instructions, <code>.data</code> for initialised data, and so on).</p>



<p class="wp-block-paragraph">One of the most important jobs of an ELF binary is to tell the operating system how to load the program into memory and which external symbols (functions, variables) must be resolved before the program can run. That information lives in dedicated ELF sections and is read by the dynamic linker — typically <code>ld-linux.so</code> — every time the binary is executed.</p>



<h2 class="wp-block-heading">Compiling vs. Linking: Two Distinct Steps</h2>



<p class="wp-block-paragraph">Developers often use the word &#8220;compiling&#8221; to mean the whole build process, but there are actually two separate operations:</p>



<ul class="wp-block-list">
<li><strong>Compiling</strong> — The compiler reads source code files and translates them into machine-language <em>object files</em> (<code>.o</code> files). Object files on their own cannot be executed.</li>
<li><strong>Linking</strong> — The linker (<code>ld</code> on Linux) takes one or more object files, resolves references to external libraries, and produces a final executable or shared library. If your code calls a function from an external library and that function cannot be found, the linker — not the compiler — reports the error.</li>
</ul>



<h2 class="wp-block-heading">Static vs. Dynamic Linking</h2>



<h3 class="wp-block-heading">Static Linking</h3>



<p class="wp-block-paragraph">In static linking, the machine code from every external library is copied directly into the final executable. The result is a single, self-contained binary with no runtime dependency on external shared object files. Static binaries are easy to deploy, but they are larger and must be recompiled and redeployed whenever a dependency is updated (for example, to patch a security vulnerability).</p>



<h3 class="wp-block-heading">Dynamic Linking</h3>



<p class="wp-block-paragraph">Dynamic linking keeps external code outside the executable. Instead of embedding library code, the linker writes metadata into the ELF binary that names the required shared object files (<code>.so</code> on Linux, <code>.dll</code> on Windows). When the binary is executed, the operating system&#8217;s dynamic linker reads that metadata and loads the correct shared libraries into the process at runtime.</p>



<p class="wp-block-paragraph">The benefits of dynamic linking include:</p>



<ul class="wp-block-list">
<li>Smaller application binaries, because library code is not duplicated.</li>
<li>The ability to update a shared library across all applications that use it without recompiling any of them.</li>
<li>Memory efficiency, because the OS can share a single copy of a loaded library between multiple running processes.</li>
</ul>



<p class="wp-block-paragraph">The trade-off is that the correct version of every required shared library must be present on the target machine at runtime. This is the classic source of &#8220;it works on my machine&#8221; deployment failures.</p>



<h2 class="wp-block-heading">How the Linux Dynamic Linker Finds Shared Libraries</h2>



<p class="wp-block-paragraph">The linker (<code>ld</code>) and the runtime dynamic linker (<code>ld-linux.so</code>) follow a strict, ordered set of rules when searching for shared libraries. Understanding this order is critical for diagnosing dependency errors and for understanding how Habitat controls the process. The following search order is taken directly from the <code>ld</code> man page:</p>



<ol class="wp-block-list">
<li>Directories specified by <code>-rpath-link</code> options (link time only; not embedded in the binary).</li>
<li>Directories specified by <code>-rpath</code> options (embedded in the ELF binary and honoured at runtime).</li>
<li>The contents of the <code>LD_RUN_PATH</code> environment variable, if <code>-rpath</code> and <code>-rpath-link</code> were not used (ELF, native linkers only).</li>
<li>On SunOS, directories specified by <code>-L</code> options if <code>-rpath</code> was not used.</li>
<li>The contents of the <code>LD_LIBRARY_PATH</code> environment variable (native linkers).</li>
<li>The <code>DT_RUNPATH</code> or <code>DT_RPATH</code> entries inside a shared library being loaded (<code>DT_RPATH</code> is ignored if <code>DT_RUNPATH</code> is present).</li>
<li>The default system directories: normally <code>/lib</code> and <code>/usr/lib</code>.</li>
<li>Directories listed in <code>/etc/ld.so.conf</code> (ELF systems with a native linker).</li>
</ol>



<p class="wp-block-paragraph">Two entries in this list are especially important for Habitat: <strong><code>-rpath</code></strong> (step 2) and <strong><code>DT_RUNPATH</code>/<code>DT_RPATH</code></strong> (step 6). Both allow a path to be baked directly into an ELF binary so that the runtime linker knows exactly where to look — regardless of what is installed in <code>/usr/lib</code> or what <code>LD_LIBRARY_PATH</code> says.</p>



<h2 class="wp-block-heading">The Dependency Problem in Traditional Linux Deployments</h2>



<p class="wp-block-paragraph">Consider a common scenario: your application depends on the ZeroMQ library. During development you run <code>apt-get install libzmq-dev</code> and the library lands somewhere under <code>/usr</code>. Your application builds and runs. When you promote to production, you (or your configuration management tool) must ensure that the same library — ideally at the same version — is installed on every production node.</p>



<p class="wp-block-paragraph">This is fragile for several reasons:</p>



<ul class="wp-block-list">
<li>Different Linux distributions package different versions of the same library.</li>
<li>Two applications on the same node may require different, incompatible versions of the same library. Most package managers cannot install multiple versions of a library into <code>/usr/lib</code> simultaneously.</li>
<li>Configuration management tools such as Chef can enforce that a specific version is installed, but they cannot easily manage version conflicts between co-located applications.</li>
</ul>



<h2 class="wp-block-heading">How Habitat Solves the Problem with Dynamic Linking</h2>



<h3 class="wp-block-heading">Dependencies Travel with the Application</h3>



<p class="wp-block-paragraph">Habitat packages applications as <code>.hart</code> files. When a Habitat package is installed, Habitat also installs every package listed in the application&#8217;s dependency manifest. These packages are placed under Habitat&#8217;s own root directory (by default <code>/hab/pkgs/</code>), completely separate from the system&#8217;s <code>/usr</code> tree. They do not conflict with system-installed libraries or with libraries belonging to other Habitat-managed applications.</p>



<h3 class="wp-block-heading">Build-Time and Runtime Paths Are the Same</h3>



<p class="wp-block-paragraph">During the Habitat build process, the linker is configured to embed the paths to Habitat-managed dependencies directly into the resulting ELF binary using <code>RPATH</code> or <code>RUNPATH</code> entries. This means that at runtime, the dynamic linker resolves shared libraries from those same Habitat package directories — not from <code>/usr/lib</code> or whatever happens to be on <code>LD_LIBRARY_PATH</code>.</p>



<p class="wp-block-paragraph">The practical consequence: <strong>the exact binaries linked at build time are the exact binaries loaded at runtime</strong>. No separate configuration management layer is needed to enforce this guarantee.</p>



<h3 class="wp-block-heading">Side-by-Side Versioning</h3>



<p class="wp-block-paragraph">Because each Habitat application&#8217;s dependencies live under their own versioned paths within <code>/hab/pkgs/</code>, two applications on the same node can depend on different versions of the same library and run simultaneously without conflict. The RPATH baked into each binary points to its own specific dependency version.</p>



<h2 class="wp-block-heading">The Habitat Studio: Keeping Builds Clean</h2>



<p class="wp-block-paragraph">A potential weakness in this model is the build step itself. If during a build the linker silently falls through to <code>/usr/lib</code> and picks up a system library that is not listed as a Habitat dependency, the resulting binary will have a runtime dependency that Habitat does not know about and will not install. The package would break on any node that does not happen to have that exact system library version installed.</p>



<p class="wp-block-paragraph">Habitat prevents this with the <strong>Studio</strong>: a clean, minimal, isolated build environment. Inside the Studio, system library paths are not available to the linker. The only libraries the linker can find are those explicitly declared as Habitat dependencies in the build plan. If your plan is missing a dependency, the build fails loudly inside the Studio — which is exactly the right behaviour. A build failure during development is far preferable to a mysterious runtime failure in production.</p>



<h2 class="wp-block-heading">Practical Implications for Plan Authors</h2>



<p class="wp-block-paragraph">Understanding the ELF linker search order and how Habitat manipulates it helps you write better build plans and diagnose build failures faster. Key points to keep in mind:</p>



<ul class="wp-block-list">
<li><strong>Declare all dependencies explicitly.</strong> If a library your software needs is not in your plan&#8217;s dependency list, the Studio build will fail. Treat that failure as useful signal, not an annoyance.</li>
<li><strong>Be cautious with build systems that hard-code paths.</strong> CMake files, configure scripts, and downloaded pre-built binaries may expect libraries in <code>/usr/lib</code>. Inside the Habitat Studio those paths do not exist, so such build systems require patching or careful configuration.</li>
<li><strong>Understand <code>-rpath</code> vs <code>LD_LIBRARY_PATH</code>.</strong> Relying on <code>LD_LIBRARY_PATH</code> at runtime is fragile because it can be overridden or unset. Habitat favours embedding paths directly in the binary via <code>RPATH</code>/<code>RUNPATH</code>, which is more robust.</li>
<li><strong>Software that uses non-GCC toolchains adds complexity.</strong> Projects that use Clang or non-standard build systems (such as .NET Core) may download pre-compiled binaries or have build scripts that assume standard filesystem layouts. These require additional work to Habitat-ise correctly.</li>
</ul>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">ELF binaries on Linux carry metadata that tells the dynamic linker exactly where to find shared library dependencies at runtime. By controlling that metadata during the Habitat build process — specifically by embedding Habitat package paths into the binary&#8217;s <code>RPATH</code>/<code>RUNPATH</code> — Habitat guarantees that an application always loads the same dependencies it was built against, regardless of what is installed on the host system. The Habitat Studio enforces this at build time by removing access to system library paths entirely. The result is genuine, reproducible application portability: install the <code>.hart</code> package and everything the application needs comes with it.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.bestdevops.com/habitat-application-portability-and-understanding-dynamic-linking-of-elf-binaries/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
