ffi-libarchive-binary 0.5.0-arm64-mingw-ucrt

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,194 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+ require "open3"
5
+
6
+ require_relative "configuration"
7
+ require_relative "base_recipe"
8
+ require_relative "zlib_recipe"
9
+ require_relative "libexpat_recipe"
10
+ require_relative "openssl_recipe"
11
+ require_relative "xz_recipe"
12
+
13
+ module LibarchiveBinary
14
+ class LibarchiveRecipe < MiniPortileCMake
15
+ ROOT = Pathname.new(File.expand_path("../..", __dir__))
16
+ NAME = "libarchive"
17
+ def initialize
18
+ libarchive = LibarchiveBinary.library_for(NAME)
19
+ super(NAME, libarchive["version"])
20
+ @printed = {}
21
+
22
+ @files << {
23
+ url: libarchive["url"],
24
+ sha256: libarchive["sha256"],
25
+ }
26
+
27
+ @target = ROOT.join(@target).to_s
28
+
29
+ create_dependencies
30
+ end
31
+
32
+ def create_dependencies
33
+ @zlib_recipe = ZLibRecipe.new
34
+ @expat_recipe = LibexpatRecipe.new
35
+ @openssl_recipe = OpensslRecipe.new
36
+ @xz_recipe = XZRecipe.new
37
+ end
38
+
39
+ def generator_flags
40
+ MiniPortile::mingw? ? ["-G", "MSYS Makefiles"] : []
41
+ end
42
+
43
+ def default_flags
44
+ [
45
+ "-DENABLE_OPENSSL:BOOL=ON", "-DENABLE_LIBB2:BOOL=OFF", "-DENABLE_LZ4:BOOL=OFF",
46
+ "-DENABLE_LZO::BOOL=OFF", "-DENABLE_LZMA:BOOL=ON", "-DENABLE_ZSTD:BOOL=OFF",
47
+ "-DENABLE_ZLIB::BOOL=ON", "-DENABLE_BZip2:BOOL=OFF", "-DENABLE_LIBXML2:BOOL=OFF",
48
+ "-DENABLE_EXPAT::BOOL=ON", "-DENABLE_TAR:BOOL=OFF", "-DENABLE_CPIO::BOOL=OFF",
49
+ "-DENABLE_CAT:BOOL=OFF", "-DENABLE_ACL:BOOL=OFF", "-DENABLE_TEST:BOOL=OFF",
50
+ "-DENABLE_UNZIP:BOOL=OFF", "-DOPENSSL_USE_STATIC_LIBS=ON", "-DENABLE_XAR:BOOL=ON",
51
+
52
+ # Provide root directories - let CMake find libraries in lib or lib64
53
+ "-DOPENSSL_ROOT_DIR:PATH=#{@openssl_recipe.path}",
54
+
55
+ # Add include paths to C flags so CMake's header detection can find them
56
+ "-DCMAKE_C_FLAGS=-I#{@expat_recipe.path}/include -I#{@openssl_recipe.path}/include -I#{@xz_recipe.path}/include -I#{@zlib_recipe.path}/include",
57
+
58
+ # Provide search paths for CMake to find libraries
59
+ "-DCMAKE_INCLUDE_PATH:STRING=#{include_path}",
60
+ "-DCMAKE_LIBRARY_PATH:STRING=#{library_path}"
61
+ ]
62
+ end
63
+
64
+ def configure_defaults
65
+ df = generator_flags + default_flags
66
+
67
+ ar = ARCHS[host]
68
+ df += ["-DCMAKE_OSX_ARCHITECTURES=#{ar}"] if ar
69
+
70
+ df
71
+ end
72
+
73
+ def include_path
74
+ paths = [@zlib_recipe.path, @expat_recipe.path, @openssl_recipe.path, @xz_recipe.path]
75
+ paths.map { |k| "#{k}/include" }.join(";")
76
+ end
77
+
78
+ def library_path
79
+ paths = [@zlib_recipe.path, @expat_recipe.path, @openssl_recipe.path, @xz_recipe.path]
80
+ paths.map { |k| "#{k}/lib;#{k}/lib64" }.join(";")
81
+ end
82
+
83
+ def activate
84
+ @zlib_recipe.activate
85
+ @expat_recipe.activate
86
+ @openssl_recipe.activate
87
+ @xz_recipe.activate
88
+
89
+ super
90
+ end
91
+
92
+ def cook_if_not
93
+ cook unless File.exist?(checkpoint)
94
+ end
95
+
96
+ def cook
97
+ @zlib_recipe.host = @host if @host
98
+ @zlib_recipe.cook_if_not
99
+
100
+ @expat_recipe.host = @host if @host
101
+ @expat_recipe.cook_if_not
102
+
103
+ @openssl_recipe.host = @host if @host
104
+ @openssl_recipe.cook_if_not
105
+
106
+ @xz_recipe.host = @host if @host
107
+ @xz_recipe.cook_if_not
108
+
109
+ # Set explicit LZMA environment variables for libarchive configure
110
+ ENV['LIBLZMA_CFLAGS'] = "-I#{@xz_recipe.path}/include"
111
+ ENV['LIBLZMA_LIBS'] = "-L#{@xz_recipe.path}/lib -llzma"
112
+
113
+ super
114
+
115
+ FileUtils.touch(checkpoint)
116
+ end
117
+
118
+ def checkpoint
119
+ File.join(@target, "#{name}-#{version}-#{host}.installed")
120
+ end
121
+
122
+ def install
123
+ super
124
+
125
+ libs = Dir.glob(File.join(port_path, "{lib,bin}", "*"))
126
+ .grep(/\/(?:lib)?[a-zA-Z0-9\-]+\.(?:so|dylib|dll)$/)
127
+ FileUtils.cp_r(libs, lib_workpath, verbose: true)
128
+ if lib_fullpath.nil?
129
+ message("Cannot guess libarchive library name, skipping format verification")
130
+ else
131
+ verify_lib
132
+ end
133
+ end
134
+
135
+ def lib_workpath
136
+ @lib_workpath ||= ROOT.join("lib", "ffi-libarchive-binary")
137
+ end
138
+
139
+ def lib_fullpath
140
+ lib_filename = LIBNAMES[@host]
141
+ @lib_fullpath ||= lib_filename.nil? ? nil : File.join(lib_workpath, lib_filename)
142
+ end
143
+
144
+ def libraries
145
+ configuration_file = File.join(File.dirname(__FILE__), "..", "..", "ext", "configuration.yml")
146
+ @libraries ||= ::YAML.load_file(configuration_file)["libraries"] || {}
147
+ rescue Psych::SyntaxError => e
148
+ puts "Warning: The configuration file '#{configuration_file}' contains invalid YAML syntax."
149
+ puts e.message
150
+ exit 1
151
+ rescue StandardError => e
152
+ puts "An unexpected error occurred while loading the configuration file '#{configuration_file}'."
153
+ puts e.message
154
+ exit 1
155
+ end
156
+
157
+ def library_for(libname)
158
+ libraries[libname][MiniPortile::windows? ? "windows" : "all"]
159
+ rescue StandardError => e
160
+ puts "Failed to load library configuration for '#{libname}'."
161
+ puts e.message
162
+ exit 1
163
+ end
164
+
165
+ def verify_lib
166
+ begin
167
+ out, = Open3.capture2("file #{lib_fullpath}")
168
+ rescue StandardError
169
+ message("failed to call file, library verification skipped.\n")
170
+ return
171
+ end
172
+ unless out.include?(target_format)
173
+ raise "Invalid file format '#{out.strip}', '#{target_format}' expected"
174
+ end
175
+
176
+ message("#{lib_fullpath} format has been verified (#{target_format})\n")
177
+ end
178
+
179
+ def target_format
180
+ @target_format ||= FORMATS[@host].nil? ? "skip" : FORMATS[@host]
181
+ end
182
+
183
+ def message(text)
184
+ return super unless text.start_with?("\rDownloading")
185
+
186
+ match = text.match(/(\rDownloading .*)\((\s*)(\d+)%\)/)
187
+ pattern = match ? match[1] : text
188
+ return if @printed[pattern] && match[3].to_i != 100
189
+
190
+ @printed[pattern] = true
191
+ super
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_recipe"
4
+
5
+ module LibarchiveBinary
6
+ class LibexpatRecipe < BaseRecipe
7
+ def initialize
8
+ super("libexpat")
9
+
10
+ @target = ROOT.join(@target).to_s
11
+ end
12
+
13
+ def configure_defaults
14
+ [
15
+ "--host=#{@host}", "--disable-shared", "--enable-static",
16
+ "--without-tests", "--without-examples"
17
+ ]
18
+ end
19
+
20
+ def configure
21
+ # Set cross-compiler environment variables for aarch64
22
+ env_vars = cross_compiler_env(host)
23
+ cmd = ["env"] + env_vars.map { |k, v| "#{k}=#{v}" } +
24
+ [cflags(host), ldflags(host), "./configure"] + computed_options
25
+ execute("configure", cmd)
26
+ end
27
+
28
+ def checkpoint
29
+ File.join(@target, "#{name}-#{version}-#{host}.installed")
30
+ end
31
+
32
+ def cook_if_not
33
+ cook unless File.exist?(checkpoint)
34
+ end
35
+
36
+ def cook
37
+ super
38
+
39
+ FileUtils.touch(checkpoint)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_recipe"
4
+
5
+ module LibarchiveBinary
6
+ class Libxml2Recipe < BaseRecipe
7
+ def initialize
8
+ super("libxml2")
9
+
10
+ @target = ROOT.join(@target).to_s
11
+ end
12
+
13
+ def configure_defaults
14
+ [
15
+ "--host=#{@host}",
16
+ "--disable-dependency-tracking",
17
+ "--without-python",
18
+ "--without-lzma",
19
+ "--without-zlib",
20
+ "--without-iconv",
21
+ "--without-icu",
22
+ "--without-debug",
23
+ "--without-threads",
24
+ "--without-modules",
25
+ "--without-catalog",
26
+ "--without-docbook",
27
+ "--without-legacy",
28
+ "--without-http",
29
+ "--without-ftp",
30
+ "--enable-static",
31
+ "--disable-shared"
32
+ ]
33
+ end
34
+
35
+ def configure
36
+ cmd = ["env", cflags(host), ldflags(host),
37
+ "./configure"] + computed_options
38
+ execute("configure", cmd)
39
+ end
40
+
41
+ def checkpoint
42
+ File.join(@target, "#{name}-#{version}-#{host}.installed")
43
+ end
44
+
45
+ def cook_if_not
46
+ cook unless File.exist?(checkpoint)
47
+ end
48
+
49
+ def cook
50
+ super
51
+
52
+ FileUtils.touch(checkpoint)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_recipe"
4
+
5
+ module LibarchiveBinary
6
+ OS_COMPILERS = {
7
+ "arm64-apple-darwin" => "darwin64-arm64-cc",
8
+ "x86_64-apple-darwin" => "darwin64-x86_64-cc",
9
+ "aarch64-linux-gnu" => "linux-aarch64",
10
+ "aarch64-linux-musl" => "linux-aarch64",
11
+ "x86_64-linux-gnu" => nil,
12
+ "x86_64-linux-musl" => nil,
13
+ "x86_64-w64-mingw32" => "mingw64",
14
+ # Use mingw64 target for Windows ARM64 with clang and explicit CFLAGS
15
+ # This prevents OpenSSL from adding -m64 flag which would create x86_64 objects
16
+ "aarch64-w64-mingw32" => "mingw64",
17
+ }.freeze
18
+
19
+ ENV_CMD = ["env", "CFLAGS=-fPIC", "LDFLAGS=-fPIC"].freeze
20
+
21
+ class OpensslRecipe < BaseRecipe
22
+ def initialize
23
+ super("openssl")
24
+ end
25
+
26
+ def configure
27
+ os_compiler = OS_COMPILERS[@host]
28
+ common_opts = ["--openssldir=#{ROOT}/ports/SSL", "--libdir=lib", "no-tests", "no-shared", "no-docs"] +
29
+ computed_options.grep(/--prefix/)
30
+
31
+ # For Windows ARM64, set CFLAGS=-fPIC first to prevent OpenSSL from adding -m64
32
+ # The mingw64 target unconditionally adds -m64 which breaks ARM64 cross-compilation
33
+ common_opts.unshift("CFLAGS=-fPIC") if @host == "aarch64-w64-mingw32"
34
+
35
+ # Disable assembly for ARM64 as x86_64-specific instructions (AVX512, etc.) won't work
36
+ common_opts << "no-asm" if @host == "aarch64-w64-mingw32"
37
+
38
+ # Disable module loading for Windows ARM64 to avoid resource file compilation
39
+ # The resource compiler (llvm-rc) can't find Windows SDK headers like winver.h
40
+ common_opts << "no-module" if @host == "aarch64-w64-mingw32"
41
+
42
+ # Disable command-line apps for Windows ARM64 to avoid resource file compilation
43
+ # The apps/openssl.rc also requires Windows SDK headers which llvm-rc can't find
44
+ common_opts << "no-apps" if @host == "aarch64-w64-mingw32"
45
+
46
+ # Set cross-compiler environment variables for aarch64
47
+ env_vars = cross_compiler_env(@host)
48
+ env_prefix = env_vars.empty? ? ENV_CMD : ENV_CMD + env_vars.map { |k, v| "#{k}=#{v}" }
49
+
50
+ cmd = if os_compiler.nil?
51
+ message("OpensslRecipe: guessing with 'config' for '#{@host}'\n")
52
+ env_prefix + ["./config"] + common_opts
53
+ else
54
+ env_prefix + ["./Configure"] + common_opts + [os_compiler]
55
+ end
56
+ execute("configure", cmd)
57
+
58
+ # For Windows ARM64, fix the Makefile to use pe-arm64 instead of pe-x86-64 for windres
59
+ # OpenSSL's mingw64 target hardcodes --target=pe-x86-64 which creates x86_64 resource files
60
+ if @host == "aarch64-w64-mingw32"
61
+ makefile = File.join(work_path, "Makefile")
62
+ content = File.read(makefile)
63
+ content.gsub!("pe-x86-64", "pe-arm64")
64
+ File.write(makefile, content)
65
+ message("OpensslRecipe: fixed Makefile to use pe-arm64 for windres\n")
66
+ end
67
+ end
68
+
69
+ def checkpoint
70
+ File.join(@target, "#{name}-#{version}-#{host}.installed")
71
+ end
72
+
73
+ def cook_if_not
74
+ cook unless File.exist?(checkpoint)
75
+ end
76
+
77
+ def cook
78
+ super
79
+
80
+ FileUtils.touch(checkpoint)
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LibarchiveBinary
4
+ VERSION = "0.5.0"
5
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_recipe"
4
+
5
+ module LibarchiveBinary
6
+ class XZRecipe < BaseRecipe
7
+ def initialize
8
+ super("xz")
9
+ end
10
+
11
+ def configure_defaults
12
+ [
13
+ "--host=#{@host}",
14
+ "--disable-doc", "--disable-xz", "--with-pic",
15
+ "--disable-xzdec", "--disable-lzmadec", "--disable-lzmainfo",
16
+ "--disable-scripts", "--disable-shared", "--enable-static"
17
+ ]
18
+ end
19
+
20
+ def configure
21
+ # Set cross-compiler environment variables for aarch64
22
+ env_vars = cross_compiler_env(host)
23
+ cmd = ["env"] + env_vars.map { |k, v| "#{k}=#{v}" } +
24
+ [cflags(host), ldflags(host), "./configure"] + computed_options
25
+ execute("configure", cmd)
26
+ end
27
+
28
+ def checkpoint
29
+ File.join(@target, "#{name}-#{version}-#{host}.installed")
30
+ end
31
+
32
+ def cook_if_not
33
+ cook unless File.exist?(checkpoint)
34
+ end
35
+
36
+ def cook
37
+ super
38
+
39
+ FileUtils.touch(checkpoint)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+ require_relative "base_recipe"
5
+
6
+ module LibarchiveBinary
7
+ class ZLibRecipe < BaseRecipe
8
+ def initialize
9
+ super("zlib")
10
+ end
11
+
12
+ def configure_defaults
13
+ [
14
+ "--static",
15
+ ]
16
+ end
17
+
18
+ def configure_windows
19
+ mk = File.read("win32/Makefile.gcc")
20
+ File.open("win32/Makefile.gcc", "wb") do |f|
21
+ f.puts "BINARY_PATH = #{path}/bin"
22
+ f.puts "LIBRARY_PATH = #{path}/lib"
23
+ f.puts "INCLUDE_PATH = #{path}/include"
24
+ f.puts "SHARED_MODE = 0"
25
+ f.puts "LOC = -fPIC"
26
+ f.puts mk
27
+ end
28
+ end
29
+
30
+ def configure
31
+ if MiniPortile::windows?
32
+ Dir.chdir(work_path) do
33
+ configure_windows
34
+ end
35
+ else
36
+ # Set cross-compiler environment variables for aarch64
37
+ env_vars = cross_compiler_env(host)
38
+ cmd = ["env"] + env_vars.map { |k, v| "#{k}=#{v}" } +
39
+ [cflags(host), ldflags(host), "./configure"] + computed_options
40
+ execute("configure", cmd)
41
+ end
42
+ end
43
+
44
+ def configured?
45
+ if MiniPortile::windows?
46
+ Dir.chdir(work_path) do
47
+ !!(File.read("win32/Makefile.gcc") =~ /^BINARY_PATH/)
48
+ end
49
+ else
50
+ super
51
+ end
52
+ end
53
+
54
+ def compile
55
+ if MiniPortile::windows?
56
+ execute("compile", "make -f win32/Makefile.gcc libz.a")
57
+ else
58
+ super
59
+ end
60
+ end
61
+
62
+ def install
63
+ if MiniPortile::windows?
64
+ execute("install", "make -f win32/Makefile.gcc install")
65
+ else
66
+ super
67
+ end
68
+ end
69
+
70
+ def checkpoint
71
+ File.join(@target, "#{name}-#{version}-#{host}.installed")
72
+ end
73
+
74
+ def cook_if_not
75
+ cook unless File.exist?(checkpoint)
76
+ end
77
+
78
+ def cook
79
+ super
80
+
81
+ FileUtils.touch(checkpoint)
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ffi-libarchive-binary/version"
4
+ require "pathname"
5
+
6
+ module LibarchiveBinary
7
+ class Error < StandardError; end
8
+
9
+ LIBRARY_PATH = Pathname.new(File.join(__dir__, "ffi-libarchive-binary"))
10
+
11
+ def self.lib_path
12
+ LIBRARY_PATH.join(lib_filename).to_s
13
+ end
14
+
15
+ def self.lib_filename
16
+ if FFI::Platform.windows?
17
+ "libarchive.dll"
18
+ elsif FFI::Platform.mac?
19
+ "libarchive.dylib"
20
+ else
21
+ "libarchive.so"
22
+ end
23
+ end
24
+ end
25
+
26
+ module Archive
27
+ module C
28
+ def self.ffi_lib(*args)
29
+ prefixed = args.map do |names|
30
+ paths = names.is_a?(Array) ? names : [names]
31
+ if paths.any? { |f| f.include?("libarchive") }
32
+ [LibarchiveBinary.lib_path] + paths
33
+ else
34
+ names
35
+ end
36
+ end
37
+
38
+ super(*prefixed)
39
+ end
40
+ end
41
+ end
42
+
43
+ require "ffi-libarchive"
@@ -0,0 +1,12 @@
1
+ set(CMAKE_SYSTEM_NAME Linux)
2
+ set(CMAKE_SYSTEM_PROCESSOR aarch64)
3
+
4
+ # Specify the cross compiler
5
+ set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
6
+ set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)
7
+
8
+ # Where to look for the target environment
9
+ set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
10
+ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
11
+ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
12
+ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)