forked from caldwell/build-emacs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbuild-emacs-from-tar
executable file
·149 lines (127 loc) · 6.89 KB
/
build-emacs-from-tar
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
148
149
#!/usr/bin/env ruby
# Copyright © 2014-2021 David Caldwell
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
require 'optparse'
require 'fileutils'
require 'pathname'
require_relative 'build-dependencies'
require_relative 'verbose-shell'
Vsh = VerboseShell
def build_emacs(src_dir, dep_dir, out_name, options={})
out_name = out_name + ".tar.bz2"
puts "building emacs: #{src_dir} => #{out_name}"
options[:cc] ||= "cc"
options[:extra_cc_options] ||= ''
ENV["PKG_CONFIG_PATH"]="#{dep_dir}/lib/pkgconfig:#{ENV["PKG_CONFIG_PATH"]}"
ENV["PATH"]="#{dep_dir}/bin:#{ENV["PATH"]}"
FileUtils.cd(src_dir) do
min_os_flag = options[:min_os] ? "-mmacosx-version-min=#{options[:min_os]}" : ""
configure_flags = options[:host] ? ["--host=#{options[:host]}", '--build=i686-apple-darwin'] : []
parallel_flags = options[:parallel] ? ["-j", options[:parallel]] : []
# This should be the default but isn't :-( http://debbugs.gnu.org/cgi/bugreport.cgi?bug=19850
configure_flags += ['--enable-locallisppath=/Library/Application Support/Emacs/${version}/site-lisp:/Library/Application Support/Emacs/site-lisp']
configure_flags += %W"--with-modules"
ENV['CC']="#{options[:cc]} #{min_os_flag} #{options[:extra_cc_options]}"
Vsh.system_trace(["CC=#{ENV['CC']}"])
Vsh.system(*(%W"./configure --with-ns")+configure_flags+(options[:extra_configure_flags]||[]))
Vsh.system(*(%W"make clean"))
Vsh.system(*(%W"make")+parallel_flags)
Vsh.system(*(%W"make install"))
copy_lib('nextstep/Emacs.app/Contents/MacOS/Emacs', dep_dir, "nextstep/Emacs.app/Contents/MacOS/#{options[:libdir]}") # Install and adjust libs into the App.
FileUtils.cd('nextstep') { Vsh.system(*(%W"tar cjf #{out_name} Emacs.app")) }
end
Vsh.mv(File.join(src_dir, 'nextstep', out_name), out_name, :force => true)
out_name
end
def with_writable_mode(file)
old = File.stat(file).mode
File.chmod(0775, file)
yield
File.chmod(old, file)
end
def copy_lib(exe, dep_dir, dest, options={})
options[:rel_path_to_dest] ||= "@executable_path/" + Pathname.new(dest).relative_path_from(Pathname.new(exe).dirname).to_s
`otool -L #{exe}`.split("\n").each do |line| # ex: /Volumes/sensitive/src/build-emacs/brew/opt/gnutls/lib/libgnutls.30.dylib (compatibility version 37.0.0, current version 37.6.0)
(m,orig,dep_path,lib)=line.match(%r,^\s+(#{dep_dir}(/[^ ]+)/(lib[^/ ]+))\s,).to_a
if m
with_writable_mode(exe) {
if lib == File.basename(exe)
Vsh.system(*%W"install_name_tool -id #{dest}/#{lib} #{exe}") # remove our local build path from the id to leak as litle as possible (not that it really matters)
else
Vsh.system(*%W"install_name_tool -change #{orig} #{options[:rel_path_to_dest]}/#{lib} #{exe}") # Point the libs to the newly embedded lib directory
end
}
unless lib == File.basename(exe) || File.exists?(File.join(dest, lib))
Vsh.mkdir_p(dest)
Vsh.cp(File.join(dep_dir, dep_path, lib), dest)
copy_lib(File.join(dest, lib), dep_dir, dest, options) # Copy lib's deps, too
end
end
end
end
def prepare_extra_deps(dep_dir, out_name)
extra_source = "#{out_name}-extra-source"
Vsh.rm_rf extra_source
build_dep = BuildDependencies.new(dep_dir)
build_dep.ensure()
build_dep.export_sources(extra_source)
Vsh.system(*(%W"tar cf #{extra_source}.tar #{extra_source}"))
"#{extra_source}.tar"
end
arch=`uname -m`.chomp.to_sym
parallel=false
disable_deps=false
extra_rev = ''
add_configure_flags = []
(opts=OptionParser.new do |opts|
opts.banner = "Usage:\n\t#{$0} <SOURCE_TARBALL> <KIND> [options]"
opts.on("-v", "--verbose", "Turn up the verbosity") { |v| Vsh.verbose = true }
opts.on("-a", "--arch ARCH", [:i386, :x86_64, :arm64], "Compile for ARCH instead of #{arch.to_s}") { |a| arch = a }
opts.on("-j", "--parallel PROCS", "Compile in parallel using PROCS processes") { |p| parallel = p }
opts.on( "--extra-rev REV", "Add an extra -REV to the version") { |r| extra_rev = r }
opts.on( "--no-deps", "Don't attempt to get any extra libraries") { |b| disable_deps = true }
opts.on("-A", "--add-configure-flags FLAGS", "Additional configure flags") { |c| add_configure_flags.push(c) }
opts.on_tail("-h", "--help") { puts opts; exit }
end).parse!
source_tar = ARGV.shift || opts.abort("Missing <SOURCE_TARBALL>\n\n"+opts.help)
kind = ARGV.shift || opts.abort("Missing <KIND>\n\n"+opts.help)
label = kind == 'pretest' ? 'pretest-' : ''
version = source_tar =~ %r{^(?:.*/)?emacs-(.*)\.tar} && $1 || throw("couldn't parse version from #{source_tar}")
trunk = !!(version =~ /^\d{4}-\d{2}-\d{2}/)
src_dir = 'emacs-source'
dep_dir = File.expand_path("dep")
Vsh.rm_rf src_dir
Vsh.mkdir_p src_dir
FileUtils.cd(src_dir) do
Vsh.system(*%W'tar xf #{"../"+source_tar} --strip-components=1')
end
os_maj_version = `sw_vers -productVersion`.chomp.sub(/^(\d+\.\d+)\.\d+/,'\1')
os_maj_version = $1 if os_maj_version =~ /^(\d+)\./ && $1.to_i > 10 # After 10.15.x Apple moved to 11.x, 12.x, etc.
options = arch == :i386 ? { :cc => 'i686-apple-darwin10-gcc-4.2.1', :host => 'i686-apple-darwin', :min_os => '10.5' } :
{ }
options[:min_os] = '10.7' if os_maj_version == '10.8'
options[:min_os] = '10.5' if os_maj_version == '10.6' && arch == :x86_64
options[:min_os] = '10.6' if trunk && options[:min_os] == '10.5'
options[:min_os] = '11' if os_maj_version == '12' && arch == :arm64 # Hack around thoughtless upgrade of the build machine to macOS 12 🤦
options[:extra_configure_flags] ||= []
options[:extra_configure_flags] += %w"--with-jpeg=no --with-png=no --with-gif=no --with-tiff=no" if os_maj_version == '10.6'
options[:extra_configure_flags] += %w"--with-gnutls=no" if disable_deps
options[:extra_configure_flags] += %w"CFLAGS=-DNSTextAlignmentRight=NSRightTextAlignment" if os_maj_version.to_f < 10.12
options[:extra_configure_flags] += add_configure_flags if ! add_configure_flags.empty?
options[:parallel] = parallel if parallel
options[:libdir] = 'lib-' + arch.to_s + '-' + (options[:min_os] || os_maj_version).to_s.gsub('.','_') # see similar gsub in combine-and-package
out_name = "Emacs-#{label}#{version}#{extra_rev}-#{options[:min_os] || os_maj_version}-#{arch.to_s}"
extra_source = prepare_extra_deps dep_dir, out_name unless disable_deps
binary = build_emacs src_dir, dep_dir, out_name, options
puts "Built #{binary}, #{extra_source||''}"