Briefly describe the environment:
This is a C ++ build system. It is extended based on premake and can manage the dependency relationship between packages [1]/libraries, each package publishes a Lua file along with binary to describe the exported library and dependent package. For example:
Libraries = {}
Dependencies = {}
In this way, the entire dependency closure is serialized.
Currently, users need to define their own functions in this Lua file so that they can call them when defining their projects, the goal is to provide more precise control for consumer when using the library.
For example, in boost's use. Lua, define:
Function use_boost_thread ()
Links ('boost _ 000046_0000thread ')
-- Do Anything special...
End
And Foo depends on boost:
Project ('foo ')
Kind ('sharedlib ')
Use_boost_thread ()
It should be said that this is a flexible design that gives the database publisher and user greater control, but how can premake be implemented?
User defined in their use. functions in the Lua file are not directly available-because there are a lot of use during the premake operation. lua files are loaded, and they need to be loaded into an independent table (through setfenv) to avoid name conflicts between libraries and dependencies, therefore, we need to introduce these functions loaded into the independent table into the global table [2], for example:
_ G['Functionname'] = NS. use_boost_thread ()
The problem is that users can define many functions in their use. Lua. You need to know which function should be imported to the global table-the user must tell me in some way, what method? One method is to use naming convention. For example, all functions to be exported start with use _ and all functions starting with use _ can be imported. However, this method is not flexible, not robust, and obviously stupid:
- If I want a function everywhere, it must start with this ugly use _.
- If an internal function accidentally starts a name starting with use _, it is unfortunately exported.
- To modify whether the function is exported, You need to modify the function name.
Is there a better way? Yes. It is explicitly specified through a data structure, for example:
Exports = {'Use_boost_thread'}FunctionUse_boost_thread () links ('Boost_000046_0000thread')--Do anything special...End
Then, you can name your function at will and place the exported function in the exports table.
When processing, read exports first, find the exported function name, and export them.
This is equivalent to adding an indirect layer, which reminds me of one sentence: all problems in computer science can be solved by another level of indirection [3].
Of course, another better method is to add properties (C #/Java) to the function, or add modifications (_ declspec (dllimport) in C ++) /visibility ('hiddy') is more concise and clear.
[1] The concept of package is a series of libraries that need to be jointly released, such as boost or opencv. users use a package, but do not have to link all the libraries in the package, it may be only one of the links.
[2] A reference implementation: https://gist.github.com/4133666
[3] http://en.wikipedia.org/wiki/Indirection