diff --git a/.gitignore b/.gitignore index e97ca2fe..65492a94 100644 --- a/.gitignore +++ b/.gitignore @@ -12,5 +12,6 @@ *.so *.o *.a +*.gem mkmf.log vendor/bundle diff --git a/.gitmodules b/.gitmodules index 1d1b46ab..e762dbbd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "ext/libsass"] path = ext/libsass - url = git://github.com/sass/libsass.git + url = https://github.com/sass/libsass.git diff --git a/README.md b/README.md index 31083f6b..5830be1e 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This gem combines the speed of `libsass`, the [Sass C implementation](https://gi ### libsass Version -[3.5.2](https://github.com/sass/libsass/releases/tag/3.5.2) +[d225a09a](https://github.com/sass/libsass/commit/d225a09a152050d569c077f97bb944c8dc819d6f) ## Installation diff --git a/Rakefile b/Rakefile index 13e97e8a..f682dc4e 100644 --- a/Rakefile +++ b/Rakefile @@ -1,15 +1,30 @@ -begin - require 'bundler/gem_tasks' -rescue LoadError - puts 'Cannot load bundler/gem_tasks' -end - -require 'tasks/libsass' +require 'bundler/gem_tasks' task default: :test +require 'rake/extensiontask' +gem_spec = Gem::Specification.load("sassc.gemspec") +Rake::ExtensionTask.new('libsass', gem_spec) do |ext| + ext.name = 'libsass' + ext.ext_dir = 'ext' + ext.lib_dir = 'lib/sassc' + ext.cross_compile = true + ext.cross_platform = %w[x86-mingw32 x64-mingw32 x86-linux x86_64-linux] + ext.cross_compiling do |spec| + spec.files.reject! { |path| File.fnmatch?('ext/*', path) } + end +end + +desc 'Compile all native gems via rake-compiler-dock (Docker)' +task 'gem:native' do + require 'rake_compiler_dock' + RakeCompilerDock.sh "bundle && gem i rake --no-document && "\ + "rake cross native gem MAKE='nice make -j`nproc`' "\ + "RUBY_CC_VERSION=2.6.0:2.5.0:2.4.0:2.3.0" +end + desc "Run all tests" -task test: 'libsass:compile' do +task test: 'compile:libsass' do $LOAD_PATH.unshift('lib', 'test') Dir.glob('./test/**/*_test.rb') { |f| require f } end diff --git a/ext/Rakefile b/ext/Rakefile deleted file mode 100644 index a8ed3958..00000000 --- a/ext/Rakefile +++ /dev/null @@ -1,3 +0,0 @@ -require_relative '../lib/tasks/libsass' - -task default: 'libsass:compile' diff --git a/ext/extconf.rb b/ext/extconf.rb new file mode 100644 index 00000000..adbb065c --- /dev/null +++ b/ext/extconf.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +gem_root = File.expand_path('..', __dir__) +libsass_dir = File.join(gem_root, 'ext', 'libsass') + +if !File.directory?(libsass_dir) || + # '.', '..', and possibly '.git' from a failed checkout: + Dir.entries(libsass_dir).size <= 3 + Dir.chdir(gem_root) { system('git submodule update --init') } or + fail 'Could not fetch libsass' +end + +File.write 'Makefile', <<-MAKEFILE +ifndef DESTDIR + LIBSASS_OUT = #{gem_root}/lib/sassc/libsass.so +else + LIBSASS_OUT = $(DESTDIR)$(PREFIX)/libsass.so +endif + +SUB_DIR := #{libsass_dir} +SUB_TARGET := lib/libsass.so + +libsass.so:#{' clean' if ENV['CLEAN']} + $(MAKE) -C '$(SUB_DIR)' lib/libsass.so + cp '$(SUB_DIR)/lib/libsass.so' libsass.so + strip libsass.so + +install: libsass.so + cp libsass.so '$(LIBSASS_OUT)' + +clean: + $(MAKE) -C '$(SUB_DIR)' clean + rm -f '$(LIBSASS_OUT)' libsass.so + +.PHONY: clean install +MAKEFILE diff --git a/ext/libsass b/ext/libsass index 9cfe0df9..8d220b74 160000 --- a/ext/libsass +++ b/ext/libsass @@ -1 +1 @@ -Subproject commit 9cfe0df975945325e05d6dd39ee98224898d9a79 +Subproject commit 8d220b74770ad16aaf7819b5e18d85746aa63d7d diff --git a/lib/sassc/engine.rb b/lib/sassc/engine.rb index 150ce022..935b547d 100644 --- a/lib/sassc/engine.rb +++ b/lib/sassc/engine.rb @@ -133,7 +133,7 @@ def output_style def load_paths paths = (@options[:load_paths] || []) + SassC.load_paths - paths.join(":") if paths.any? + paths.join(File::PATH_SEPARATOR) unless paths.empty? end end end diff --git a/lib/sassc/native.rb b/lib/sassc/native.rb index 443dcbe1..b9ed8f1c 100644 --- a/lib/sassc/native.rb +++ b/lib/sassc/native.rb @@ -8,7 +8,13 @@ module Native spec = Gem.loaded_specs["sassc"] gem_root = spec.gem_dir - ffi_lib "#{gem_root}/ext/libsass/lib/libsass.so" + + ruby_version_so_path = "#{gem_root}/lib/sassc/#{RUBY_VERSION[/\d+.\d+/]}/libsass.so" + if File.exist?(ruby_version_so_path) + ffi_lib ruby_version_so_path + else + ffi_lib "#{gem_root}/lib/sassc/libsass.so" + end require_relative "native/sass_value" diff --git a/lib/tasks/libsass.rb b/lib/tasks/libsass.rb deleted file mode 100644 index 57ed47bd..00000000 --- a/lib/tasks/libsass.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -namespace :libsass do - desc "Compile libsass" - task :compile do - if Dir.pwd.end_with?('/ext') - libsass_path = "libsass" - else - libsass_path = "ext/libsass" - end - - cd libsass_path do - Rake::Task["lib/libsass.so"].invoke - end - end - - file "Makefile" do - sh "git submodule update --init" - end - - file "lib/libsass.so" => "Makefile" do - make_program = ENV['MAKE'] - make_program ||= case RUBY_PLATFORM - when /mswin/ - 'nmake' - when /(bsd|solaris)/ - 'gmake' - else - 'make' - end - sh "#{make_program} lib/libsass.so" - end -end diff --git a/sassc.gemspec b/sassc.gemspec index b92366f1..f2ea18b3 100644 --- a/sassc.gemspec +++ b/sassc.gemspec @@ -23,26 +23,34 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] - spec.extensions = ["ext/Rakefile"] + spec.platform = Gem::Platform::RUBY + spec.extensions = ["ext/extconf.rb"] spec.add_development_dependency "minitest", "~> 5.5.1" spec.add_development_dependency "minitest-around" spec.add_development_dependency "test_construct" spec.add_development_dependency "pry" spec.add_development_dependency "bundler" + spec.add_development_dependency "rake" + spec.add_development_dependency "rake-compiler" + spec.add_development_dependency "rake-compiler-dock" - spec.add_dependency "rake" spec.add_dependency "ffi", "~> 1.9" gem_dir = File.expand_path(File.dirname(__FILE__)) + "/" - `git submodule --quiet foreach pwd`.split($\).each do |submodule_path| - Dir.chdir(submodule_path) do - submodule_relative_path = submodule_path.sub gem_dir, "" - # issue git ls-files in submodule's directory and - # prepend the submodule path to create absolute file paths - `git ls-files`.split($\).each do |filename| - spec.files << "#{submodule_relative_path}/#{filename}" - end + + libsass_dir = File.join(gem_dir, 'ext', 'libsass') + if !File.directory?(libsass_dir) + $stderr.puts "Error: ext/libsass not checked out. Please run:\n\n"\ + " git submodule update --init" + exit 1 + end + + Dir.chdir(libsass_dir) do + submodule_relative_path = File.join('ext', 'libsass') + `git ls-files`.split($\).each do |filename| + next if filename =~ %r{(^("?test|docs|script)/)|\.md$|\.yml$} + spec.files << File.join(submodule_relative_path, filename) end end diff --git a/test/engine_test.rb b/test/engine_test.rb index 6169e5cf..a273efee 100644 --- a/test/engine_test.rb +++ b/test/engine_test.rb @@ -88,7 +88,7 @@ def test_precision_not_specified SCSS expected_output = <<-CSS .foo { - baz: 0.33333; } + baz: 0.3333333333; } CSS output = Engine.new(template).render assert_equal expected_output, output @@ -218,7 +218,7 @@ def test_global_load_paths def test_env_load_paths expected_load_paths = [ "included_1", "included_2" ] ::SassC.instance_eval { @load_paths = nil } - ENV['SASS_PATH'] = expected_load_paths.join(':') + ENV['SASS_PATH'] = expected_load_paths.join(File::PATH_SEPARATOR) assert_equal expected_load_paths, ::SassC.load_paths ::SassC.load_paths.clear end diff --git a/test/native_test.rb b/test/native_test.rb index 639e0e7c..8937ea03 100644 --- a/test/native_test.rb +++ b/test/native_test.rb @@ -11,7 +11,7 @@ module NativeTest class General < MiniTest::Test def test_it_reports_the_libsass_version - assert_equal "3.5.2", Native.version + assert_equal "3.6.0", Native.version end end