Skip to content

Commit

Permalink
Add cxx_command which parallels cc_command
Browse files Browse the repository at this point in the history
and use it for configuring CMake.

Related to #141 and #130.
  • Loading branch information
flavorjones committed May 29, 2024
1 parent c484eba commit c0f0564
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 90 deletions.
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,22 +85,29 @@ system-wide installation.

Some keyword arguments can be passed to the constructor to configure the commands used:

#### `cc_command`
#### `cc_command` and `cxx_command`

The compiler command that is used is configurable, and in order of preference will use:
The C compiler command that is used is configurable, and in order of preference will use:

- the `CC` environment variable (if present)
- the `:cc_command` keyword argument passed in to the constructor
- `RbConfig::CONFIG["CC"]`
- `"gcc"`

You can pass it in like so:
The C++ compiler is similarly configuratble, and in order of preference will use:

- the `CXX` environment variable (if present)
- the `:cxx_command` keyword argument passed in to the constructor
- `RbConfig::CONFIG["CXX"]`
- `"g++"`

You can pass your compiler commands to the MiniPortile constructor:

``` ruby
MiniPortile.new("libiconv", "1.13.1", cc_command: "cc")
MiniPortile.new("libiconv", "1.13.1", cc_command: "clang", cxx_command: "clang++")
```

For backwards compatibility, the constructor also supports a keyword argument `:gcc_command`.
(For backwards compatibility, the constructor also supports a keyword argument `:gcc_command` for the C compiler.)

#### `make_command`

Expand Down
5 changes: 5 additions & 0 deletions lib/mini_portile2/mini_portile.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ def initialize(name, version, **kwargs)
@source_directory = nil

@cc_command = kwargs[:cc_command] || kwargs[:gcc_command]
@cxx_command = kwargs[:cxx_command]
@make_command = kwargs[:make_command]
@open_timeout = kwargs[:open_timeout] || DEFAULT_TIMEOUT
@read_timeout = kwargs[:read_timeout] || DEFAULT_TIMEOUT
Expand Down Expand Up @@ -377,6 +378,10 @@ def cc_cmd
end
alias :gcc_cmd :cc_cmd

def cxx_cmd
(ENV["CXX"] || @cxx_command || RbConfig::CONFIG["CXX"] || "g++").dup
end

def make_cmd
(ENV["MAKE"] || @make_command || ENV["make"] || "make").dup
end
Expand Down
38 changes: 5 additions & 33 deletions lib/mini_portile2/mini_portile_cmake.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,49 +67,21 @@ def generator_defaults
end

def cmake_compile_flags
c_compiler, cxx_compiler = find_c_and_cxx_compilers(host)
# RbConfig::CONFIG['CC'] and RbConfig::CONFIG['CXX'] can contain additional flags, for example
# "clang++ -std=gnu++11" or "clang -fdeclspec". CMake is just looking for the command name.
cc_compiler = cc_cmd.split.first
cxx_compiler = cxx_cmd.split.first

# needed to ensure cross-compilation with CMake targets the right CPU and compilers
[
"-DCMAKE_SYSTEM_NAME=#{cmake_system_name}",
"-DCMAKE_SYSTEM_PROCESSOR=#{cpu_type}",
"-DCMAKE_C_COMPILER=#{c_compiler}",
"-DCMAKE_C_COMPILER=#{cc_compiler}",
"-DCMAKE_CXX_COMPILER=#{cxx_compiler}",
"-DCMAKE_BUILD_TYPE=#{cmake_build_type}",
]
end

def find_compiler(compilers)
compilers.find { |binary| which(binary) }
end

# configure automatically searches for the right compiler based on the
# `--host` parameter. However, CMake doesn't have an equivalent feature.
# Search for the right compiler for the target architecture using
# some basic heruistics.
def find_c_and_cxx_compilers(host)
c_compiler = ENV["CC"]
cxx_compiler = ENV["CXX"]

if MiniPortile.darwin?
c_compiler ||= 'clang'
cxx_compiler ||='clang++'
elsif MiniPortile.freebsd?
c_compiler ||= 'cc'
cxx_compiler ||= 'c++'
else
c_compiler ||= 'gcc'
cxx_compiler ||= 'g++'
end

c_platform_compiler = "#{host}-#{c_compiler}"
cxx_platform_compiler = "#{host}-#{cxx_compiler}"
c_compiler = find_compiler([c_platform_compiler, c_compiler])
cxx_compiler = find_compiler([cxx_platform_compiler, cxx_compiler])

[c_compiler, cxx_compiler]
end

# Full list: https://gitlab.kitware.com/cmake/cmake/-/blob/v3.26.4/Modules/CMakeDetermineSystem.cmake?ref_type=tags#L12-31
def cmake_system_name
return system_name if system_name
Expand Down
81 changes: 29 additions & 52 deletions test/test_cmake.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,23 +83,20 @@ def test_make_command_configuration
end

def test_configure_defaults_with_macos
recipe = init_recipe
recipe.host = 'some-host'

with_env({ "CC" => nil, "CXX" => nil }) do
MiniPortile.stub(:darwin?, true) do
with_stubbed_target(os: 'darwin22', cpu: 'arm64') do
with_compilers(recipe, host_prefix: true, c_compiler: 'clang', cxx_compiler: 'clang++') do
with_compilers(c_compiler: 'clang', cxx_compiler: 'clang++') do
Open3.stub(:capture2, cmake_help_mock('Unix')) do
assert_equal(
[
"-DCMAKE_SYSTEM_NAME=Darwin",
"-DCMAKE_SYSTEM_PROCESSOR=arm64",
"-DCMAKE_C_COMPILER=some-host-clang",
"-DCMAKE_CXX_COMPILER=some-host-clang++",
"-DCMAKE_C_COMPILER=clang",
"-DCMAKE_CXX_COMPILER=clang++",
"-DCMAKE_BUILD_TYPE=Release"
],
recipe.configure_defaults)
@recipe.configure_defaults)
end
end
end
Expand All @@ -108,12 +105,9 @@ def test_configure_defaults_with_macos
end

def test_configure_defaults_with_freebsd
recipe = init_recipe
recipe.host = 'some-host'

with_env({ "CC" => nil, "CXX" => nil }) do
with_stubbed_target(os: 'freebsd14') do
with_compilers(recipe, c_compiler: 'cc', cxx_compiler: 'c++') do
with_compilers(c_compiler: 'cc', cxx_compiler: 'c++') do
Open3.stub(:capture2, cmake_help_mock('Unix')) do
assert_equal(
[
Expand All @@ -123,47 +117,44 @@ def test_configure_defaults_with_freebsd
"-DCMAKE_CXX_COMPILER=c++",
"-DCMAKE_BUILD_TYPE=Release"
],
recipe.configure_defaults)
@recipe.configure_defaults)
end
end
end
end
end

def test_configure_defaults_with_manual_system_name
recipe = init_recipe
recipe.system_name = 'Custom'

MiniPortile.stub(:darwin?, false) do
with_stubbed_target do
with_compilers(recipe) do
with_compilers do
Open3.stub(:capture2, cmake_help_mock('Unix')) do
assert_equal(
[
"-DCMAKE_SYSTEM_NAME=Custom",
"-DCMAKE_SYSTEM_PROCESSOR=x86_64",
"-DCMAKE_C_COMPILER=gcc",
"-DCMAKE_CXX_COMPILER=g++",
"-DCMAKE_BUILD_TYPE=Release"
],
recipe.configure_defaults)
@recipe.stub(:system_name, 'Custom') do
assert_equal(
[
"-DCMAKE_SYSTEM_NAME=Custom",
"-DCMAKE_SYSTEM_PROCESSOR=x86_64",
"-DCMAKE_C_COMPILER=gcc",
"-DCMAKE_CXX_COMPILER=g++",
"-DCMAKE_BUILD_TYPE=Release"
],
@recipe.configure_defaults)
end
end
end
end
end
end

def test_configure_defaults_with_unix_makefiles
recipe = init_recipe

MiniPortile.stub(:linux?, true) do
MiniPortile.stub(:darwin?, false) do
with_stubbed_target do
with_compilers(recipe) do
with_compilers do
Open3.stub(:capture2, cmake_help_mock('Unix')) do
MiniPortile.stub(:mingw?, true) do
assert_equal(default_x86_compile_flags,
recipe.configure_defaults)
@recipe.configure_defaults)
end
end
end
Expand All @@ -173,15 +164,13 @@ def test_configure_defaults_with_unix_makefiles
end

def test_configure_defaults_with_msys_makefiles
recipe = init_recipe

MiniPortile.stub(:linux?, true) do
MiniPortile.stub(:darwin?, false) do
with_stubbed_target do
with_compilers(recipe) do
with_compilers do
Open3.stub(:capture2, cmake_help_mock('MSYS')) do
MiniPortile.stub(:mingw?, true) do
assert_equal(['-G', 'MSYS Makefiles'] + default_x86_compile_flags, recipe.configure_defaults)
assert_equal(['-G', 'MSYS Makefiles'] + default_x86_compile_flags, @recipe.configure_defaults)
end
end
end
Expand All @@ -191,15 +180,13 @@ def test_configure_defaults_with_msys_makefiles
end

def test_configure_defaults_with_nmake_makefiles
recipe = init_recipe

MiniPortile.stub(:linux?, true) do
MiniPortile.stub(:darwin?, false) do
with_stubbed_target do
with_compilers(recipe) do
with_compilers do
Open3.stub(:capture2, cmake_help_mock('NMake')) do
MiniPortile.stub(:mswin?, true) do
assert_equal(['-G', 'NMake Makefiles'] + default_x86_compile_flags, recipe.configure_defaults)
assert_equal(['-G', 'NMake Makefiles'] + default_x86_compile_flags, @recipe.configure_defaults)
end
end
end
Expand Down Expand Up @@ -240,21 +227,11 @@ def with_stubbed_target(os: 'linux', cpu: 'x86_64')
end
end

def with_compilers(recipe, host_prefix: false, c_compiler: 'gcc', cxx_compiler: 'g++')
mock = MiniTest::Mock.new

if host_prefix
mock.expect(:call, true, ["#{recipe.host}-#{c_compiler}"])
mock.expect(:call, true, ["#{recipe.host}-#{cxx_compiler}"])
else
mock.expect(:call, false, ["#{recipe.host}-#{c_compiler}"])
mock.expect(:call, true, [c_compiler])
mock.expect(:call, false, ["#{recipe.host}-#{cxx_compiler}"])
mock.expect(:call, true, [cxx_compiler])
end

recipe.stub(:which, mock) do
yield
def with_compilers(c_compiler: 'gcc', cxx_compiler: 'g++')
@recipe.stub(:cc_cmd, c_compiler) do
@recipe.stub(:cxx_cmd, cxx_compiler) do
yield
end
end
end

Expand Down
12 changes: 12 additions & 0 deletions test/test_cook.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,18 @@ def test_cc_command_configuration
assert_equal("asdf", MiniPortile.new("test", "1.0.0", gcc_command: "xyzzy").gcc_cmd)
end
end

def test_cxx_command_configuration
without_env("CXX") do
expected_compiler = RbConfig::CONFIG["CXX"] || "g++"
assert_equal(expected_compiler, MiniPortile.new("test", "1.0.0").cxx_cmd)
assert_equal("xyzzy", MiniPortile.new("test", "1.0.0", cxx_command: "xyzzy").cxx_cmd)
end
with_env("CXX"=>"asdf") do
assert_equal("asdf", MiniPortile.new("test", "1.0.0").cxx_cmd)
assert_equal("asdf", MiniPortile.new("test", "1.0.0", cxx_command: "xyzzy").cxx_cmd)
end
end
end


Expand Down

0 comments on commit c0f0564

Please sign in to comment.