Module: Objctify

Defined in:
lib/objctify/context.rb,
lib/objctify.rb,
lib/objctify/command.rb,
lib/objctify/version.rb,
lib/objctify/fix_imports.rb,
lib/objctify/informative.rb,
lib/objctify/command/init.rb,
lib/objctify/command/this.rb,
lib/objctify/generate_project.rb,
lib/objctify/translator_runner.rb,
lib/objctify/j2objc/j2_obj_c_prefixes.rb

Overview

Copyright Devexperts (2019)

This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at mozilla.org/MPL/2.0/.

Defined Under Namespace

Classes: Command, Context, Informative, J2ObjCPrefixes

Constant Summary collapse

VERSION =
"0.4.0".freeze

Class Method Summary collapse

Class Method Details

.collect_files(java_source_path) ⇒ Object



10
11
12
13
14
15
16
# File 'lib/objctify/translator_runner.rb', line 10

def self.collect_files(java_source_path)
  files_to_translate = ''
  Dir.glob(java_source_path + '/**/*.java') do |item|
    files_to_translate = files_to_translate + item + ' '
  end
  files_to_translate
end

.compose_j2objc_call(java_sources, j2objc_home, prefix_file_path, result_path, extra_cli_args) ⇒ Object



29
30
31
32
33
34
35
36
37
# File 'lib/objctify/translator_runner.rb', line 29

def self.compose_j2objc_call(java_sources, j2objc_home, prefix_file_path, result_path, extra_cli_args)
  j2objc_call = "#{j2objc_home}/j2objc -source 8 --swift-friendly -l #{extra_cli_args} -d #{result_path} -classpath #{j2objc_home}/lib/jsr305-3.0.0.jar -sourcepath #{java_sources}"

  unless prefix_file_path.nil? || prefix_file_path == ''
    j2objc_call += " --prefixes #{prefix_file_path}"
  end

  j2objc_call
end

.fix_imports(framework_name, prefix_file_path) ⇒ Object



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
# File 'lib/objctify/fix_imports.rb', line 10

def self.fix_imports(framework_name, prefix_file_path)
  prefixes = J2ObjCPrefixes.new(prefix_file_path)

  header_map = {}
  Dir.chdir(framework_name) do
    Pathname('.').find do |path|
      dir, base = path.split

      next unless path.file?

      prefix = prefixes.prefix_for(path.dirname.to_s)
      path.rename(dir.to_s + '/' + prefix + base.to_s)
      header_map[path.to_s.sub('./', '')] = prefix + base.to_s
    end
  end

  Dir.chdir(framework_name) do
    Pathname('.').find do |path|
      next unless path.file?

      import_reg_exp = %r{(#[a-zA-Z]+\s+"([a-zA-Z_0-9/]+.[hm]{1})")}

      text = File.read(path)
      text.scan(import_reg_exp).each do |import|

        if (mapped_import = header_map[import[1]]) && !mapped_import.nil?
          text = text.gsub(import[1], mapped_import)
        end
      end

      File.open(path, 'w') do |f|
        f.write(text)
      end
    end
  end
end

.generate_project(framework_name, j2objc_home) ⇒ Object



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
# File 'lib/objctify/generate_project.rb', line 12

def self.generate_project(framework_name, j2objc_home)
  project = Xcodeproj::Project.new("#{framework_name}.xcodeproj")
  target = project.new_target(:framework, framework_name, :ios)

  source_build_phase = target.source_build_phase
  headers_build_phase = target.headers_build_phase

  #add files
  Pathname(framework_name).find do |path|
    dir, base = path.split
    if path.directory?

      if path.to_s == framework_name
        project.new_group base.to_s, base
      else
        group_to_append_to = project[dir.to_s]
        group_to_append_to.new_group base.to_s, base
      end

    elsif path.file?

      group = project[dir.to_s]
      new_ref = group.new_reference base

      if new_ref.last_known_file_type == 'sourcecode.c.h'
        build_file = headers_build_phase.add_file_reference new_ref
        build_file.settings = { ATTRIBUTES: ['', 'Public'] }
      elsif new_ref.last_known_file_type == 'sourcecode.c.objc'
        source_build_phase.add_file_reference new_ref
      end

    end
  end

  header_file_path = Pathname("#{framework_name}/#{framework_name}.h")

  File.open(header_file_path, 'w') do |header_file|
    header_template = "//
//  #{framework_name}.h
//  #{framework_name}
//
//

#import <UIKit/UIKit.h>

//! Project version number for #{framework_name}.
FOUNDATION_EXPORT double #{framework_name}VersionNumber;

//! Project version string for #{framework_name}.
FOUNDATION_EXPORT const unsigned char #{framework_name}VersionString[];

"

    header_file.write(header_template)
    header_file.write(headers_build_phase.files_references.map(&:path).map { |header_file_name| "#include <#{framework_name}/" + header_file_name + '>' } * "\n")
  end

  dir, base = header_file_path.split

  header_file_ref = project[dir.to_s].new_reference base
  header_build_file = headers_build_phase.add_file_reference header_file_ref
  header_build_file.settings = { ATTRIBUTES: ['', 'Public'] }

  project.targets.each do |target|
    target.add_system_library_tbd(%w[z iconv])
    target.add_system_framework('UIKit')

    path = File.expand_path("#{j2objc_home}/frameworks/JRE.framework")
    unless (ref = project.frameworks_group.find_file_by_path(path))
      ref = project.frameworks_group.new_file(path, :absolute)
    end
    target.frameworks_build_phase.add_file_reference(ref, true)

    target.build_configurations.each do |config|
      config.build_settings['CLANG_ENABLE_OBJC_ARC'] = false
      config.build_settings['FRAMEWORK_SEARCH_PATHS'] = "#{j2objc_home}/frameworks"
      config.build_settings['HEADER_SEARCH_PATHS'] = "#{j2objc_home}/frameworks/JRE.framework/Headers"

      # Workaround
      config.build_settings['SUPPORTS_MACCATALYST'] = false
    end
  end

  project.save
end

.translate_files(java_sources, prefix_file_path, j2objc_home, result_path, extra_cli_args) ⇒ Object



18
19
20
21
22
23
24
25
26
27
# File 'lib/objctify/translator_runner.rb', line 18

def self.translate_files(java_sources, prefix_file_path, j2objc_home, result_path, extra_cli_args)
  files_to_translate = collect_files(java_sources)

  raise Objctify::Informative, "No files to translate, check 'java_sources' parameter in Objctifile" if files_to_translate.empty?

  j2objc_call = compose_j2objc_call(java_sources, j2objc_home, prefix_file_path, result_path, extra_cli_args) + ' ' + files_to_translate
  call = system(j2objc_call)

  raise Objctify::Informative, "J2Objc call is unsuccessful: #{j2objc_call}" unless call
end