Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
F
frama-c
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Container Registry
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
pub
frama-c
Commits
72934bd4
Commit
72934bd4
authored
3 years ago
by
Andre Maroneze
Browse files
Options
Downloads
Patches
Plain Diff
[analysis-scripts] build: fix issues with JBDBs and relative directories
parent
f7363645
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
share/analysis-scripts/build.py
+53
-23
53 additions, 23 deletions
share/analysis-scripts/build.py
with
53 additions
and
23 deletions
share/analysis-scripts/build.py
+
53
−
23
View file @
72934bd4
...
@@ -122,8 +122,7 @@ def call_and_get_output(command_and_args):
...
@@ -122,8 +122,7 @@ def call_and_get_output(command_and_args):
def
ask_if_overwrite
(
path
):
def
ask_if_overwrite
(
path
):
yn
=
input
(
f
"
warning:
{
path
}
already exists. Overwrite? [y/N]
"
)
yn
=
input
(
f
"
warning:
{
path
}
already exists. Overwrite? [y/N]
"
)
if
yn
==
""
or
not
(
yn
[
0
]
==
"
Y
"
or
yn
[
0
]
==
"
y
"
):
if
yn
==
""
or
not
(
yn
[
0
]
==
"
Y
"
or
yn
[
0
]
==
"
y
"
):
print
(
"
Exiting without overwriting.
"
)
sys
.
exit
(
"
Exiting without overwriting.
"
)
sys
.
exit
(
0
)
def
insert_lines_after
(
lines
,
line_pattern
,
new_lines
):
def
insert_lines_after
(
lines
,
line_pattern
,
new_lines
):
re_line
=
re
.
compile
(
line_pattern
)
re_line
=
re
.
compile
(
line_pattern
)
...
@@ -158,6 +157,11 @@ def replace_line(lines, line_pattern, value, all_occurrences=False):
...
@@ -158,6 +157,11 @@ def replace_line(lines, line_pattern, value, all_occurrences=False):
else
:
else
:
sys
.
exit
(
f
"
error: no lines found matching pattern:
{
line_pattern
}
"
)
sys
.
exit
(
f
"
error: no lines found matching pattern:
{
line_pattern
}
"
)
# replaces '/' with '_' so that a valid target name is created
def
make_target_name
(
target
):
pp
=
blug_jbdb
.
prettify
(
target
)
return
pp
.
replace
(
'
/
'
,
'
_
'
)
# sources are pretty-printed relatively to the .frama-c directory, where the
# sources are pretty-printed relatively to the .frama-c directory, where the
# GNUmakefile will reside
# GNUmakefile will reside
def
rel_prefix
(
path
):
def
rel_prefix
(
path
):
...
@@ -188,16 +192,28 @@ def copy_fc_stubs():
...
@@ -188,16 +192,28 @@ def copy_fc_stubs():
fc_stubs_copied
=
True
fc_stubs_copied
=
True
return
dest
return
dest
# returns the line number where a likely definition for [funcname] was found,
# Returns pairs (line_number, has_args) for each likely definition of
# or None otherwise
# [funcname] in [filename].
# [has_args] is used to distinguish between main(void) and main(int, char**).
def
find_definitions
(
funcname
,
filename
):
def
find_definitions
(
funcname
,
filename
):
with
open
(
filename
,
encoding
=
"
ascii
"
,
errors
=
'
ignore
'
)
as
data
:
with
open
(
filename
,
encoding
=
"
ascii
"
,
errors
=
'
ignore
'
)
as
data
:
file_content
=
data
.
read
()
file_content
=
data
.
read
()
file_lines
=
file_content
.
splitlines
(
keepends
=
True
)
file_lines
=
file_content
.
splitlines
(
keepends
=
True
)
newlines
=
function_finder
.
compute_newline_offsets
(
file_lines
)
newlines
=
function_finder
.
compute_newline_offsets
(
file_lines
)
defs
=
function_finder
.
find_definitions_and_declarations
(
True
,
False
,
filename
,
file_content
,
file_lines
,
newlines
)
defs
=
function_finder
.
find_definitions_and_declarations
(
True
,
False
,
filename
,
file_content
,
file_lines
,
newlines
,
funcname
)
defs
=
[
d
for
d
in
defs
if
d
[
0
]
==
funcname
]
#print(f"found defs for {funcname}: {defs}")
return
[
d
[
2
]
for
d
in
defs
]
res
=
[]
for
d
in
defs
:
defining_line
=
file_lines
[
d
[
2
]
-
1
]
after_funcname
=
defining_line
[
defining_line
.
find
(
funcname
)
+
len
(
funcname
):]
# heuristics: if there is a comma after the function name,
# it is very likely the signature contains arguments;
# otherwise, the function is either defined in several lines,
# or we somehow missed it. By default, we assume it has no arguments
# if we miss it.
has_args
=
'
,
'
in
after_funcname
res
.
append
((
d
[
2
],
has_args
))
return
res
# End of auxiliary functions ##################################################
# End of auxiliary functions ##################################################
...
@@ -207,7 +223,7 @@ if sources:
...
@@ -207,7 +223,7 @@ if sources:
sys
.
exit
(
f
"
error: option --targets is mandatory when --sources is specified
"
)
sys
.
exit
(
f
"
error: option --targets is mandatory when --sources is specified
"
)
if
len
(
targets
)
>
1
:
if
len
(
targets
)
>
1
:
sys
.
exit
(
f
"
error: option --targets can only have a single target when --sources is specified
"
)
sys
.
exit
(
f
"
error: option --targets can only have a single target when --sources is specified
"
)
sources_map
[
targets
[
0
]]
=
sources
sources_map
[
targets
[
0
]]
=
[
s
for
s
in
sources
if
blug_jbdb
.
filter_source
(
s
)]
elif
os
.
path
.
isfile
(
jbdb_path
):
elif
os
.
path
.
isfile
(
jbdb_path
):
# JBDB exists
# JBDB exists
with
open
(
jbdb_path
,
"
r
"
)
as
data
:
with
open
(
jbdb_path
,
"
r
"
)
as
data
:
...
@@ -230,7 +246,7 @@ elif os.path.isfile(jbdb_path):
...
@@ -230,7 +246,7 @@ elif os.path.isfile(jbdb_path):
else
:
else
:
if
unknown_targets
!=
[]:
if
unknown_targets
!=
[]:
continue
# already found a problem; avoid useless computations
continue
# already found a problem; avoid useless computations
sources
=
blug_jbdb
.
collect_leaves
(
graph
,
[
target
])
sources
=
[
s
for
s
in
blug_jbdb
.
collect_leaves
(
graph
,
[
target
])
if
blug_jbdb
.
filter_source
(
s
)]
sources_map
[
target
]
=
sorted
([
blug_jbdb
.
prettify
(
source
)
for
source
in
sources
])
sources_map
[
target
]
=
sorted
([
blug_jbdb
.
prettify
(
source
)
for
source
in
sources
])
if
unknown_targets
:
if
unknown_targets
:
targets_pretty
=
"
\n
"
.
join
(
unknown_targets
)
targets_pretty
=
"
\n
"
.
join
(
unknown_targets
)
...
@@ -248,18 +264,21 @@ if unknown_sources:
...
@@ -248,18 +264,21 @@ if unknown_sources:
# Check that the main function is defined exactly once per target.
# Check that the main function is defined exactly once per target.
# note: this is only based on heuristics (and fails on a few real case studies),
# note: this is only based on heuristics (and fails on a few real case studies),
# so we cannot emit errors, only warnings
# so we cannot emit errors, only warnings.
# We also need to check if the main function uses a 'main(void)'-style
# signature, to patch fc_stubs.c.
main_definitions
=
{}
for
target
,
sources
in
sources_map
.
items
():
for
target
,
sources
in
sources_map
.
items
():
main_definitions
=
[]
main_definitions
[
target
]
=
[]
for
source
in
sources
:
for
source
in
sources
:
defs
=
find_definitions
(
main
,
source
)
fun
defs
=
find_definitions
(
main
,
source
)
main_definitions
+=
[(
source
,
line
)
for
line
in
defs
]
main_definitions
[
target
]
+=
[(
source
,
fundef
[
0
],
fundef
[
1
])
for
fundef
in
fun
defs
]
if
main_definitions
==
[]:
if
main_definitions
[
target
]
==
[]:
print
(
f
"
warning
:
function
'
{
main
}
'
seems to be never defined in the sources of target
'
{
target
}
'"
)
logging
.
warning
(
f
"
function
'
{
main
}
'
seems to be never defined in the sources of target
'
{
blug_jbdb
.
prettify
(
target
)
}
'"
)
elif
len
(
main_definitions
)
>
1
:
elif
len
(
main_definitions
[
target
]
)
>
1
:
print
(
f
"
warning
:
function
'
{
main
}
'
seems to be defined multiple times in the sources of target
'
{
target
}
'
:
"
)
logging
.
warning
(
f
"
function
'
{
main
}
'
seems to be defined multiple times in the sources of target
'
{
blug_jbdb
.
prettify
(
target
)
}
'
:
"
)
for
(
filename
,
line
)
in
main_definitions
:
for
(
filename
,
line
,
_
)
in
main_definitions
[
target
]
:
print
(
f
"
- definition at
{
filename
}
:
{
line
}
"
)
print
(
f
"
- definition at
{
filename
}
:
{
line
}
"
)
# End of checks; start writing GNUmakefile and stubs from templates ###########
# End of checks; start writing GNUmakefile and stubs from templates ###########
...
@@ -271,9 +290,19 @@ if not dot_framac_dir.is_dir():
...
@@ -271,9 +290,19 @@ if not dot_framac_dir.is_dir():
fc_config
=
json
.
loads
(
call_and_get_output
([
framac_bin
/
"
frama-c
"
,
"
-print-config-json
"
]))
fc_config
=
json
.
loads
(
call_and_get_output
([
framac_bin
/
"
frama-c
"
,
"
-print-config-json
"
]))
share_dir
=
Path
(
fc_config
[
'
datadir
'
])
share_dir
=
Path
(
fc_config
[
'
datadir
'
])
fc_stubs
=
copy_fc_stubs
()
# copy fc_stubs if at least one main function has arguments
for
target
in
targets
:
any_has_arguments
=
False
sources_map
[
target
].
insert
(
0
,
fc_stubs
)
for
defs
in
main_definitions
.
values
():
if
any
(
d
[
2
]
for
d
in
defs
):
any_has_arguments
=
True
break
if
any_has_arguments
:
fc_stubs
=
copy_fc_stubs
()
for
target
in
targets
:
if
any
(
d
[
2
]
for
d
in
main_definitions
[
target
]):
logging
.
debug
(
f
"
target
{
blug_jbdb
.
prettify
(
target
)
}
has main with args, adding fc_stubs.c to its sources
"
)
sources_map
[
target
].
insert
(
0
,
fc_stubs
)
gnumakefile
=
dot_framac_dir
/
"
GNUmakefile
"
gnumakefile
=
dot_framac_dir
/
"
GNUmakefile
"
...
@@ -289,14 +318,15 @@ if machdep:
...
@@ -289,14 +318,15 @@ if machdep:
if
jbdb_path
:
if
jbdb_path
:
insert_lines_after
(
template
,
"
^FCFLAGS
"
,
[
f
"
-json-compilation-database
{
rel_prefix
(
jbdb_path
)
}
\\
"
])
insert_lines_after
(
template
,
"
^FCFLAGS
"
,
[
f
"
-json-compilation-database
{
rel_prefix
(
jbdb_path
)
}
\\
"
])
targets_eva
=
([
f
"
{
target
}
.eva
\\
"
for
target
in
targets
])
targets_eva
=
([
f
"
{
make_
target
_name
(
target
)
}
.eva
\\
"
for
target
in
targets
])
replace_line
(
template
,
"
^TARGETS = main.eva
"
,
"
TARGETS =
\\
"
)
replace_line
(
template
,
"
^TARGETS = main.eva
"
,
"
TARGETS =
\\
"
)
insert_lines_after
(
template
,
r
"
^TARGETS = \\
"
,
targets_eva
)
insert_lines_after
(
template
,
r
"
^TARGETS = \\
"
,
targets_eva
)
delete_line
(
template
,
r
"
^main.parse: \\
"
)
delete_line
(
template
,
r
"
^main.parse: \\
"
)
delete_line
(
template
,
r
"
^ main.c \\
"
)
delete_line
(
template
,
r
"
^ main.c \\
"
)
for
target
,
sources
in
reversed
(
sources_map
.
items
()):
for
target
,
sources
in
reversed
(
sources_map
.
items
()):
new_lines
=
[
f
"
{
target
}
.parse:
\\
"
]
+
pretty_sources
(
sources
)
+
[
""
,
f
"
{
target
}
.parse: FCFLAGS += -main eva_main
"
,
""
]
pp_target
=
make_target_name
(
target
)
new_lines
=
[
f
"
{
pp_target
}
.parse:
\\
"
]
+
pretty_sources
(
sources
)
+
[
""
,
f
"
{
pp_target
}
.parse: FCFLAGS += -main eva_main
"
,
""
]
insert_lines_after
(
template
,
"
^### Each target <t>.eva
"
,
new_lines
)
insert_lines_after
(
template
,
"
^### Each target <t>.eva
"
,
new_lines
)
gnumakefile
.
write_text
(
"
\n
"
.
join
(
template
))
gnumakefile
.
write_text
(
"
\n
"
.
join
(
template
))
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment