Skip to content

Commit 3967018

Browse files
noonienkarlp
authored andcommitted
genlink: Rewrite genlink script from awk to python
This removes the dependency on awk and should fix libopencm3#732 python was already a dependency, for the irq generation
1 parent c7d46c4 commit 3967018

File tree

8 files changed

+151
-113
lines changed

8 files changed

+151
-113
lines changed

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,7 @@ _TIP_: Include this repository as a Git submodule in your project to make sure
4040
Prerequisites
4141
-------------
4242

43-
Building requires Python (some code is generated).
44-
If your user application uses the (optional) dynamic linker script generator,
45-
you will (presently) need GNU AWK. Please see https://github.com/libopencm3/libopencm3/issues/732
43+
Building requires Python (Some code is generated).
4644

4745
**For Ubuntu/Fedora:**
4846

ld/README

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@ File contents
1313

1414
* {ROOT}/ld/tests/* - Prepared tests for the testing of the script
1515
* {ROOT}/ld/devices.data - Device database file
16-
* {ROOT}/ld/Makefile.linker - Common makefile part
1716
* {ROOT}/ld/linker.ld.S - Linker script template
18-
* {ROOT}/scripts/genlink.awk - Device database file search script
17+
* {ROOT}/scripts/genlink.py - Device database file search script
1918
* {ROOT}/scripts/genlinktest.sh - Device database file search test script
2019

2120
Principle of operation
@@ -29,26 +28,15 @@ is case insensitive.
2928

3029
DEVICE=stm32f407vgt6
3130

32-
Then, the user includes the file /ld/Makefile.linker exactly after the first
33-
target (usually all) has been defined.
34-
35-
The script automatically modifies the $(LDSCRIPT) variable to meet the new
36-
generated script with <device part name>.ld in the project directory, and adds
37-
a rule to make it from the scratch.
38-
39-
Making the script is done by looking to device database file for the needed
40-
definitions, and applying those definitions to the C preprocessor source
41-
linker.ld.S outputting the preprocessed ld file.
42-
4331
Device database contains definitions of common sections and its origins for
4432
the linker preprocessor. Every definition is interpreted in the linker script
4533
template as a macro, and it can be used for conditional insertion of the device
4634
dependent stuff.
4735

48-
The search in the device database is pattern-based, and using awk script
49-
genlink.awk. The awk script traverses the file as a tree, joining the options
50-
for the preprocessor together by single space. The awk script adds -D to each
51-
parameter for you.
36+
The search in the device database is pattern-based, and using python script
37+
genlink.py. The python script traverses the file as a tree, joining the options
38+
for the preprocessor together by single space. The python script adds -D to
39+
each parameter for you.
5240

5341
Testing
5442
-------
@@ -69,7 +57,7 @@ The testing stops after all test cases are valid, or at first error found.
6957
Example of use
7058
--------------
7159

72-
* See Makefile.example file
60+
* Check the documentation for the genlink module in /mk/README.
7361

7462
Device database file structure
7563
------------------------------
@@ -127,9 +115,8 @@ stm32 END
127115
--- queried chip name ---
128116
stm32f051c4t6
129117

130-
--- output of the awk script ---
131-
-D_ROM=16K -D_RAM=4K -D_ROM_OFF=0x08000000 -D_RAM_OFF=0x20000000 \
132-
-mcpu=cortex-m0 -mthumb
118+
--- output of the python script ---
119+
-D_ROM=16K -D_RAM=4K -D_ROM_OFF=0x08000000 -D_RAM_OFF=0x20000000
133120

134121
The generated linker script file will contain sections rom and ram with
135122
appropriate initialization code, specified in linker file source linker.ld.S
@@ -154,4 +141,4 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
154141
GNU Lesser General Public License for more details.
155142

156143
You should have received a copy of the GNU Lesser General Public License
157-
along with this library. If not, see <http://www.gnu.org/licenses/>.
144+
along with this library. If not, see <http://www.gnu.org/licenses/>.

ld/devices.data

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
# --- queried chip name ---
5656
# stm32f051c8t6
5757
#
58-
# --- output of the awk script ---
58+
# --- output of the python script ---
5959
# -DROM=16K -DRAM=4K -DROM_OFF=0x08000000 -DRAM_OFF=0x20000000
6060
#
6161
# The generated linker script file will contain sections rom and ram with

mk/genlink-config.mk

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ endif
2424
LDSCRIPT = generated.$(DEVICE).ld
2525
DEVICES_DATA = $(OPENCM3_DIR)/ld/devices.data
2626

27-
genlink_family :=$(shell gawk -v PAT="$(DEVICE)" -v MODE="FAMILY" -f $(OPENCM3_DIR)/scripts/genlink.awk $(DEVICES_DATA))
28-
genlink_subfamily :=$(shell gawk -v PAT="$(DEVICE)" -v MODE="SUBFAMILY" -f $(OPENCM3_DIR)/scripts/genlink.awk $(DEVICES_DATA))
29-
genlink_cpu :=$(shell gawk -v PAT="$(DEVICE)" -v MODE="CPU" -f $(OPENCM3_DIR)/scripts/genlink.awk $(DEVICES_DATA))
30-
genlink_fpu :=$(shell gawk -v PAT="$(DEVICE)" -v MODE="FPU" -f $(OPENCM3_DIR)/scripts/genlink.awk $(DEVICES_DATA))
31-
genlink_cppflags :=$(shell gawk -v PAT="$(DEVICE)" -v MODE="CPPFLAGS" -f $(OPENCM3_DIR)/scripts/genlink.awk $(DEVICES_DATA))
27+
genlink_family :=$(shell $(OPENCM3_DIR)/scripts/genlink.py $(DEVICES_DATA) $(DEVICE) FAMILY)
28+
genlink_subfamily :=$(shell $(OPENCM3_DIR)/scripts/genlink.py $(DEVICES_DATA) $(DEVICE) SUBFAMILY)
29+
genlink_cpu :=$(shell $(OPENCM3_DIR)/scripts/genlink.py $(DEVICES_DATA) $(DEVICE) CPU)
30+
genlink_fpu :=$(shell $(OPENCM3_DIR)/scripts/genlink.py $(DEVICES_DATA) $(DEVICE) FPU)
31+
genlink_cppflags :=$(shell $(OPENCM3_DIR)/scripts/genlink.py $(DEVICES_DATA) $(DEVICE) CPPFLAGS)
3232

3333
CPPFLAGS += $(genlink_cppflags)
3434

mk/genlink-rules.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@
1919

2020
$(LDSCRIPT): $(OPENCM3_DIR)/ld/linker.ld.S $(OPENCM3_DIR)/ld/devices.data
2121
@printf " GENLNK $(DEVICE)\n"
22-
$(Q)$(CPP) $(ARCH_FLAGS) $(shell gawk -v PAT="$(DEVICE)" -v MODE="DEFS" -f $(OPENCM3_DIR)/scripts/genlink.awk $(OPENCM3_DIR)/ld/devices.data 2>/dev/null) -P -E $< > $@
22+
$(Q)$(CPP) $(ARCH_FLAGS) $(shell $(OPENCM3_DIR)/scripts/genlink.py $(DEVICES_DATA) $(DEVICE) DEFS) -P -E $< > $@

scripts/genlink.awk

Lines changed: 0 additions & 77 deletions
This file was deleted.

scripts/genlink.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#!/usr/bin/env python
2+
# This python program generates parameters for the linker script generator feature.
3+
4+
# This file is part of the libopencm3 project.
5+
#
6+
# 2017 George-Cristian Jiglau <noonien>
7+
#
8+
# This library is free software: you can redistribute it and/or modify
9+
# it under the terms of the GNU Lesser General Public License as published by
10+
# the Free Software Foundation, either version 3 of the License, or
11+
# (at your option) any later version.
12+
#
13+
# This library is distributed in the hope that it will be useful,
14+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
# GNU Lesser General Public License for more details.
17+
#
18+
# You should have received a copy of the GNU Lesser General Public License
19+
# along with this library. If not, see <http://www.gnu.org/licenses/>.
20+
from __future__ import print_function
21+
import fnmatch
22+
import sys
23+
import re
24+
import os
25+
26+
if len(sys.argv) != 4:
27+
print("usage: %s <device-data-file> <device> <mode>" % sys.argv[0], file=sys.stderr)
28+
sys.exit(1)
29+
30+
data_file_path = sys.argv[1]
31+
find = sys.argv[2].lower()
32+
mode = sys.argv[3].upper()
33+
34+
device = {
35+
'info': {},
36+
'defs': [],
37+
'family': [],
38+
}
39+
40+
# open device data file
41+
with open(data_file_path, 'r') as data_file:
42+
# iterate lines
43+
for line in data_file:
44+
# strip whitespace from the beginning and end of line
45+
line = line.strip()
46+
47+
# skip empty lines and comments
48+
if line == '' or line.startswith('#'):
49+
continue
50+
51+
# split line into it's parts: <pattern> <parent> <data..>
52+
parts = line.split()
53+
pattern, parent, data = parts[0], parts[1], parts[2:]
54+
55+
# skip line if pattern did not match first element
56+
if not fnmatch.fnmatch(find, pattern):
57+
continue
58+
59+
# extract data
60+
for d in data:
61+
# split into K=V
62+
try:
63+
(k, v) = d.split('=')
64+
except:
65+
continue
66+
67+
# skip invalid datas
68+
if not re.match('^[A-Z0-9_]+$', k):
69+
continue
70+
71+
# add FPU and CPU to info, not defs
72+
if k in ('FPU', 'CPU'):
73+
device['info'][k.lower()] = v
74+
continue
75+
76+
device['defs'].append((k, v))
77+
78+
# if parent is +, there's more data for this pattern
79+
if parent == '+':
80+
continue
81+
82+
# device family
83+
device['family'].append(find)
84+
85+
# break if this was the last line in this chain
86+
if parent == 'END':
87+
break
88+
89+
# look for the parent
90+
find = parent
91+
92+
# reverse device list
93+
device['family'] = device['family'][::-1]
94+
95+
# device was not found
96+
if len(device['family']) == 0:
97+
sys.exit(1)
98+
99+
# for CPPFLAGS and DEFS, define device family
100+
if mode in ('CPPFLAGS', 'DEFS'):
101+
sys.stdout.write(' '.join('-D%s' % d.upper() for d in device['family']))
102+
103+
# defines
104+
if mode == 'DEFS':
105+
if len(device['defs']) > 0:
106+
defs = ' '.join('-D_%s=%s' % d for d in device['defs'])
107+
sys.stdout.write(' ' + defs)
108+
109+
# device family
110+
elif mode == 'FAMILY':
111+
if len(device['family']) > 0:
112+
sys.stdout.write(device['family'][0])
113+
114+
# device subfamily
115+
elif mode == 'SUBFAMILY':
116+
if len(device['family']) > 1:
117+
sys.stdout.write(device['family'][1])
118+
119+
# device info
120+
else:
121+
info = mode.lower()
122+
if info in device['info']:
123+
sys.stdout.write(device['info'][info])
124+
125+
sys.stdout.flush()

scripts/genlinktest.sh

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/bin/sh
22

3-
# This script is intended to test the awk program genlink.awk for the linker
3+
# This script is intended to test the python program genlink.py for the linker
44
# script generator feature.
55
#
66
# See ld/README file for more info.
@@ -25,8 +25,13 @@
2525
# along with this library. If not, see <http://www.gnu.org/licenses/>.
2626

2727
# run test
28-
PAAT=`basename $1`;
29-
gawk -v PAT="$PAAT" -f scripts/genlink.awk $1.data > $1.out;
28+
DEVICE=`basename $1`;
29+
(scripts/genlink.py $1.data $DEVICE CPPFLAGS; echo) > $1.out
30+
(scripts/genlink.py $1.data $DEVICE DEFS; echo) >> $1.out
31+
(scripts/genlink.py $1.data $DEVICE FAMILY; echo) >> $1.out
32+
(scripts/genlink.py $1.data $DEVICE SUBFAMILY; echo) >> $1.out
33+
(scripts/genlink.py $1.data $DEVICE CPU; echo) >> $1.out
34+
(scripts/genlink.py $1.data $DEVICE FPU; echo) >> $1.out
3035

3136
#check test
3237
if ! diff -q $1.out $1.result >/dev/null; then
@@ -36,4 +41,4 @@ fi
3641
#remove workout only if it is OK
3742
rm -f $1.out
3843

39-
exit 0
44+
exit 0

0 commit comments

Comments
 (0)