Class: Emf2svg::Recipe

Inherits:
MiniPortileCMake
  • Object
show all
Defined in:
lib/emf2svg/recipe.rb

Constant Summary collapse

VCPKG_REF =

Pinned vcpkg commit. Matches the SHA claricle/libemf2svg CI uses; bump deliberately to refresh the ports tree.

"4f95fba7a7d1101bb8acdeb51e4609686449701e".freeze
VCPKG_URL =
"https://github.com/microsoft/vcpkg.git".freeze
ROOT =
Pathname.new(File.expand_path("../..", __dir__))

Instance Method Summary collapse

Constructor Details

#initializeRecipe

Returns a new instance of Recipe.



16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/emf2svg/recipe.rb', line 16

def initialize
  super("libemf2svg", LIBEMF2SVG_VERSION)

  @files << {
    # rubocop:disable Layout/LineLength
    url: "https://github.com/claricle/libemf2svg/releases/download/v#{LIBEMF2SVG_VERSION}/libemf2svg.tar.gz",
    sha256: "3782453987b477f2d8657c727e30f1e7a509188edfe6de2f7423443635aefd6d",
    # rubocop:enable Layout/LineLength
  }

  @target = ROOT.join(@target).to_s
  @printed = {}
end

Instance Method Details

#bootstrap_cmdObject



82
83
84
85
86
87
88
# File 'lib/emf2svg/recipe.rb', line 82

def bootstrap_cmd
  if MiniPortile.windows?
    "bootstrap-vcpkg.bat -disableMetrics"
  else
    "./bootstrap-vcpkg.sh -disableMetrics"
  end
end

#bootstrap_vcpkgObject



65
66
67
68
69
70
71
72
73
74
75
# File 'lib/emf2svg/recipe.rb', line 65

def bootstrap_vcpkg
  vcpkg_root = File.join(work_path, "vcpkg")
  return if vcpkg_bootstrapped?(vcpkg_root)

  message("Bootstrapping vcpkg@#{VCPKG_REF} into #{vcpkg_root}\n")
  FileUtils.rm_rf(vcpkg_root)
  execute("clone-vcpkg", "git clone --quiet #{VCPKG_URL} #{vcpkg_root}")
  execute("checkout-vcpkg",
          "git checkout --quiet #{VCPKG_REF}", cd: vcpkg_root)
  execute("bootstrap-vcpkg", bootstrap_cmd, cd: vcpkg_root)
end

#checkpointObject



98
99
100
# File 'lib/emf2svg/recipe.rb', line 98

def checkpoint
  File.join(@target, "#{name}-#{version}-#{target_platform}.installed")
end

#compileObject



117
118
119
# File 'lib/emf2svg/recipe.rb', line 117

def compile
  execute("compile", "#{make_cmd} --target emf2svg")
end

#configureObject

Since libemf2svg v1.8.2 the source tarball no longer bundles the vcpkg tool (it moved too fast to ship as a snapshot). We bootstrap vcpkg into the work path before CMake configure runs.



42
43
44
45
46
# File 'lib/emf2svg/recipe.rb', line 42

def configure
  bootstrap_vcpkg
  export_toolchain_to_env
  super
end

#configure_defaultsObject



102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/emf2svg/recipe.rb', line 102

def configure_defaults
  opts = []

  opts << "-DCMAKE_BUILD_TYPE=Release"
  opts << "-DLONLY=ON"

  unless target_triplet.nil? || drop_target_triplet?
    opts << "-DVCPKG_TARGET_TRIPLET=#{target_triplet}"
  end

  opts << "-DCMAKE_TOOLCHAIN_FILE=vcpkg/scripts/buildsystems/vcpkg.cmake"

  opts
end

#cookObject



34
35
36
37
# File 'lib/emf2svg/recipe.rb', line 34

def cook
  super
  FileUtils.touch(checkpoint)
end

#cook_if_notObject



30
31
32
# File 'lib/emf2svg/recipe.rb', line 30

def cook_if_not
  cook unless File.exist?(checkpoint)
end

#drop_target_triplet?Boolean

Returns:

  • (Boolean)


94
95
96
# File 'lib/emf2svg/recipe.rb', line 94

def drop_target_triplet?
  windows_native? || host_platform.eql?(target_platform)
end

#execute(action, command, command_opts = {}) ⇒ Object



160
161
162
# File 'lib/emf2svg/recipe.rb', line 160

def execute(action, command, command_opts = {})
  super(action, command, command_opts.merge(debug: false))
end

#export_toolchain_to_envObject

Downstream consumers (e.g. metanorma) sometimes patch RbConfig at runtime to point Ruby's toolchain at a known-good compiler, but those overrides live in the Ruby process and don't reach the raw cmake subprocess that mini_portile2 spawns. The result is "CMAKE_C_COMPILER not set" when the deploy environment has a stripped PATH. Mirror the resolved RbConfig toolchain into ENV so the subprocess sees the same compiler the running Ruby was built with.



56
57
58
59
60
61
62
63
# File 'lib/emf2svg/recipe.rb', line 56

def export_toolchain_to_env
  %w[CC CXX LDFLAGS].each do |var|
    val = RbConfig::CONFIG[var]
    next if val.nil? || val.empty?

    ENV[var] = val
  end
end

#installObject



148
149
150
151
152
153
154
155
156
157
158
# File 'lib/emf2svg/recipe.rb', line 148

def install
  libs = if MiniPortile.windows?
           Dir.glob(File.join(work_path, "Release", "*.dll"))
         else
           Dir.glob(File.join(work_path, "libemf2svg.{so,dylib}"))
             .grep(/\/(?:lib)?[a-zA-Z0-9-]+\.(?:so|dylib)$/)
         end
  FileUtils.cp_r(libs, ROOT.join("lib", "emf2svg"), verbose: true)

  verify_libs unless target_format.eql?("skip")
end

#lb_to_verifyObject



125
126
127
128
129
130
131
132
# File 'lib/emf2svg/recipe.rb', line 125

def lb_to_verify
  pt = if MiniPortile.windows?
         "emf2svg.dll"
       else
         "libemf2svg.{so,dylib}"
       end
  @lb_to_verify ||= Dir.glob(ROOT.join("lib", "emf2svg", pt))
end

#make_cmdObject



121
122
123
# File 'lib/emf2svg/recipe.rb', line 121

def make_cmd
  "cmake --build #{File.expand_path(work_path)} --config Release"
end

#message(text) ⇒ Object



164
165
166
167
168
169
170
171
172
173
# File 'lib/emf2svg/recipe.rb', line 164

def message(text)
  return super unless text.start_with?("\rDownloading")

  match = text.match(/(\rDownloading .*)\(\s*\d+%\)/)
  pattern = match ? match[1] : text
  return if @printed[pattern]

  @printed[pattern] = true
  super
end

#vcpkg_bootstrapped?(vcpkg_root) ⇒ Boolean

Returns:

  • (Boolean)


77
78
79
80
# File 'lib/emf2svg/recipe.rb', line 77

def vcpkg_bootstrapped?(vcpkg_root)
  exe = MiniPortile.windows? ? "vcpkg.exe" : "vcpkg"
  File.executable?(File.join(vcpkg_root, exe))
end

#verify_libsObject



134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/emf2svg/recipe.rb', line 134

def verify_libs
  lb_to_verify.each do |l|
    out, st = Open3.capture2("file #{l}")
    raise "Failed to query file #{l}: #{out}" unless st.exitstatus.zero?

    if target_format.match?(out)
      message("Verifying #{l} ... OK\n")
    else
      fmt = target_format.source
      raise "Invalid file format '#{out}', /#{fmt}/ expected"
    end
  end
end

#windows_native?Boolean

Returns:

  • (Boolean)


90
91
92
# File 'lib/emf2svg/recipe.rb', line 90

def windows_native?
  MiniPortile.windows? && target_triplet.eql?("x64-mingw-static")
end