-
-
Notifications
You must be signed in to change notification settings - Fork 50
/
mini_portile_cmake.rb
147 lines (118 loc) · 3.86 KB
/
mini_portile_cmake.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
require 'mini_portile2/mini_portile'
require 'open3'
class MiniPortileCMake < MiniPortile
attr_accessor :system_name
def configure_prefix
"-DCMAKE_INSTALL_PREFIX=#{File.expand_path(port_path)}"
end
def initialize(name, version, **kwargs)
super(name, version, **kwargs)
@cmake_command = kwargs[:cmake_command]
@cmake_build_type = kwargs[:cmake_build_type]
end
def configure_defaults
[
generator_defaults,
cmake_compile_flags,
].flatten
end
def configure
return if configured?
cache_file = File.join(tmp_path, 'configure.options_cache')
File.open(cache_file, "w") { |f| f.write computed_options.to_s }
execute('configure', [cmake_cmd] + computed_options + ["."])
end
def configured?
configure = File.join(work_path, 'configure')
makefile = File.join(work_path, 'CMakefile')
cache_file = File.join(tmp_path, 'configure.options_cache')
stored_options = File.exist?(cache_file) ? File.read(cache_file) : ""
current_options = computed_options.to_s
(current_options == stored_options) && newer?(makefile, configure)
end
def make_cmd
return "nmake" if MiniPortile.mswin?
super
end
def cmake_cmd
(ENV["CMAKE"] || @cmake_command || "cmake").dup
end
def cmake_build_type
(ENV["CMAKE_BUILD_TYPE"] || @cmake_build_type || "Release").dup
end
private
def generator_defaults
if MiniPortile.mswin? && generator_available?('NMake')
['-G', 'NMake Makefiles']
elsif MiniPortile.mingw? && generator_available?('MSYS')
['-G', 'MSYS Makefiles']
else
[]
end
end
def cmake_compile_flags
c_compiler, cxx_compiler = find_c_and_cxx_compilers(host)
# 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_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
if MiniPortile.linux?
'Linux'
elsif MiniPortile.darwin?
'Darwin'
elsif MiniPortile.windows?
'Windows'
elsif MiniPortile.freebsd?
'FreeBSD'
elsif MiniPortile.openbsd?
'OpenBSD'
elsif MiniPortile.solaris?
'SunOS'
else
raise "Unable to set CMAKE_SYSTEM_NAME for #{MiniPortile.target_os}"
end
end
def generator_available?(generator_type)
stdout_str, status = Open3.capture2("#{cmake_cmd} --help")
raise 'Unable to determine whether CMake supports #{generator_type} Makefile generator' unless status.success?
stdout_str.include?("#{generator_type} Makefiles")
end
def cpu_type
return 'x86_64' if MiniPortile.target_cpu == 'x64'
MiniPortile.target_cpu
end
end