Skip to content

Commit dcf9c86

Browse files
committed
chore(build): Add configurations and scripts for compiling, testing, and packaging
1 parent db0d855 commit dcf9c86

File tree

6 files changed

+182
-114
lines changed

6 files changed

+182
-114
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ Gemfile.lock
1010
.vscode
1111

1212
doc/
13+
deps/
1314
gems/
1415
issues/
1516
pkg/
1617
ports/
1718
tmp/
18-
tmp_chdb/
1919
vendor/
2020
test/
2121
testdb/

Gemfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ group :test do
88
gem 'rake-compiler', '1.2.9'
99
gem 'rake-compiler-dock', '1.9.1'
1010
gem 'rspec', '3.12.0'
11-
gem 'ruby_memcheck', '3.0.1' if Gem::Platform.local.os == 'linux'
1211
end
1312

1413
group :development do

ext/chdb/extconf.rb

Lines changed: 129 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,138 @@
11
# frozen_string_literal: true
22

3+
require 'fileutils'
34
require 'mkmf'
5+
require 'yaml'
46

5-
system_found = have_library('chdb') && have_header('chdb.h')
7+
module ChDB
8+
module ExtConf
9+
class << self
10+
def configure
11+
configure_cross_compiler
612

7-
unless system_found
8-
abort "chdb.h or chdb library not found! Please install chdb development files.\n" \
9-
"You can try installing with: gem install chdb -- --with-opt-dir=/usr/local/lib \n" \
10-
'Or any other path that contains chdb.h and libchdb.so'
11-
end
13+
download_and_extract
14+
15+
configure_extension
16+
17+
create_makefile('chdb/chdb_native')
18+
end
19+
20+
def configure_cross_compiler
21+
RbConfig::CONFIG['CC'] = RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
22+
ENV['CC'] = RbConfig::CONFIG['CC']
23+
end
24+
25+
def libname
26+
'chdb'
27+
end
28+
29+
def configure_extension
30+
include_path = File.expand_path('ext/chdb/include', package_root_dir)
31+
append_cppflags("-I#{include_path}")
32+
33+
lib_path = File.expand_path('ext/chdb/lib', package_root_dir)
34+
append_ldflags("-L#{lib_path}")
35+
36+
append_ldflags("-Wl,-rpath,'$$ORIGIN/../lib'")
37+
38+
abort_could_not_find('chdb.h') unless find_header('chdb.h', include_path)
39+
40+
return if find_library(libname, nil, lib_path)
41+
42+
abort_could_not_find(libname)
43+
end
44+
45+
def abort_could_not_find(missing)
46+
message = <<~MSG
47+
Could not find #{missing}.
48+
Please visit https://github.com/chdb-io/chdb-ruby for installation instructions.
49+
MSG
50+
abort("\n#{message}\n")
51+
end
52+
53+
def download_and_extract
54+
target_platform = determine_target_platform
55+
version = fetch_chdb_version
56+
download_dir = setup_download_directory(target_platform, version)
1257

13-
$srcs = Dir['*.c'] + ['chdb.c'] # rubocop:disable Style/GlobalVars
58+
unless Dir.exist?(download_dir)
59+
file_name = get_file_name(target_platform)
60+
url = build_download_url(version, file_name)
61+
download_tarball(url, download_dir, file_name)
62+
extract_tarball(download_dir, file_name)
63+
end
64+
65+
copy_files(download_dir, version)
66+
end
67+
68+
private
69+
70+
def determine_target_platform
71+
ENV['TARGET'] || host_platform
72+
end
73+
74+
def fetch_chdb_version
75+
dependencies = YAML.load_file(File.join(package_root_dir, 'dependencies.yml'), symbolize_names: true)
76+
dependencies[:chdb][:version]
77+
end
78+
79+
def setup_download_directory(target_platform, version)
80+
download_dir = File.join(package_root_dir, 'deps', version, target_platform)
81+
FileUtils.mkdir_p(download_dir)
82+
download_dir
83+
end
84+
85+
def get_file_name(target_platform)
86+
case target_platform
87+
when 'aarch64-linux-gnu' then 'linux-aarch64-libchdb.tar.gz'
88+
when 'x86_64-linux-gnu' then 'linux-x86_64-libchdb.tar.gz'
89+
when 'arm64-darwin' then 'macos-arm64-libchdb.tar.gz'
90+
when 'x86_64-darwin' then 'macos-x86_64-libchdb.tar.gz'
91+
else raise "Unsupported platform: #{target_platform}"
92+
end
93+
end
94+
95+
def build_download_url(version, file_name)
96+
"https://github.com/chdb-io/chdb/releases/download/v#{version}/#{file_name}"
97+
end
98+
99+
def download_tarball(url, download_dir, file_name)
100+
tarball = File.join(download_dir, file_name)
101+
puts "Downloading chdb library for #{determine_target_platform}..."
102+
URI.open(url) do |remote| # rubocop:disable Security/Open
103+
IO.copy_stream(remote, tarball)
104+
end
105+
end
106+
107+
def extract_tarball(download_dir, file_name)
108+
tarball = File.join(download_dir, file_name)
109+
system("tar xzf #{tarball} -C #{download_dir}")
110+
end
111+
112+
def copy_files(download_dir, _version)
113+
ext_chdb_path = File.join(package_root_dir, 'ext/chdb')
114+
[%w[include *.h], %w[lib *.so], %w[lib *.dylib]].each do |(src_dir, pattern)|
115+
src = File.join(download_dir, src_dir, pattern)
116+
dest = File.join(ext_chdb_path, src_dir)
117+
FileUtils.mkdir_p(dest)
118+
FileUtils.cp_r(Dir.glob(src), dest, remove_destination: true)
119+
end
120+
end
121+
122+
def host_platform
123+
RbConfig::CONFIG['host_os'].downcase
124+
end
125+
126+
def package_root_dir
127+
File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
128+
end
129+
end
130+
end
131+
end
14132

15-
if RbConfig::CONFIG['GCC'] == 'yes'
16-
$CFLAGS << ' -Wno-declaration-after-statement' # rubocop:disable Style/GlobalVars
17-
$CFLAGS = $CFLAGS.gsub(/-Wno-self-assign|-Wno-parentheses-equality|-Wno-constant-logical-operand/, '') # rubocop:disable Style/GlobalVars
133+
if arg_config('--download-dependencies')
134+
ChDB::ExtConf.download_and_extract
135+
exit!(0)
18136
end
19137

20-
create_makefile('chdb/chdb')
138+
ChDB::ExtConf.configure

lib/chdb.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
begin
44
RUBY_VERSION =~ /(\d+\.\d+)/
5-
require "ChDB/#{Regexp.last_match(1)}/chdb"
5+
require "chdb/#{Regexp.last_match(1)}/chdb_native"
66
rescue LoadError
7-
require 'ChDB/chdb'
7+
require 'chdb/chdb_native'
88
end
99

1010
require 'chdb/database'

rakelib/native.rake

Lines changed: 39 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,30 @@
11
# frozen_string_literal: true
22

3-
require "bundler/gem_tasks"
4-
require "rubygems/package_task"
5-
require "rake/extensiontask"
6-
require "rake_compiler_dock"
7-
require "yaml"
8-
9-
cross_platforms = [
10-
"aarch64-linux-gnu",
11-
"x86_64-linux-gnu",
12-
"arm64-darwin",
13-
"x86_64-darwin"
3+
require 'bundler/gem_tasks'
4+
require 'rubygems/package_task'
5+
require 'rake/extensiontask'
6+
require 'rake_compiler_dock'
7+
require 'yaml'
8+
9+
cross_platforms = %w[
10+
aarch64-linux-gnu
11+
x86_64-linux-gnu
12+
arm64-darwin
13+
x86_64-darwin
1414
]
1515

16-
RakeCompilerDock.set_ruby_cc_version("~> 3.1")
16+
RakeCompilerDock.set_ruby_cc_version('~> 3.1')
1717

1818
# Gem::PackageTask.new(CHDB_SPEC).define # packaged_tarball version of the gem for platform=ruby
19-
task "package" => cross_platforms.map { |p| "gem:#{p}" } # "package" task for all the native platforms
20-
21-
module CHDBDependency
22-
class << self
23-
def setup
24-
dependencies = YAML.load_file(File.join(__dir__, "..", "dependencies.yml"), symbolize_names: true)
25-
chdb_info = dependencies[:chdb]
26-
version = chdb_info[:version]
27-
28-
cross_platforms.each do |platform|
29-
platform_key = platform.gsub(/-/, '_').to_sym
30-
next unless chdb_info[:platforms][platform_key]
31-
32-
download_and_extract(platform, version)
33-
end
34-
end
35-
36-
private
37-
38-
def download_and_extract(platform, version)
39-
file_name = case platform
40-
when 'aarch64-linux-gnu' then 'linux-aarch64-libchdb.tar.gz'
41-
when 'x86_64-linux-gnu' then 'linux-x86_64-libchdb.tar.gz'
42-
when 'arm64-darwin' then 'macos-arm64-libchdb.tar.gz'
43-
when 'x86_64-darwin' then 'macos-x86_64-libchdb.tar.gz'
44-
end
45-
46-
url = "https://github.com/chdb-io/chdb/releases/download/v#{version}/#{file_name}"
47-
48-
archive_dir = File.join("ports", "archives")
49-
FileUtils.mkdir_p(archive_dir)
50-
51-
tarball = File.join(archive_dir, name)
52-
unless File.exist?(tarball)
53-
puts "Downloading #{name}..."
54-
URI.open(url) do |remote|
55-
IO.copy_stream(remote, tarball)
56-
end
57-
end
58-
59-
tmp_dir = File.join(archive_dir, "tmp_chdb")
60-
FileUtils.rm_rf(tmp_dir)
61-
FileUtils.mkdir_p(tmp_dir)
62-
63-
system("tar xzf #{tarball} -C #{tmp_dir}")
64-
65-
ext_chdb_path = File.expand_path("ext/chdb", __dir__)
66-
[%w[include *.h], %w[lib *.so], %w[lib *.dylib]].each do |(src_dir, pattern)|
67-
src = File.join(tmp_dir, src_dir, pattern)
68-
dest = File.join(ext_chdb_path, src_dir)
69-
FileUtils.mkdir_p(dest)
70-
FileUtils.cp_r(Dir.glob(src), dest, remove_destination: true)
71-
end
72-
73-
# 清理临时目录
74-
FileUtils.rm_rf(tmp_dir)
75-
end
76-
end
77-
end
19+
# 'package' task for all the native platforms
20+
task 'package' => cross_platforms.map { |p| "gem:#{p}" }
7821

7922
def gem_build_path
80-
File.join("pkg", CHDB_SPEC.full_name)
23+
File.join('pkg', CHDB_SPEC.full_name)
8124
end
8225

8326
def add_file_to_gem(relative_source_path)
84-
if relative_source_path.nil? || !File.exist?(relative_source_path)
85-
raise "Cannot find file '#{relative_source_path}'"
86-
end
27+
raise "Cannot find file '#{relative_source_path}'" if relative_source_path.nil? || !File.exist?(relative_source_path)
8728

8829
dest_path = File.join(gem_build_path, relative_source_path)
8930
dest_dir = File.dirname(dest_path)
@@ -96,72 +37,71 @@ def add_file_to_gem(relative_source_path)
9637
end
9738

9839
task gem_build_path do
99-
dependencies = YAML.load_file(File.join(__dir__, "..", "dependencies.yml"), symbolize_names: true)
40+
dependencies = YAML.load_file(File.join(__dir__, '..', 'dependencies.yml'), symbolize_names: true)
10041
sqlite_tarball = File.basename(dependencies[:sqlite3][:files].first[:url])
101-
archive = Dir.glob(File.join("ports", "archives", sqlite_tarball)).first
42+
archive = Dir.glob(File.join('ports', 'archives', sqlite_tarball)).first
10243
add_file_to_gem(archive)
10344
end
10445

105-
Rake::ExtensionTask.new("chdb_native", CHDB_SPEC) do |ext|
106-
ext.ext_dir = "ext/chdb"
107-
ext.lib_dir = "lib/chdb"
46+
Rake::ExtensionTask.new('chdb_native', CHDB_SPEC) do |ext|
47+
ext.ext_dir = 'ext/chdb'
48+
ext.lib_dir = 'lib/chdb'
10849
ext.cross_compile = true
10950
ext.cross_platform = cross_platforms
110-
ext.cross_config_options << "--enable-cross-build" # so extconf.rb knows we're cross-compiling
111-
112-
ext.prerequisites << :download_chdb_deps
51+
# so extconf.rb knows we're cross-compiling
52+
ext.cross_config_options << '--enable-cross-build'
11353
end
11454

115-
namespace "gem" do
55+
namespace 'gem' do
11656
cross_platforms.each do |platform|
11757
desc "build native gem for #{platform}"
11858
task platform do
119-
RakeCompilerDock.sh(<<~EOF, platform: platform, verbose: true)
59+
RakeCompilerDock.sh(<<~COMMAND_END, platform: platform, verbose: true)
12060
gem install bundler --no-document &&
12161
bundle &&
12262
bundle exec rake gem:#{platform}:buildit
123-
EOF
63+
COMMAND_END
12464
end
12565

12666
namespace platform do
12767
# this runs in the rake-compiler-dock docker container
128-
task "buildit" do
68+
task 'buildit' do
12969
# use Task#invoke because the pkg/*gem task is defined at runtime
13070
Rake::Task["native:#{platform}"].invoke
13171
Rake::Task["pkg/#{CHDB_SPEC.full_name}-#{Gem::Platform.new(platform)}.gem"].invoke
13272
end
13373
end
13474
end
13575

136-
desc "build native gem for all platforms"
137-
task "all" => [cross_platforms, "gem"].flatten
76+
desc 'build native gem for all platforms'
77+
task 'all' => [cross_platforms, 'gem'].flatten
13878
end
13979

140-
desc "Temporarily set VERSION to a unique timestamp"
141-
task "set-version-to-timestamp" do
80+
desc 'Temporarily set VERSION to a unique timestamp'
81+
task 'set-version-to-timestamp' do
14282
# this task is used by bin/test-gem-build
14383
# to test building, packaging, and installing a precompiled gem
14484
version_constant_re = /^\s*VERSION\s*=\s*["'](.*)["']$/
14585

146-
version_file_path = File.join(__dir__, "../lib/chdb/version.rb")
86+
version_file_path = File.join(__dir__, '../lib/chdb/version.rb')
14787
version_file_contents = File.read(version_file_path)
14888

14989
current_version_string = version_constant_re.match(version_file_contents)[1]
15090
current_version = Gem::Version.new(current_version_string)
15191

152-
fake_version = Gem::Version.new(format("%s.test.%s", current_version.bump, Time.now.strftime("%Y.%m%d.%H%M")))
92+
bumped_version = current_version.bump
93+
timestamp = Time.now.strftime('%Y.%m%d.%H%M')
94+
fake_version = Gem::Version.new(format('%<bumped_version>s.test.%<timestamp>s',
95+
bumped_version: bumped_version,
96+
timestamp: timestamp))
15397

15498
unless version_file_contents.gsub!(version_constant_re, " VERSION = \"#{fake_version}\"")
155-
raise("Could not hack the VERSION constant")
99+
raise('Could not hack the VERSION constant')
156100
end
157101

158102
File.write(version_file_path, version_file_contents)
159103

160104
puts "NOTE: wrote version as \"#{fake_version}\""
161105
end
162106

163-
CLEAN.add("{ext,lib}/**/*.{o,so}", "pkg", "ext/chdb/{include,lib}")
164-
165-
task :download_chdb_deps do
166-
CHDBDependency.setup
167-
end
107+
CLEAN.add('{ext,lib}/**/*.{o,so}', 'pkg', 'ext/chdb/{include,lib}')

rakelib/test.rake

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# frozen_string_literal: true
2+
3+
require 'rspec/core/rake_task'
4+
5+
CHDB_SPEC = Bundler.load_gemspec('chdb.gemspec')
6+
7+
RSpec::Core::RakeTask.new(:spec) do |t|
8+
t.pattern = 'spec/**/*_spec.rb'
9+
end
10+
11+
task test: :spec

0 commit comments

Comments
 (0)