Merge pull request #827 from acemod/makeEnhancements

Make Signature Key Building + enhancements
This commit is contained in:
ViperMaul 2015-04-24 12:36:24 -07:00
commit 9fc14de251
2 changed files with 124 additions and 37 deletions

View File

@ -17,6 +17,11 @@ project = @ace
# Default: None
# key = D:\Program Files (x86)\Bohemia Interactive\Tools\DSSignFile Tools\keys\ace_preAlpha.biprivatekey
# Path to where private keys are automatically created if the command-line parameter "key" is used
# Make sure this isn't in your public repository!
# Default: <work_drive>\private_keys
# private_key_path = P:\private_keys
# If set to True, the make system will attempt to autodetect addons in the
# current folder by looking for directories with 'config.cpp' in them.
# Default: True

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# vim: set fileencoding=utf-8 :
# make.py
@ -60,6 +60,9 @@ module_root = ""
release_dir = ""
module_root_parent = ""
optionals_root = ""
key_name = "ace_preAlpha"
key = ""
dssignfile = ""
###############################################################################
# http://akiscode.com/articles/sha-1directoryhash.shtml
@ -196,6 +199,7 @@ def find_bi_tools(work_drive):
else:
raise Exception("BadTools","Arma 3 Tools are not installed correctly or the P: drive needs to be created.")
def find_depbo_tools(regKey):
"""Use registry entries to find DePBO-based tools."""
stop = False
@ -248,6 +252,7 @@ def find_depbo_tools(regKey):
#Strip any quotations from the path due to a MikeRo tool bug which leaves a trailing space in some of its registry paths.
return [pboproject_path.strip('"'),rapify_path.strip('"'),makepbo_path.strip('"')]
def color(color):
"""Set the color. Works on Win32 and normal terminals."""
if sys.platform == "win32":
@ -336,6 +341,7 @@ def copy_important_files(source_dir,destination_dir):
finally:
os.chdir(originalDir)
def copy_optionals_for_building(mod,pbos):
src_directories = os.listdir(optionals_root)
current_dir = os.getcwd()
@ -350,10 +356,15 @@ def copy_optionals_for_building(mod,pbos):
#print ("Adding the following file: " + file_name)
pbos.append(file_name)
pbo_path = os.path.join(release_dir, "@ace","optionals",file_name)
sigFile_name = file_name +"."+ key_name + ".bisign"
sig_path = os.path.join(release_dir, "@ace","optionals",sigFile_name)
if (os.path.isfile(pbo_path)):
print("Moving " + pbo_path + " for processing.")
shutil.move(pbo_path, os.path.join(release_dir,"@ace","addons",file_name))
if (os.path.isfile(sig_path)):
#print("Moving " + sig_path + " for processing.")
shutil.move(sig_path, os.path.join(release_dir,"@ace","addons",sigFile_name))
except:
print_error("Error in moving")
raise
@ -384,7 +395,8 @@ def copy_optionals_for_building(mod,pbos):
finally:
os.chdir(current_dir)
def cleanup_optionals(mod,pbos):
def cleanup_optionals(mod):
print("")
try:
for dir_name in mod:
@ -400,9 +412,17 @@ def cleanup_optionals(mod,pbos):
file_name = "ace_{}.pbo".format(dir_name)
src_file_path = os.path.join(release_dir, "@ace","addons",file_name)
dst_file_path = os.path.join(release_dir, "@ace","optionals",file_name)
sigFile_name = file_name +"."+ key_name + ".bisign"
src_sig_path = os.path.join(release_dir, "@ace","addons",sigFile_name)
dst_sig_path = os.path.join(release_dir, "@ace","optionals",sigFile_name)
if (os.path.isfile(src_file_path)):
#print("Preserving " + file_name)
os.renames(src_file_path,dst_file_path)
if (os.path.isfile(src_sig_path)):
#print("Preserving " + sigFile_name)
os.renames(src_sig_path,dst_sig_path)
except FileExistsError:
print_error(file_name + " already exists")
continue
@ -411,12 +431,40 @@ def cleanup_optionals(mod,pbos):
except:
print_error("Cleaning Optionals Failed")
raise
def purge(dir, pattern, friendlyPattern="files"):
print_green("Deleting " + friendlyPattern + " files from directory: " + dir)
for f in os.listdir(dir):
if re.search(pattern, f):
os.remove(os.path.join(dir, f))
def build_signature_file(file_name):
global key
global dssignfile
print("Signing with " + key + ".")
ret = subprocess.call([dssignfile, key, file_name])
if ret == 0:
return True
else:
return False
###############################################################################
def main(argv):
"""Build an Arma addon suite in a directory from rules in a make.cfg file."""
print_blue(("\nmake.py for Arma, modified for Advanced Combat Environment v" + __version__))
global work_drive
global module_root
global release_dir
global module_root_parent
global optionals_root
global key_name
global key
global dssignfile
if sys.platform != "win32":
print_error("Non-Windows platform (Cygwin?). Please re-run from cmd.")
sys.exit(1)
@ -436,7 +484,7 @@ def main(argv):
release_version = 0 # Version of release
use_pboproject = True # Default to pboProject build tool
make_target = "DEFAULT" # Which section in make.cfg to use for the build
new_key = False # Make a new key and use it to sign?
new_key = True # Make a new key and use it to sign?
quiet = False # Suppress output from build tool?
# Parse arguments
@ -512,6 +560,8 @@ See the make.cfg file for additional build options.
else:
check_external = False
print_yellow("\nCheck external references is set to " + str(check_external))
# Get the directory the make script is in.
make_root = os.path.dirname(os.path.realpath(__file__))
make_root_parent = os.path.abspath(os.path.join(os.getcwd(), os.pardir))
@ -524,26 +574,27 @@ See the make.cfg file for additional build options.
commit_id = subprocess.check_output(["git", "rev-parse", "HEAD"])
commit_id = str(commit_id, "utf-8")[:8]
key_name = str(key_name+"-"+commit_id)
except:
print_error("FAILED TO DETERMINE COMMIT ID.")
commit_id = "NOGIT"
cfg = configparser.ConfigParser();
try:
global work_drive
global module_root
global release_dir
global module_root_parent
global optionals_root
cfg.read(os.path.join(make_root, "make.cfg"))
# Project name (with @ symbol)
project = cfg.get(make_target, "project", fallback="@"+os.path.basename(os.getcwd()))
# BI Tools work drive on Windows
work_drive = cfg.get(make_target, "work_drive", fallback="P:\\")
# Private key path
key = cfg.get(make_target, "key", fallback=None)
# Private key creation directory
private_key_path = cfg.get(make_target, "private_key_path", fallback=os.path.join(work_drive, "private_keys"))
# Project prefix (folder path)
prefix = cfg.get(make_target, "prefix", fallback="")
@ -561,9 +612,6 @@ See the make.cfg file for additional build options.
# List of directories to ignore when detecting
ignore = [x.strip() for x in cfg.get(make_target, "ignore", fallback="release").split(',')]
# BI Tools work drive on Windows
work_drive = cfg.get(make_target, "work_drive", fallback="P:\\")
# Which build tool should we use?
build_tool = cfg.get(make_target, "build_tool", fallback="addonbuilder").lower()
@ -640,6 +688,20 @@ See the make.cfg file for additional build options.
print ("No cache found.")
cache = {}
if not os.path.isdir(os.path.join(release_dir, project, "addons")):
try:
os.makedirs(os.path.join(release_dir, project, "addons"))
except:
print_error("Cannot create release directory")
raise
if not os.path.isdir(os.path.join(release_dir, project, "keys")):
try:
os.makedirs(os.path.join(release_dir, project, "keys"))
except:
print_error("Cannot create release directory")
raise
#Temporarily copy optionals_root for building. They will be removed later.
optionals_modules = []
optional_files = []
@ -660,31 +722,42 @@ See the make.cfg file for additional build options.
# Make the key specified from command line if necessary.
if new_key:
if not os.path.isfile(os.path.join(module_root, key_name + ".biprivatekey")):
print_green("\nRequested key does not exist.")
print_yellow("\nRequested key does not exist.")
try:
os.makedirs(private_key_path)
except:
pass
curDir = os.getcwd()
os.chdir(private_key_path)
ret = subprocess.call([dscreatekey, key_name]) # Created in make_root
os.chdir(curDir)
if ret == 0:
print_blue("Created: " + os.path.join(module_root, key_name + ".biprivatekey"))
print_green("Created: " + os.path.join(private_key_path, key_name + ".biprivatekey"))
print("Removing any old signature keys...")
purge(os.path.join(module_root, release_dir, project, "addons"), "^.*\.bisign$","*.bisign")
purge(os.path.join(module_root, release_dir, project, "optionals"), "^.*\.bisign$","*.bisign")
purge(os.path.join(module_root, release_dir, project, "keys"), "^.*\.bikey$","*.bikey")
else:
print_error("Failed to create key!")
try:
print_blue("Copying public key to release directory.")
print("Copying public key to release directory.")
try:
os.makedirs(os.path.join(module_root, release_dir, "Keys"))
os.makedirs(os.path.join(module_root, release_dir, project, "keys"))
except:
pass
shutil.copyfile(os.path.join(module_root, key_name + ".bikey"), os.path.join(module_root, release_dir, "Keys", key_name + ".bikey"))
shutil.copyfile(os.path.join(private_key_path, key_name + ".bikey"), os.path.join(module_root, release_dir, project, "keys", key_name + ".bikey"))
except:
raise
print_error("Could not copy key to release directory.")
raise
else:
print_green("\nNOTE: Using key " + os.path.join(module_root, key_name + ".biprivatekey"))
print_green("\nNOTE: Using key " + os.path.join(private_key_path, key_name + ".biprivatekey"))
key = os.path.join(module_root, key_name + ".biprivatekey")
key = os.path.join(private_key_path, key_name + ".biprivatekey")
# For each module, prep files and then build.
@ -692,6 +765,7 @@ See the make.cfg file for additional build options.
for module in modules:
print_green("\nMaking " + module + "-"*max(1, (60-len(module))))
missing = False
sigMissing = False
# Cache check
if module in cache:
@ -706,16 +780,23 @@ See the make.cfg file for additional build options.
# Hash the module
new_sha = get_directory_hash(os.path.join(module_root, module))
# Is the pbo file missing?
# Is the pbo or sig file missing?
missing = not os.path.isfile(os.path.join(release_dir, project, "addons", "ace_{}.pbo".format(module)))
sigFile = pbo_name_prefix+module + ".pbo." + key_name + ".bisign"
sigMissing = not os.path.isfile(os.path.join(release_dir, project, "addons", sigFile ))
if missing:
print("ace_{}.pbo".format(module) + " is missing. Building...")
print_yellow("Missing PBO file ace_{}.pbo".format(module) + ". Building...")
# Check if it needs rebuilt
# print ("Hash:", new_sha)
if old_sha == new_sha and not missing:
if not force_build:
print("Module has not changed.")
if sigMissing:
if key:
print("Missing Signature key " + sigFile)
build_signature_file(os.path.join(module_root, release_dir, project, "addons", pbo_name_prefix + module + ".pbo"))
# Skip everything else
continue
@ -740,13 +821,13 @@ See the make.cfg file for additional build options.
try:
# Remove the old pbo, key, and log
old = os.path.join(module_root, release_dir, project, "Addons", module) + "*"
old = os.path.join(module_root, release_dir, project, "addons", pbo_name_prefix+module) + "*"
files = glob.glob(old)
for f in files:
os.remove(f)
if pbo_name_prefix:
old = os.path.join(module_root, release_dir, project, "Addons", pbo_name_prefix+module) + "*"
old = os.path.join(module_root, release_dir, project, "addons", pbo_name_prefix+module) + "*"
files = glob.glob(old)
for f in files:
os.remove(f)
@ -759,11 +840,11 @@ See the make.cfg file for additional build options.
# Build the module into a pbo
print_blue("Building: " + os.path.join(work_drive, prefix, module))
print_blue("Destination: " + os.path.join(module_root, release_dir, project, "Addons"))
print_blue("Destination: " + os.path.join(module_root, release_dir, project, "addons"))
# Make destination folder (if needed)
try:
os.makedirs(os.path.join(module_root, release_dir, project, "Addons"))
os.makedirs(os.path.join(module_root, release_dir, project, "addons"))
except:
pass
@ -815,7 +896,7 @@ See the make.cfg file for additional build options.
if os.path.isfile(os.path.join(work_drive, prefix, module, "$NOBIN$")):
print_green("$NOBIN$ Found. Proceeding with non-binarizing!")
cmd = [makepboTool, "-P","-A","-L","-N","-G", os.path.join(work_drive, prefix, module),os.path.join(module_root, release_dir, project,"Addons")]
cmd = [makepboTool, "-P","-A","-L","-N","-G", os.path.join(work_drive, prefix, module),os.path.join(module_root, release_dir, project,"addons")]
else:
if check_external:
@ -837,7 +918,7 @@ See the make.cfg file for additional build options.
# Prettyprefix rename the PBO if requested.
if pbo_name_prefix:
try:
os.rename(os.path.join(module_root, release_dir, project, "Addons", module+".pbo"), os.path.join(module_root, release_dir, project, "Addons", pbo_name_prefix+module+".pbo"))
os.rename(os.path.join(module_root, release_dir, project, "addons", module+".pbo"), os.path.join(module_root, release_dir, project, "addons", pbo_name_prefix+module+".pbo"))
except:
raise
print_error("Could not rename built PBO with prefix.")
@ -845,9 +926,9 @@ See the make.cfg file for additional build options.
if key:
print("Signing with " + key + ".")
if pbo_name_prefix:
ret = subprocess.call([dssignfile, key, os.path.join(module_root, release_dir, project, "Addons", pbo_name_prefix + module + ".pbo")])
ret = subprocess.call([dssignfile, key, os.path.join(module_root, release_dir, project, "addons", pbo_name_prefix + module + ".pbo")])
else:
ret = subprocess.call([dssignfile, key, os.path.join(module_root, release_dir, project, "Addons", module + ".pbo")])
ret = subprocess.call([dssignfile, key, os.path.join(module_root, release_dir, project, "addons", module + ".pbo")])
if ret == 0:
build_successful = True
@ -887,7 +968,7 @@ See the make.cfg file for additional build options.
# Call AddonBuilder
os.chdir("P:\\")
cmd = [addonbuilder, os.path.join(work_drive, prefix, module), os.path.join(make_root, release_dir, project, "Addons"), "-clear", "-project="+work_drive]
cmd = [addonbuilder, os.path.join(work_drive, prefix, module), os.path.join(make_root, release_dir, project, "addons"), "-clear", "-project="+work_drive]
if not do_binarize:
cmd.append("-packonly")
@ -910,7 +991,7 @@ See the make.cfg file for additional build options.
# Prettyprefix rename the PBO if requested.
if pbo_name_prefix:
try:
os.rename(os.path.join(make_root, release_dir, project, "Addons", module+".pbo"), os.path.join(make_root, release_dir, project, "Addons", pbo_name_prefix+module+".pbo"))
os.rename(os.path.join(make_root, release_dir, project, "addons", module+".pbo"), os.path.join(make_root, release_dir, project, "addons", pbo_name_prefix+module+".pbo"))
except:
raise
print_error("Could not rename built PBO with prefix.")
@ -920,9 +1001,9 @@ See the make.cfg file for additional build options.
if key:
print("Signing with " + key + ".")
if pbo_name_prefix:
ret = subprocess.call([dssignfile, key, os.path.join(make_root, release_dir, project, "Addons", pbo_name_prefix + module + ".pbo")])
ret = subprocess.call([dssignfile, key, os.path.join(make_root, release_dir, project, "addons", pbo_name_prefix + module + ".pbo")])
else:
ret = subprocess.call([dssignfile, key, os.path.join(make_root, release_dir, project, "Addons", module + ".pbo")])
ret = subprocess.call([dssignfile, key, os.path.join(make_root, release_dir, project, "addons", module + ".pbo")])
if ret == 0:
build_successful = True
@ -965,13 +1046,16 @@ See the make.cfg file for additional build options.
print_green("\nDone.")
copy_important_files(module_root_parent,os.path.join(release_dir, "@ace"))
cleanup_optionals(optionals_modules)
# Make release
if make_release:
print_blue("\nMaking release: " + project + "-" + release_version + ".zip")
try:
# Delete all log files
for root, dirs, files in os.walk(os.path.join(module_root, release_dir, project, "Addons")):
for root, dirs, files in os.walk(os.path.join(module_root, release_dir, project, "addons")):
for currentFile in files:
if currentFile.lower().endswith("log"):
os.remove(os.path.join(root, currentFile))
@ -1004,8 +1088,6 @@ See the make.cfg file for additional build options.
except:
print_error("Could not copy files. Is Arma 3 running?")
copy_important_files(module_root_parent,os.path.join(release_dir, "@ace"))
cleanup_optionals(optionals_modules,optional_files)
if __name__ == "__main__":
main(sys.argv)
input("Press Enter to continue...")