at master 165 lines 7.1 kB view raw
1/** 2 * Since Nix does not have a standard location like /usr/share where GSettings system 3 * could look for schemas, we need to point the software to a correct location somehow. 4 * For executables, we handle this using wrappers but this is not an option for libraries like e-d-s. 5 * Instead, we patch the source code to look for the schema in a schema source 6 * through a hardcoded path to the schema. 7 * 8 * For each schema id referenced in the source code (e.g. org.gnome.evolution), 9 * a variable name such as `EVOLUTION` must be provided in the ./glib-schema-to-var.json JSON file. 10 * It will end up in the resulting patch as `@EVOLUTION@` placeholder, which should be replaced at build time 11 * with a path to the directory containing a `gschemas.compiled` file that includes the schema. 12 */ 13 14@initialize:python@ 15@@ 16import json 17 18cpp_constants = {} 19 20def register_cpp_constant(const_name, val): 21 cpp_constants[const_name] = val.strip() 22 23def resolve_cpp_constant(const_name): 24 return cpp_constants.get(const_name, const_name) 25 26with open("./glib-schema-to-var.json") as mapping_file: 27 schema_to_var = json.load(mapping_file); 28 29def get_schema_directory(schema_id): 30 # Sometimes the schema id is referenced using C preprocessor #define constant in the same file 31 # let’s try to resolve it first. 32 schema_id = resolve_cpp_constant(schema_id.strip()).strip('"') 33 if schema_id in schema_to_var: 34 return f'"@{schema_to_var[schema_id]}@"' 35 raise Exception(f"Unknown schema path {schema_id!r}, please add it to ./glib-schema-to-var.json") 36 37 38@script:python schema_exists_fn@ 39fn; 40@@ 41import json 42 43with open("./glib-schema-exists-function.json") as fn_file: 44 if (fn := json.load(fn_file)): 45 coccinelle.fn = fn 46 47 48@find_cpp_constants@ 49identifier const_name; 50expression val; 51@@ 52 53#define const_name val 54 55@script:python record_cpp_constants depends on find_cpp_constants@ 56const_name << find_cpp_constants.const_name; 57val << find_cpp_constants.val; 58@@ 59 60register_cpp_constant(const_name, val) 61 62 63@depends on ever record_cpp_constants || never record_cpp_constants@ 64// We want to run after #define constants have been collected but even if there are no #defines. 65expression SCHEMA_ID; 66expression settings; 67// Coccinelle does not like autocleanup macros in + sections, 68// let’s use fresh id with concatenation to produce the code as a string. 69fresh identifier schema_source_decl = "g_autoptr(GSettingsSchemaSource) " ## "schema_source"; 70fresh identifier schema_decl = "g_autoptr(GSettingsSchema) " ## "schema"; 71fresh identifier SCHEMA_DIRECTORY = script:python(SCHEMA_ID) { get_schema_directory(SCHEMA_ID) }; 72@@ 73-settings = g_settings_new(SCHEMA_ID); 74+{ 75+ schema_source_decl; 76+ schema_decl; 77+ schema_source = g_settings_schema_source_new_from_directory(SCHEMA_DIRECTORY, 78+ g_settings_schema_source_get_default(), 79+ TRUE, 80+ NULL); 81+ schema = g_settings_schema_source_lookup(schema_source, SCHEMA_ID, FALSE); 82+ settings = g_settings_new_full(schema, NULL, NULL); 83+} 84 85 86@depends on ever record_cpp_constants || never record_cpp_constants@ 87// We want to run after #define constants have been collected but even if there are no #defines. 88expression SCHEMA_ID; 89expression settings; 90expression BACKEND; 91// Coccinelle does not like autocleanup macros in + sections, 92// let’s use fresh id with concatenation to produce the code as a string. 93fresh identifier schema_source_decl = "g_autoptr(GSettingsSchemaSource) " ## "schema_source"; 94fresh identifier schema_decl = "g_autoptr(GSettingsSchema) " ## "schema"; 95fresh identifier SCHEMA_DIRECTORY = script:python(SCHEMA_ID) { get_schema_directory(SCHEMA_ID) }; 96@@ 97-settings = g_settings_new_with_backend(SCHEMA_ID, BACKEND); 98+{ 99+ schema_source_decl; 100+ schema_decl; 101+ schema_source = g_settings_schema_source_new_from_directory(SCHEMA_DIRECTORY, 102+ g_settings_schema_source_get_default(), 103+ TRUE, 104+ NULL); 105+ schema = g_settings_schema_source_lookup(schema_source, SCHEMA_ID, FALSE); 106+ settings = g_settings_new_full(schema, BACKEND, NULL); 107+} 108 109 110@depends on ever record_cpp_constants || never record_cpp_constants@ 111// We want to run after #define constants have been collected but even if there are no #defines. 112expression SCHEMA_ID; 113expression settings; 114expression BACKEND; 115expression PATH; 116// Coccinelle does not like autocleanup macros in + sections, 117// let’s use fresh id with concatenation to produce the code as a string. 118fresh identifier schema_source_decl = "g_autoptr(GSettingsSchemaSource) " ## "schema_source"; 119fresh identifier schema_decl = "g_autoptr(GSettingsSchema) " ## "schema"; 120fresh identifier SCHEMA_DIRECTORY = script:python(SCHEMA_ID) { get_schema_directory(SCHEMA_ID) }; 121@@ 122-settings = g_settings_new_with_backend_and_path(SCHEMA_ID, BACKEND, PATH); 123+{ 124+ schema_source_decl; 125+ schema_decl; 126+ schema_source = g_settings_schema_source_new_from_directory(SCHEMA_DIRECTORY, 127+ g_settings_schema_source_get_default(), 128+ TRUE, 129+ NULL); 130+ schema = g_settings_schema_source_lookup(schema_source, SCHEMA_ID, FALSE); 131+ settings = g_settings_new_full(schema, BACKEND, PATH); 132+} 133 134 135@depends on ever record_cpp_constants || never record_cpp_constants@ 136// We want to run after #define constants have been collected but even if there are no #defines. 137expression SCHEMA_ID; 138expression settings; 139expression PATH; 140// Coccinelle does not like autocleanup macros in + sections, 141// let’s use fresh id with concatenation to produce the code as a string. 142fresh identifier schema_source_decl = "g_autoptr(GSettingsSchemaSource) " ## "schema_source"; 143fresh identifier schema_decl = "g_autoptr(GSettingsSchema) " ## "schema"; 144fresh identifier SCHEMA_DIRECTORY = script:python(SCHEMA_ID) { get_schema_directory(SCHEMA_ID) }; 145@@ 146-settings = g_settings_new_with_path(SCHEMA_ID, PATH); 147+{ 148+ schema_source_decl; 149+ schema_decl; 150+ schema_source = g_settings_schema_source_new_from_directory(SCHEMA_DIRECTORY, 151+ g_settings_schema_source_get_default(), 152+ TRUE, 153+ NULL); 154+ schema = g_settings_schema_source_lookup(schema_source, SCHEMA_ID, FALSE); 155+ settings = g_settings_new_full(schema, NULL, PATH); 156+} 157 158 159@replace_schema_exists_fns depends on ever record_cpp_constants || never record_cpp_constants@ 160// We want to run after #define constants have been collected but even if there are no #defines. 161expression SCHEMA_ID; 162identifier schema_exists_fn.fn; 163@@ 164-fn(SCHEMA_ID) 165+TRUE