lutin/lutin/moduleGLD.py

634 lines
19 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
##
## @author Edouard DUPIN
##
## @copyright 2012, Edouard DUPIN, all right reserved
##
## @license MPL v2.0 (see license file)
##
import sys
import os
import copy
import inspect
import fnmatch
import json
# Local import
from . import host
from . import tools
from realog import debug
from . import heritage
from . import builder
from . import multiprocess
from . import image
from . import module
from . import license
from . import env
from warnings import catch_warnings
from xmlrpc.client import boolean
def get_module_type_availlable():
return [
'BINARY',
'BINARY_SHARED',
'BINARY_STAND_ALONE',
'LIBRARY',
'LIBRARY_DYNAMIC',
'LIBRARY_STATIC',
'PACKAGE',
'PREBUILD',
'DATA'
]
list_of_property_module=[
"type",
"sub-type",
"group-id",
"description",
"license",
"license-file",
"author",
"maintainer",
"version",
"version-id",
"code-quality"
];
list_of_element_ignored=[
"comment", # just to post a comment in the configuration files
"todo", # just to post a todo in the configuration files
];
list_of_element_availlable=[
"source",
"header",
"path",
"compilation-version",
"dependency",
"copy",
"flag",
"compilator", # todo
"mode",
"target",
"arch",
"bus-size", # todo
"sanity-compilation" # todo "isolate", "intricate", "*" permit to specify element to copy for the isolation mode. intricate is for current mode where everything is mixed together ...
];
"""
{
"type":"LIBRARY",
"group-id":"com.atria-soft",
"description":"Ewol tool kit (base: container)",
"licence":"MPL-2",
"licence-file":"file://LICENCE.txt",
"maintainer":"Edouard DUPIN <yui.heero@gmail.com>",
"author":"file://../authors.txt",
"version":"1.5.3",
"__version":"file://../version.txt",
"code-quality":"MEDIUM",
"mode": {
"*": {
"target": {
"*": {
"arch": {
"*": {},
}
},
},
"arch": {}
},
"release": {
},
"debug": {
}
},
"source": [
{
"source":"xxx/plop.cpp",
"flag":[
...
]
},
"xxx/Yyy.cpp",
"xxx/YuyTer.cpp"
"xxx/plouf.java"
],
"source": {
"c": [
...
],
"c++": [
...
],
"nasm": [
...
] ...
},
"header": [
"xxx/Yyy.hpp",
"xxx/YuyTer.hpp"
],
"header": {
"c": [
"xxx/Yyy.hpp",
"xxx/YuyTer.hpp"
]
},
"path":[
"."
],
"compilation-version": {
"language": "c++",
"version": 2017
},
"dependency": [
"c",
"m",
"pthread"
],
"copy":[
...
];
"mode": {
"*": {
},
"debug": {
},
"release": {
},
"coverage": {
}
},
"target": {
"*": {
},
"Android": {
"dependency": [
"SDK"
]
},
"MacOs": {
"dependency": [
"cxx"
]
},
"Windows": {
},
"Linux": {
"dependency": [
{
"name": "X11",
"optional": true,
"export": false,
"source": [
"gale/context/X11/Context.cpp"
],
"flag": {
"language": "c++",
"value": "-DGALE_BUILD_X11"
},
"missing-flag": {
"language": "c++",
"value": "-DGALE_DOES_NOT_BUILD_X11"
}
},
},
"Debian": { ## Debian/Ubuntu/Suze/RedHat/ArchLinux/Gento ... heritate from linux ...
},
"IOs": {
},
"Web": {
},
"MacOs|IOs": {
},
"comment": "For all element expect IOS and Android",
"!Android&!IOs": {
},
}
"arch": {
"x86": {
},
"arm": {
},
"ppc": {
}
"misc": {
}
},
"bus-size": {
"*": {
},
"8": {
},
"16": {
},
"32": {
},
"64": {
},
"128": {
}
},
"compilator": {
"*": {
},
"gcc": {
},
"clang": {
},
"mingw": {
},
"msvc": {
},
"intel": {
}
},
"sanity-compilation": {
"*": {
},
"isolate": {
},
"intricate": {
}
}
}
get_compilator
get_mode
get_arch
"""
def check_compatible(mode, value, list_to_check, json_path):
if value == "":
debug.debug("the <" + mode + ">: condition '" + str(value) + "' empty element >> " + json_path);
return False;
if value == "*":
return True;
find_a_valid_key = False;
debug.verbose("Depact: " + value);
# fist step ==> split in the | value ==> multiple check cases
for elemOR in value.split("|"):
debug.verbose(" |: " + elemOR);
# check the condition is True:
condition = True;
if elemOR == "" or elemOR == " " or elemOR == "\t":
debug.warning("the <" + mode + ">: condition '" + str(value) + "' is not supported must not have ' ' or '\\t' or empty element >> " + json_path);
return False;
for elemAND in elemOR.split("&"):
debug.verbose(" &: " + elemAND);
if elemAND == "" or elemAND == " " or elemAND == "\t":
debug.warning("the <" + mode + ">: condition '" + str(value) + "' is not supported must not have ' ' or '\\t' or empty element >> " + json_path);
return False;
invert_condition = False;
if elemAND[0] == "!":
debug.verbose(" ==> invert condition");
invert_condition = True;
elemAND = elemAND[1:]
if elemAND in list_to_check:
debug.verbose(" ==> detect condition OK");
if invert_condition:
condition = False;
debug.verbose(" FALSE");
break;
else:
debug.verbose(" TRUE");
continue;
if invert_condition:
debug.verbose(" TRUE");
continue;
else:
condition = False;
debug.verbose(" FALSE");
break;
if condition:
debug.verbose(" Detect OR condition at TRUE !!!!");
find_a_valid_key = True;
break;
if find_a_valid_key:
return True;
"""
if "|" in value:
debug.warning("in <" + mode + ">: '" + str(value) + " not managed '|' >> " + json_path);
return False;
if "&" in value:
debug.warning("in <" + mode + ">: '" + str(value) + " not managed '&' >> " + json_path);
return False;
if "!" in value:
debug.warning("in <" + mode + ">: '" + str(value) + " not managed '!' >> " + json_path);
return False;
if value in list_to_check or value == "*":
return True;
"""
debug.debug("the <" + mode + ">: '" + str(value) + "' is not compatible with '" + str(list_to_check) + "' >> " + json_path);
return False;
def parse_node_arch(target, path, json_path, my_module, data):
for elem in data.keys():
if check_compatible("arch", elem, target.get_arch(), json_path):
parse_node_generic(target, path, json_path, my_module, data[elem]);
def parse_node_mode(target, path, json_path, my_module, data):
for elem in data.keys():
if check_compatible("mode", elem, target.get_mode(), json_path):
parse_node_generic(target, path, json_path, my_module, data[elem]);
def parse_node_platform(target, path, json_path, my_module, data):
for elem in data.keys():
if check_compatible("target", elem, target.get_type(), json_path):
parse_node_generic(target, path, json_path, my_module, data[elem]);
def parse_node_generic(target, path, json_path, my_module, data, first = False ):
for elem in data.keys():
if elem in list_of_property_module:
if first == True:
continue;
else:
debug.error("key: '" + elem + "' is NOT allowed at expect in the root node: " + json_path);
continue;
if elem in list_of_element_ignored:
continue;
if elem not in list_of_element_availlable:
debug.warning("key: '" + elem + "' is unknown: " + json_path);
debug.warning("Available List: " + str(list_of_element_ignored) + " or: " + str(list_of_element_availlable));
if "source" in data.keys():
if type(data["source"]) == list:
my_module.add_src_file(data["source"]);
elif type(data["source"]) == dict:
if "list" in data["source"].keys():
my_module.add_src_file(data["source"]["list"]);
else:
debug.error("missing 'list' in node 'source:{}'");
else:
debug.error("Wrong type for node 'source' [] or {}");
if "header" in data.keys():
if type(data["header"]) == list:
my_module.add_header_file(data["header"]);
elif type(data["header"]) == dict:
if "list" in data["header"].keys():
my_module.add_header_file(data["header"]["list"]);
else:
debug.error("missing 'list' in node 'header:{}'");
else:
debug.error("Wrong type for node 'headers' [] or {}");
if "path" in data.keys():
if type(data["path"]) == list:
my_module.add_path(data["path"]);
else:
debug.error("Wrong type for node 'path' []");
if "dependency" in data.keys():
if type(data["dependency"]) == list:
for elem in data["dependency"]:
GLD_add_depend(my_module, elem);
else:
debug.error("Wrong type for node 'dependency' []");
if "compilation-version" in data.keys():
if type(data["compilation-version"]) == list:
for elem in data["compilation-version"]:
GLD_compile_version(my_module, elem);
elif type(data["compilation-version"]) == dict:
GLD_compile_version(my_module, data["compilation-version"]);
else:
debug.error("Wrong type for node 'compilation-version' [] or {}");
if "copy" in data.keys():
if type(data["copy"]) == list:
for elem in data["copy"]:
GLD_copy(my_module, elem);
elif type(data["copy"]) == dict:
GLD_copy(my_module, data["copy"]);
else:
debug.error("Wrong type for node 'dependency' []");
if "arch" in data.keys():
parse_node_arch(target, path, json_path, my_module, data["arch"]);
if "target" in data.keys():
parse_node_platform(target, path, json_path, my_module, data["target"]);
if "mode" in data.keys():
parse_node_mode(target, path, json_path, my_module, data["mode"]);
def load_module_from_GLD(target, name, path, json_path):
debug.debug("Parse file: "+ json_path + "'");
try:
data = json.load(open(json_path,))
except json.decoder.JSONDecodeError as ex:
debug.error("Can not parse the file : "+ json_path + " Detect error as : " + str(ex));
property = get_module_option_GLD(path, data, name)
# create the module:
my_module = module.Module(json_path, name, property["type"])
# debug.warning("plopppp " + json.dumps(property, sort_keys=True, indent=4))
# overwrite some package default property (if not set by user)
if property["compagny-type"] != None:
my_module._pkg_set_if_default("COMPAGNY_TYPE", property["compagny-type"])
if property["compagny-name"] != None:
my_module._pkg_set_if_default("COMPAGNY_NAME", property["compagny-name"])
if property["maintainer"] != None:
my_module._pkg_set_if_default("MAINTAINER", property["maintainer"])
if property["name"] != None:
my_module._pkg_set_if_default("NAME", property["name"])
if property["description"] != None:
my_module._pkg_set_if_default("DESCRIPTION", property["description"])
if property["license"] != None:
my_module._pkg_set_if_default("LICENSE", property["license"])
if property["version"] != None:
my_module._pkg_set_if_default("VERSION", property["version"])
# parsing all the file to configure:
parse_node_generic(target, path, json_path, my_module, data, True);
return my_module
def GLD_add_depend(my_module, data):
if type(data) == str:
my_module.add_depend(data);
elif type(data) == dict:
if "name" in data.keys():
name = data["name"];
else:
debug.error("Can not have dependency without name ...");
optional = False;
if "optional" in data.keys():
if type(data["optional"]) == boolean:
optional = data["optional"];
else:
debug.error("Can not have dependency 'optional' in an other type than boolean ...");
export = False;
if "export" in data.keys():
if type(data["export"]) == boolean:
optional = data["export"];
else:
debug.error("Can not have dependency 'export' in an other type than boolean ...");
flags_data = None;
if "flag" in data.keys():
if "language" in data["flag"].keys() and "value" in data["flag"].keys():
flags_data = [data["flag"]["language"], data["flag"]["value"]]
else:
debug.error("Can not have dependency 'flag' without value 'language' and 'value' ...");
missing_flags_data = None;
if "missing-flag" in data.keys():
if "language" in data["missing-flag"].keys() and "value" in data["missing-flag"].keys():
missing_flags_data = [data["missing-flag"]["language"], data["missing-flag"]["value"]]
else:
debug.error("Can not have dependency 'missing-flag' without value 'language' and 'value' ...");
src_file=[]
if "source" in data.keys():
if type(data["source"]) == list:
src_file = data["source"];
elif type(data["source"]) == str:
src_file = [ data["source"] ];
else:
debug.error("Can not have dependency 'source' in an other type than [] or string: '" + str(data["source"]) + "'");
header_file=[]
if "header" in data.keys():
if type(data["header"]) == list:
header_file = data["header"];
elif type(data["header"]) == str:
header_file = [ data["header"] ];
else:
debug.error("Can not have dependency 'header' in an other type than [] or string: '" + str(data["header"]) + "'");
if optional == False:
my_module.add_depend(name);
my_module.add_header_file(header_file);
my_module.add_src_file(src_file);
# TODO: add flags
else:
my_module.add_optionnal_depend(name, flags_data, export=export, compilation_flags_not_found = missing_flags_data, src_file=src_file, header_file=header_file)
else:
debug.error("dependency only support [ {} or string ]");
def GLD_compile_version(my_module, data):
if "language" in data.keys() and "version" in data.keys():
my_module.compile_version(data["language"], data["version"])
else:
debug.error("missing 'language' and/or 'version' in node 'compilation-version:{}'");
def GLD_copy(my_module, data):
path_src = None;
file_src = None;
path_to = "";
recursive = False;
if "path" in data.keys():
path_src = data["path"];
if "file" in data.keys():
file_src = data["file"];
if "to" in data.keys():
path_to = data["to"];
if "recursive" in data.keys():
if type(data["recursive"]) == bool:
recursive = data["recursive"];
else:
debug.error("recursive is a boolean !!!");
if path_src == None and file_src == None:
debug.error("copy must at least have 'path' or 'file' !!!");
if path_src != None:
my_module.copy_path(path_src, path_to);
if file_src != None:
my_module.copy_file(file_src, path_to);
def get_module_option_GLD(path, data, name):
type = None;
if "type" in data.keys():
type = data["type"];
# TODO: check it is in a list ...
else:
debug.error(" the node 'type' must be provided in the module: " + name);
sub_type = None
if "sub-type" in data.keys():
sub_type = data["sub-type"];
compagny_type = None;
compagny_name = None;
group_id = None;
if "group-id" in data.keys():
compagny_name = data["group-id"];
group_id = data["group-id"];
description = None;
if "description" in data.keys():
description = data["description"];
license = None;
if "license" in data.keys():
license = data["license"];
license_file = None;
if "license-file" in data.keys():
license_file = data["license-file"];
maintainer = None;
if "author" in data.keys():
maintainer = tools.get_maintainer_from_file_or_direct(path, data["author"]);
version = None;
if "version" in data.keys():
version = tools.get_version_from_file_or_direct(path, data["version"]);
version_id = None;
if "version-id" in data.keys():
version_id = data["version-id"];
# check type property:
if type not in get_module_type_availlable():
debug.error("Does not support module type: '" + str(type) + "' not in " + str(get_module_type_availlable()) + " path: " + str(path));
list_sub_type = ["TEST", "SAMPLE", "TOOL", None];
if sub_type not in list_sub_type:
debug.error("Does not support module sub-type: '" + str(sub_type) + "' not in " + str(list_sub_type) + " path: " + str(path));
return {
"name":name,
"description":description,
"type":type,
"sub-type":sub_type,
"license":license,
"license-file":license_file,
"compagny-type":compagny_type,
"compagny-name":compagny_name,
"group-id":group_id,
"maintainer":maintainer,
"version":version,
"version-id":version_id
}