1
2
3
4
5
6
7
8
9
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
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2018 sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
import sys
import fnmatch
# Same folder
import config
def error(line_i, message):
""" Print a configure.ac error message with the line number.
:param line_i: the zero based line counter """
print("ERROR: configure.ac line " + str(line_i+1) + ": " + message)
sys.exit(1)
def repository(library, version):
""" Find the git repository that contains a certain library. Based on the
information in config.py.
:param library: the name as referenced in the PKG_CHECK_MODULES
statement. For example: "libosmoabis"
:param version: for example "0.5.0"
:returns: the repository name, e.g. "libosmo-abis" """
for repo, libraries in config.repos.items():
if library in libraries:
print(" * " + library + ":" + version + " (part of " + repo + ")")
return repo
print(" * " + library + ":" + version)
return library
def library_is_relevant(library):
""" :returns: True when we would build the library in question from source,
False otherwise. """
for pattern in config.relevant_library_patterns:
if fnmatch.fnmatch(library, pattern):
return True
return False
def parse_condition(line):
""" Find the PKG_CHECK_MODULES conditions in any line from a configure.ac.
Example lines:
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.10.0)
PKG_CHECK_MODULES(LIBSYSTEMD, libsystemd)
:returns: * None when there's no condition in that line
* a string like "libosmocore >= 0.1.0" """
# Only look at PKG_CHECK_MODULES lines
if "PKG_CHECK_MODULES" not in line:
return
# Extract the condition
ret = line.split(",")[1].split(")")[0].strip()
# Only look at Osmocom libraries
library = ret.split(" ")[0]
if library_is_relevant(library):
return ret
def library_version(line_i, condition):
""" Get the library and version strings from a condition.
:param line_i: the zero based line counter
:param condition: a condition like "libosmocore >= 0.1.0" """
# Split by space and remove empty list elements
split = list(filter(None, condition.split(" ")))
if len(split) != 3:
error(line_i, "invalid condition format, expected something"
" like 'libosmocore >= 0.10.0' but got: '" +
condition + "'")
library, operator, version = split
# Right operator
if operator == ">=":
return (library, version)
# Wrong operator
error(line_i, "invalid operator, expected '>=' but got: '" +
operator + "'")
def configure_ac(gitdir, repo):
""" Parse the PKG_CHECK_MODULES statements of a configure.ac file.
:param gitdir: parent folder of all locally cloned git repositories
:param repo: the repository to look at (e.g. "osmo-bts")
:returns: a dictionary like the following:
{"libosmocore": "0.11.0",
"libosmo-abis": "0.5.0"} """
# Read configure.ac
path = gitdir + "/" + repo + "/configure.ac"
with open(path) as handle:
lines = handle.readlines()
# Parse the file into ret
ret = {}
for i in range(0, len(lines)):
# Parse the line
condition = parse_condition(lines[i])
if not condition:
continue
(library, version) = library_version(i, condition)
# Add to ret (with duplicate check)
repo_dependency = repository(library, version)
if repo_dependency in ret and version != ret[repo_dependency]:
error(i, "found multiple PKG_CHECK_MODULES statements for " +
repo_dependency + ".git, and they have different"
" versions!")
ret[repo_dependency] = version
return ret
|