<commit_before>require "Build"
require "Utils"
require "../Helpers"

local llvm = path.getabsolute(basedir .. "/../deps/llvm")

-- Prevent premake from inserting /usr/lib64 search path on linux. GCC does not need this path specified
-- as compiler automatically knows where to look for system libs. Insertion of this path causes issues
-- when system has clang/llvm libs installed. Build would link to system libraries instead of custom
-- build required by CppSharp.
if os.istarget("linux") then
	premake.tools.gcc.libraryDirectories['architecture']['x86_64'] = function(cfg) return {} end
end

-- If we are inside vagrant then clone and build LLVM outside the shared folder,
-- otherwise file I/O performance will be terrible.
if is_vagrant() then
	llvm = os.getenv("HOME") .. "/llvm"
end

function get_llvm_rev()
	return cat(basedir .. "/LLVM-commit")
end

function get_clang_rev()
	return cat(basedir .. "/Clang-commit")
end

function clone_llvm()
  local llvm_release = get_llvm_rev()
  print("LLVM release: " .. llvm_release)

  local clang_release = get_clang_rev()
  print("Clang release: " .. clang_release)

  if os.ishost("windows") then
    extract = extract_7z
  else
    extract = extract_tar_gz
  end

  local archive = 'llvm-'..llvm_release..'.tar.gz'
  if os.isfile(archive) then
    print('Archive '..archive..' already exists.')
  else
    download('https://github.com/llvm-mirror/llvm/archive/'..llvm_release..'.tar.gz', archive)
  end

  if os.isdir(llvm) then
    os.rmdir(llvm)
    if os.isdir(llvm) then
      print('Removing '..llvm..' directory failed. Please remove it manually and restart.')
      return
    end
  end

  extract(archive, '.')
  os.rename('llvm-'..llvm_release, llvm)

  archive = 'clang-'..clang_release..'.tar.gz'
  if os.isfile(archive) then
    print('Archive '..archive..' already exists.')
  else
    download('https://github.com/llvm-mirror/clang/archive/'..clang_release..'.tar.gz', archive)
  end
  extract(archive, '.')
  os.rename('clang-'..clang_release, llvm..'/tools/clang')
end
function get_vs_version()
  local function map_msvc_to_vs_version(major, minor)
    if major == "19" and minor >= "10" then return "vs2017"
    elseif major == "19" then return "vs2015"
    elseif major == "18" then return "vs2013"
    elseif major == "17" then return "vs2012"
    else error("Unknown MSVC compiler version, run in VS command prompt.") end
  end

  local out = outputof("cl")
  local major, minor = string.match(out, '(%d+).(%d+).%d+.?%d*%s+')
  
  return map_msvc_to_vs_version(major, minor)
end

function get_toolset_configuration_name(arch)
  if not arch then
    arch = target_architecture()
  end

  if os.istarget("windows") then
    local vsver = _ACTION

    if not string.starts(vsver, "vs") then
      vsver = get_vs_version()
    end

    return table.concat({vsver, arch}, "-")
  end
  -- FIXME: Implement for non-Windows platforms
  return table.concat({arch}, "-")
end

-- Returns a string describing the package configuration.
-- Example: llvm-f79c5c-windows-vs2015-x86-Debug
function get_llvm_package_name(rev, conf, arch)
  if not rev then
  	rev = get_llvm_rev()
  end
  rev = string.sub(rev, 0, 6)

  local components = {"llvm", rev, os.target()}

  local toolset = get_toolset_configuration_name(arch)
  table.insert(components, toolset)

  if os.istarget("linux") then
    local version = GccVersion()
    if version < "5.0.0" then
      -- Minor version matters only with gcc 4.8/4.9
      version = string.match(version, "%d+.%d+")
    else
      version = string.match(version, "%d+")
    end
    table.insert(components, "gcc-"..version)
  end

  if not conf then
  	conf = get_llvm_configuration_name()
  end

  table.insert(components, conf)

  if os.istarget("linux") then
    if GccVersion() >= "4.9.0" and not UseCxx11ABI() then
      table.insert(components, "no-cxx11")
    end
  end

  return table.concat(components, "-")
end

function get_llvm_configuration_name(debug)
	if debug == true then
		return "Debug"
	end
	return os.istarget("windows") and "RelWithDebInfo" or "Release"
end

function get_7z_path()
	local path = "C:\\Program Files\\7-Zip\\7z.exe"
	if os.isfile(path) then
		return string.format('"%s"', path)
	end
	return "7z.exe"
end

function extract_7z(archive, dest_dir)
	return execute_or_die(string.format("%s x %s -o%s -y", get_7z_path(),
		archive, dest_dir), true)
end

function extract_tar_xz(archive, dest_dir)
	execute("mkdir -p " .. dest_dir, true)
	return execute_or_die(string.format("tar xJf %s -C %s", archive, dest_dir), true)
end

function extract_tar_gz(archive, dest_dir)
	execute("mkdir -p " .. dest_dir, true)
	return execute_or_die(string.format("tar xf %s -C %s", archive, dest_dir), true)
end

local use_7zip = os.ishost("windows")
local archive_ext = use_7zip and ".7z" or ".tar.xz"

function download_llvm()
  local toolset = get_toolset_configuration_name()<commit_msg>Fixed LLVM/Clang tar.gz archive extraction using 7-Zip on Windows.<commit_after>require "Build"
require "Utils"
require "../Helpers"

local llvm = path.getabsolute(basedir .. "/../deps/llvm")

-- Prevent premake from inserting /usr/lib64 search path on linux. GCC does not need this path specified
-- as compiler automatically knows where to look for system libs. Insertion of this path causes issues
-- when system has clang/llvm libs installed. Build would link to system libraries instead of custom
-- build required by CppSharp.
if os.istarget("linux") then
	premake.tools.gcc.libraryDirectories['architecture']['x86_64'] = function(cfg) return {} end
end

-- If we are inside vagrant then clone and build LLVM outside the shared folder,
-- otherwise file I/O performance will be terrible.
if is_vagrant() then
	llvm = os.getenv("HOME") .. "/llvm"
end

function get_llvm_rev()
	return cat(basedir .. "/LLVM-commit")
end

function get_clang_rev()
	return cat(basedir .. "/Clang-commit")
end

function clone_llvm()
  local llvm_release = get_llvm_rev()
  print("LLVM release: " .. llvm_release)

  local clang_release = get_clang_rev()
  print("Clang release: " .. clang_release)

  if os.ishost("windows") then
    extract = extract_7z_tar_gz
  else
    extract = extract_tar_gz
  end

  local archive = 'llvm-'..llvm_release..'.tar.gz'
  if os.isfile(archive) then
    print('Archive '..archive..' already exists.')
  else
    download('https://github.com/llvm-mirror/llvm/archive/'..llvm_release..'.tar.gz', archive)
  end

  if os.isdir(llvm) then
    os.rmdir(llvm)
    if os.isdir(llvm) then
      print('Removing '..llvm..' directory failed. Please remove it manually and restart.')
      return
    end
  end

  extract(archive, '.')
  os.rename('llvm-'..llvm_release, llvm)

  archive = 'clang-'..clang_release..'.tar.gz'
  if os.isfile(archive) then
    print('Archive '..archive..' already exists.')
  else
    download('https://github.com/llvm-mirror/clang/archive/'..clang_release..'.tar.gz', archive)
  end
  extract(archive, '.')
  os.rename('clang-'..clang_release, llvm..'/tools/clang')
end
function get_vs_version()
  local function map_msvc_to_vs_version(major, minor)
    if major == "19" and minor >= "10" then return "vs2017"
    elseif major == "19" then return "vs2015"
    elseif major == "18" then return "vs2013"
    elseif major == "17" then return "vs2012"
    else error("Unknown MSVC compiler version, run in VS command prompt.") end
  end

  local out = outputof("cl")
  local major, minor = string.match(out, '(%d+).(%d+).%d+.?%d*%s+')
  
  return map_msvc_to_vs_version(major, minor)
end

function get_toolset_configuration_name(arch)
  if not arch then
    arch = target_architecture()
  end

  if os.istarget("windows") then
    local vsver = _ACTION

    if not string.starts(vsver, "vs") then
      vsver = get_vs_version()
    end

    return table.concat({vsver, arch}, "-")
  end
  -- FIXME: Implement for non-Windows platforms
  return table.concat({arch}, "-")
end

-- Returns a string describing the package configuration.
-- Example: llvm-f79c5c-windows-vs2015-x86-Debug
function get_llvm_package_name(rev, conf, arch)
  if not rev then
  	rev = get_llvm_rev()
  end
  rev = string.sub(rev, 0, 6)

  local components = {"llvm", rev, os.target()}

  local toolset = get_toolset_configuration_name(arch)
  table.insert(components, toolset)

  if os.istarget("linux") then
    local version = GccVersion()
    if version < "5.0.0" then
      -- Minor version matters only with gcc 4.8/4.9
      version = string.match(version, "%d+.%d+")
    else
      version = string.match(version, "%d+")
    end
    table.insert(components, "gcc-"..version)
  end

  if not conf then
  	conf = get_llvm_configuration_name()
  end

  table.insert(components, conf)

  if os.istarget("linux") then
    if GccVersion() >= "4.9.0" and not UseCxx11ABI() then
      table.insert(components, "no-cxx11")
    end
  end

  return table.concat(components, "-")
end

function get_llvm_configuration_name(debug)
	if debug == true then
		return "Debug"
	end
	return os.istarget("windows") and "RelWithDebInfo" or "Release"
end

function get_7z_path()
	local path = "C:\\Program Files\\7-Zip\\7z.exe"
	if os.isfile(path) then
		return string.format('"%s"', path)
	end
	return "7z.exe"
end

function extract_7z_tar_gz(archive, dest_dir)
	extract_7z(archive, dest_dir)
	local tar = string.sub(archive, 1, -4)
	extract_7z(tar, dest_dir)
end

function extract_7z(archive, dest_dir)
	return execute(string.format("%s x %s -o%s -y", get_7z_path(),
		archive, dest_dir), false)
end

function extract_tar_xz(archive, dest_dir)
	execute("mkdir -p " .. dest_dir, true)
	return execute_or_die(string.format("tar xJf %s -C %s", archive, dest_dir), true)
end

function extract_tar_gz(archive, dest_dir)
	execute("mkdir -p " .. dest_dir, true)
	return execute_or_die(string.format("tar xf %s -C %s", archive, dest_dir), true)
end

local use_7zip = os.ishost("windows")
local archive_ext = use_7zip and ".7z" or ".tar.xz"

function download_llvm()
  local toolset = get_toolset_configuration_name()
{'fraction_non_alphanumeric': 0.1332133213321332, 'fraction_numerical': 0.014001400140014001, 'mean_word_length': 3.759638267491671, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1421434', 'n_tokens_mistral': 3517, 'n_tokens_neox': 3388, 'n_words': 942}