Question

Fix Compass Native Extension Build Errors on macOS (Ruby)

rubymacosterminalcompass-sass

Question

When installing Compass version 1.0.0.alpha.17 on macOS with the system Ruby 2.0, installation fails while building the native extension for the ffi gem. The final build error is:

clang: error: unknown argument: '-multiply_definedsuppress'
make: *** [ffi_c.bundle] Error 1

What causes this native extension error, and how can Compass be installed successfully?

Short Answer

This error is not primarily a Compass error. Compass pulls in the ffi gem, which contains C code that must be compiled for your machine. The installed ffi version is using an old macOS compiler/linker option that a newer Clang toolchain rejects. You will learn how to read this kind of gem installation log, update or constrain dependencies safely, and avoid relying on macOS's system Ruby.

Concept

Ruby gems are often pure Ruby: RubyGems downloads their files and installation is complete. Other gems include a native extension, which is C, C++, Rust, or another compiled language integrated with Ruby.

ffi is one such gem. It lets Ruby code call native libraries. During installation, RubyGems performs roughly these steps:

  1. Runs extconf.rb to inspect the computer and generate a Makefile.
  2. Runs make to compile C source files.
  3. Links the compiled files into a loadable Ruby extension, such as ffi_c.bundle on macOS.

In the log, compilation mostly succeeds. The important failure is the final link command:

clang: error: unknown argument: '-multiply_definedsuppress'

That flag was accepted by older Apple build tools but is rejected by newer Clang versions. Therefore, the installed ffi 1.9.3 release is incompatible with that compiler configuration. The warnings earlier in the output are useful information, but the clang: error line and the following make failure identify the actual installation blocker.

This matters because a dependency can fail even when the gem you explicitly requested, such as Compass, contains no C code itself.

Mental Model

Think of a Ruby gem installation as assembling furniture.

  • A pure Ruby gem is preassembled: you unpack it and use it.
  • A native gem includes parts that must be assembled in your home.
  • Ruby, make, Clang, headers, and libraries are the tools and parts needed for assembly.
  • An old native extension may include instructions for an older tool. If your newer tool no longer recognizes one instruction, assembly stops.

Compass is the item you ordered, but ffi is one of the parts it depends on. The build fails while assembling that part.

Take Quiz

Syntax and Examples

Native-extension failures are usually diagnosed from the last fatal error, not the first warning.

A typical installation command is:

gem install compass

If the dependency graph allows it, first install a compatible ffi release and then install Compass:

gem install ffi --version 1.9.5
gem install compass

For a project, prefer Bundler so all developers use the same dependency versions:

# Gemfile
source "https://rubygems.org"

gem "compass"
gem "ffi", "~> 1.9.5"

Then run:

bundle install

The ~> 1.9.5 constraint means “use version 1.9.5 or a later compatible 1.9.x version, but not 1.10.0.” Bundler records the exact resolved version in Gemfile.lock.

If you specifically need the historical Compass alpha, use its exact version in the Gemfile:

gem "compass", "1.0.0.alpha.17"
gem "ffi", "~> 1.9.5"

Whether this works depends on the alpha release's declared dependency constraints. If it requires an exact incompatible ffi version, use a newer Compass release or maintain a compatible older development environment instead.

Step by Step Execution

Consider this shortened build log:

checking for ffi.h... yes
creating Makefile
compiling Function.c
linking shared-object ffi_c.bundle
clang: error: unknown argument: '-multiply_definedsuppress'
make: *** [ffi_c.bundle] Error 1

Step by step:

  1. checking for ffi.h... yes means the installer found the FFI header files it needs.
  2. creating Makefile means extconf.rb completed successfully and generated build instructions.
  3. compiling Function.c means Clang compiled at least some C source files into object files.
  4. linking shared-object ffi_c.bundle starts the final stage: combining compiled objects into a file Ruby can load.
  5. Clang rejects -multiply_definedsuppress because the old extension passed a flag unsupported by the installed compiler.
  6. make receives a nonzero exit status and stops.
  7. RubyGems reports Failed to build gem native extension, then Compass installation fails because its dependency was not installed.

The line Results logged to .../gem_make.out gives the full build log if terminal output has been truncated.

Real World Use Cases

Native Ruby dependencies appear in many practical situations:

  • Database drivers: Gems may compile bindings for PostgreSQL, MySQL, or SQLite libraries.
  • Image processing: Libraries such as ImageMagick integrations can require native headers and linker settings.
  • Performance-sensitive code: Some gems use C extensions for speed.
  • System integrations: FFI-based gems can communicate with operating-system libraries.
  • Legacy application maintenance: A project lockfile may select an old native dependency that no longer builds with a current compiler.

In each case, identify the native gem named near the final error, then check compatibility among the gem version, Ruby version, OS, compiler, and required system libraries.

Take Quiz

Real Codebase Usage

In real projects, developers avoid solving dependency problems by repeatedly installing global gems. They declare dependencies in a Gemfile and use Bundler:

source "https://rubygems.org"

gem "compass"
gem "ffi", "~> 1.9.5"

Useful workflow:

bundle install
bundle exec compass --version

bundle exec ensures the command uses the versions selected for the project rather than an unrelated globally installed gem.

Common maintenance patterns include:

  • Pinning: Temporarily specify a known-working dependency version.
  • Updating: Run bundle update ffi when a newer compatible release fixes a build issue.
  • Lockfiles: Commit Gemfile.lock for applications so CI and teammates resolve the same versions.
  • Isolation: Use a Ruby version manager such as rbenv, asdf, or RVM instead of changing the macOS-provided Ruby installation.
  • Reproducible environments: For old projects, use a container or an intentionally maintained older toolchain when modern tools cannot support the historical dependency set.

Common Mistakes

Treating every warning as the failure

The log contains C warnings, but the build actually stops at the fatal Clang error.

warning: implicit declaration ...
clang: error: unknown argument: '-multiply_definedsuppress'

Read from the bottom upward and find the first error: that causes make to fail.

Reinstalling the same incompatible version

This repeats the same build instructions and usually produces the same result:

gem install ffi --version 1.9.3

Use a compatible version instead, subject to the parent gem's dependency requirements.

Editing files inside the installed gem directory

It is possible to patch generated build files manually, but the patch disappears on reinstall and is hard to reproduce on another machine. Prefer an updated gem release, a Bundler constraint, or a maintained fork.

Using sudo gem install as the default fix

sudo changes permissions; it does not make an incompatible compiler flag valid. It can also mix project dependencies with macOS system files.

Assuming Compass itself is compiling

The log says the failing files are installed under an ffi-1.9.3 directory. Always locate the exact dependency that is being built.

Ignoring obsolete pre-release dependencies

A release named 1.0.0.alpha.17 is a pre-release. It may have old constraints or assumptions. Prefer a stable, supported release unless the project explicitly requires that pre-release.

Comparisons

SituationWhat it meansTypical response
Pure Ruby gem fails to installUsually a RubyGems, dependency, or permission issueCheck Ruby and gem version constraints
Native gem fails during extconf.rbThe configuration script cannot find headers, libraries, or toolsInstall required development libraries and inspect mkmf.log
Native gem fails during compilationC source is incompatible with the compiler or Ruby headersUpgrade the gem or use a supported toolchain
Native gem fails during linkingA linker flag or native library is missing or incompatibleUpdate the native gem; verify library paths and build tools
Global gem installInstalls into the active Ruby's gem setUseful for tools, but can cause version drift
bundle installResolves versions declared by a projectPreferred for application dependencies

A compiler warning may indicate future maintenance work, while a compiler error prevents the extension from being built. In this log, the unsupported Clang argument is an error.

Take Quiz

Cheat Sheet

# Install the normal stable Compass release
gem install compass

# Install a known newer compatible FFI release, if allowed by dependencies
gem install ffi --version 1.9.5

# Install project dependencies from a Gemfile
bundle install

# Run the project-selected executable
bundle exec compass --version

# See installed versions
gem list ffi
gem list compass
  • extconf.rb checks the environment and writes a Makefile.
  • make compiles and links native code.
  • ffi_c.bundle is the macOS native extension being built.
  • The final clang: error: usually identifies the immediate cause.
  • A newer dependency can fix an old compiler flag.
  • A Gemfile plus Gemfile.lock is safer than relying on system-wide gem versions.
  • Do not use sudo to solve compiler compatibility problems.
  • Pre-release gems can depend on outdated libraries; use stable versions when possible.

FAQ

Why does installing Compass install ffi?

RubyGems installs a gem's dependencies automatically. Compass or one of its dependencies requires ffi, so ffi must install successfully first.

What does “Failed to build gem native extension” mean?

It means RubyGems tried to compile non-Ruby code included with a gem, and the compiler or linker returned an error.

Is -multiply_definedsuppress a Ruby error?

No. It is an old compiler/linker option passed while building the native ffi extension. Clang rejects it in this environment.

Which line in the log is the important one?

The key line is:

clang: error: unknown argument: '-multiply_definedsuppress'

The subsequent make error is the result of that failure.

Should I install Xcode command-line tools?

Native gems need a working compiler toolchain, so installing current command-line tools can be necessary. However, this particular error shows that a compiler is already running; the immediate issue is the old ffi build flag.

Should I use the macOS system Ruby for development?

It is better to use an application-managed Ruby installed through a version manager. This isolates gems from system files and makes project Ruby versions reproducible.

What if Compass requires exactly ffi 1.9.3?

If the dependency constraint prevents a compatible ffi upgrade, choose a newer compatible Compass release, use a maintained fork, or run the legacy project in an environment with tools it supports.

Is installing an alpha version recommended?

Only when a project specifically requires it. Alpha releases are pre-release software and may not support modern Ruby or compiler toolchains.

Take Quiz

Mini Project

Description

Create a small Ruby project that uses Bundler to install and run Compass with explicitly managed dependencies. This demonstrates how a Gemfile prevents your project from silently using whichever global gem versions happen to be installed.

Goal

Install and run Compass through Bundler, with the ffi dependency version recorded for repeatable installs.

Requirements

Create a new directory containing a Gemfile. Declare Compass as a project dependency. Declare a compatible ffi 1.9.x version constraint. Run Bundler to generate a lockfile. Verify the Compass executable using bundle exec.

Take Quiz

Keep learning

Related questions

View more