Skip to content

tools/mkconstfs: Add an improved tool.#9282

Merged
MichelRottleuthner merged 1 commit intoRIOT-OS:masterfrom
jcarrano:new-mkconstfs
Jul 2, 2018
Merged

tools/mkconstfs: Add an improved tool.#9282
MichelRottleuthner merged 1 commit intoRIOT-OS:masterfrom
jcarrano:new-mkconstfs

Conversation

@jcarrano
Copy link
Contributor

@jcarrano jcarrano commented Jun 4, 2018

Background

I need to generate a constant file system to run the Lua test suite, and rather than roll my own, I decided to enhance the one already in RIOT.

The problems I found with the current script:

  • It outputs to stdout only and does not buffer the whole output, meaning it can fail but still generate a partial output. When this is used inside a makefile, the result is that the first call to make fails but on the second call there is already a (partial) file up to date and make ignores the target.
  • It crawls the file system, recursively including everything it finds in a directory tree. This is not flexible enough.
  • Filename mangling is not robust enough (it can generate invalid identifier names).

Contribution description

In order not to break code that may use the older script, this PR adds a new script with a different name.

  • Writing to a file is now possible without having to resort to shell redirection.
  • The output is buffered and written only after all processing is done, so there is no partial files and no timestamp changes in case of errors.
  • Complete name mangling. It will only generate valid C identifiers. No more name mangling: no more problems.
  • Files to be included should be given in the command line - no more crawling. There are tools to find and filter files better than any we may ever make ourselves.
  • Command line parsing is done by argparse.

At some point I will extend the tool to embed files in other formats different from constfs.

Issues/PRs references

I need this for #9256.

@jcarrano jcarrano added Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation Area: tools Area: Supplementary tools Area: fs Area: File systems labels Jun 5, 2018
@danpetry danpetry mentioned this pull request Jun 11, 2018
@jcarrano jcarrano requested review from jia200x and jnohlgard and removed request for MichelRottleuthner June 14, 2018 13:30
Copy link
Contributor

@MichelRottleuthner MichelRottleuthner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me in general. the nested maps and lambdas could be split up a bit though.

I tested the generated file with examples/filesystem. everything looks fine - apart from the fact that the path properties of the generated constfs_file_t structs are missing a slash at the beginning, compared to the old mkconstfs.py. This leads to the files not being accessible. With an added slash infront of the filename everything works fine.

lambda x: x[0]//16)
) # noqa: E127
)
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wooha "the python foo is strong in this one" Not sure if this is more "nice and efficient" than it is "ugly and hard to understand/maintain"^^ I'm also wondering why you are mixing yield from and itertools.chain. I'm certain this can be written in a cleaner way, which might also help with getting rid of all the #noqa ... markers ;)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually I'm referring to the lines 105 -111


parser.add_argument("-r", '--root', metavar="root_base_path",
help="Paths on the constf will be gerated for the real"
"path of the files by considering this path to be the root"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

insert whitespaces at the end of the multiline strings above (i.e. after root, real, ..)

"(i.e. there is no partial output")

parser.add_argument("-r", '--root', metavar="root_base_path",
help="Paths on the constf will be gerated for the real"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generated?

@jcarrano jcarrano removed request for jia200x and jnohlgard June 22, 2018 10:36
@jcarrano
Copy link
Contributor Author

@MichelRottleuthner I just realized this script will generate wrong paths if ran in a system that doesn't use UNIX paths. Is that a problem?


parser.add_argument("-o", '--output', metavar="output_file",
help="Write the output to a file instead of stdout."
"The file is only written if the command is successful"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you use type=argparse.FileType here, argparse checks the file and mode for you automatically 1.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason, I didn't like FileType, but that was in the past and I think I forgot the reasons.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I remember, it opens the file right away. Not a good idea with mode "w+".

@MichelRottleuthner
Copy link
Contributor

@MichelRottleuthner I just realized this script will generate wrong paths if ran in a system that doesn't use UNIX paths. Is that a problem?

Not a real problem but I'd prefer to make it as independent from the platform as possible. Its python so everyone will assume it works wherever python is available.

@jcarrano
Copy link
Contributor Author

Its python so everyone will assume it works wherever python is available.

I think the same, but I don't have a windows PC now, so I won't be able to test it.

@MichelRottleuthner
Copy link
Contributor

I have access to a windows machine here so I can help with testing if needed

@jcarrano
Copy link
Contributor Author

@MichelRottleuthner Could you test it?

@MichelRottleuthner
Copy link
Contributor

Tried it on a windows machine but it only seems to work if used with files that are not prefixed by a path (backslashes are not converted to slashes). I'll try to find time to look into a solution later today.
Another thing that I found: you implemented filename mangling to ensure valid identifiers - would it make sense to also do this for the struct names like vfs_mount_t?

@jcarrano
Copy link
Contributor Author

@MichelRottleuthner Ouch! I knew I won't get the windows thing right.

There is not chance of collision with things like vfs_mount_t because the mangling always prefixes an underscore (that's a cheap fix to ensure identifiers never start with a number). I don't think it's reasonable to check the mangled name against all identifiers defined in the file (especially because we are generating identifiers). The options are either leave it as is (what are the chances of a collision?) or drop mangling entirely and generate identifiers of the form _fileXXXXX where XXXXX is some code that does not depend on the filename.



def addroot(fname):
return "/" + fname if not fname.startswith("/") else fname
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to rework this to something using the python os.path module or the pathlib module to keep it OS agnostic. It might just be what is causing issues for @MichelRottleuthner

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this won't help (for everything) because I also got backslashes in the middle of the path

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, so do I understand correctly that the problem is that a path provided as path\to\file on windows shows up in the constfs as /path\to\file?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ourch, that is not supposed to happen, but it's not because of addroot.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just had another look. The problem actually occurs only if relative paths are used. It then not only leaves backslashes there but also creates some crazy paths like /../C:\path\to/C:/path/to/file. I played around with various os.path / pathlib methods and found the following fix to make it working on linux and windows in the same way:

--- a/dist/tools/mkconstfs/mkconstfs2.py
+++ b/dist/tools/mkconstfs/mkconstfs2.py
@@ -1,5 +1,6 @@
 #!/usr/bin/env python3
 
+import os
 import sys
 import argparse
 import pathlib
@@ -50,7 +51,8 @@ static const uint8_t {varname}[] = {{
 
 
 def _relpath_p(path, start):
-    return posixpath.relpath(path.as_posix(), start.as_posix())
+    return posixpath.relpath(pathlib.Path(os.path.abspath(path)).as_posix(),
+                             pathlib.Path(os.path.abspath(start)).as_posix())

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MichelRottleuthner Great! Can you push it to my branch, please?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just tried that but somehow it doesn't work. Did you allow edits for maintainers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was enabled. If it still does not work, I can apply a patch.
screenshot_2018-06-29_11-40-18

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope still doesn't work just add it yourself, please

@MichelRottleuthner
Copy link
Contributor

There is not chance of collision with things like vfs_mount_t

sorry, my wording wasn't clear enough. What I meant was the name of the struct instance which is put into the constfs_name field in the C_FOOTER template. Arguably one coud blame the user for putting invalid names there but i think it would help if there is some kind of warning (or mangling).

I'll try to find time to look into a solution later today

I have to shift that to tomorrow...

@jcarrano
Copy link
Contributor Author

@MichelRottleuthner I think it's out of scope to check if the user tells the tool to create a struct with an invalid name. Almost every time this tool is used it will be from within a makefile and the name will be fixed. The Correct(TM) way of generating code and making sure it's correct is to create an abstract tree and dump it as code. Templating things we will always run into some kind of corner case, and it's not practical to check everything. As long as we don't generate wrong code that still compiles and fails silently and weirdly, it's ok.

@jcarrano
Copy link
Contributor Author

BTW, what is the opinion on dropping name mangling and going for serially generated identifiers? AFAIK, GCC allows for arbitrarily long identifiers, but then we could have a file that it a hairy mess of characters.

@MichelRottleuthner
Copy link
Contributor

since the user/dev will not use the mangled names in most cases anyway you could also use short numbered identifiers. This could also save some memory ;)

@MichelRottleuthner
Copy link
Contributor

@jcarrano squash and we are ready to go!

The new tool (mkconstfs2) features:

* more robust filename handling: no need for mangling,
  and works on Windows.
* Better output generation: nothing is written in case
  of failures.
* Allows more control over the files that are included:
 - does not traverse directories, filenames must be explicitly
   given.
 - The "root" can be explicitly given (thus the tool can get
   the same result independently of the CWD).

Thanks to MichelRottleuthner for making it work with Windows paths.
@jcarrano
Copy link
Contributor Author

jcarrano commented Jul 2, 2018

@MichelRottleuthner Squashed and edited the commit msg to give you some credit.

@jcarrano jcarrano closed this Jul 2, 2018
@jcarrano
Copy link
Contributor Author

jcarrano commented Jul 2, 2018

Oops, accidentally hit "close"!!!

@jcarrano jcarrano reopened this Jul 2, 2018
@MichelRottleuthner MichelRottleuthner added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Jul 2, 2018
@MichelRottleuthner MichelRottleuthner merged commit 2ac61b7 into RIOT-OS:master Jul 2, 2018
@cladmi cladmi added this to the Release 2018.07 milestone Jul 10, 2018
@jcarrano jcarrano deleted the new-mkconstfs branch November 8, 2018 15:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: fs Area: File systems Area: tools Area: Supplementary tools CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants