Re: [Premake-users] Advice on linking and dependencies
On GitHub now!
Brought to you by:
starkos,
ttk-bandit
From: Ash B. <ash...@fi...> - 2009-05-14 08:34:18
|
On 14 May 2009, at 05:46, Jason McKesson wrote: > Ash Berlin wrote: >> >> SharedLibs get a bit messier i think, take this layout, which is >> similar to my project >> >> project "A" >> kind "SharedLib" >> includedir { "./include", "boost-1_37" } >> links { "boostlibs" } >> >> project "B" >> kind "SharedLib" >> links "A" >> >> project "CProg" >> links {"A", "B" } >> >> >> Now, to compile either of A, B or C, the boost-1_37 include path >> needs to be there, since the API headers from libA.so include boost >> header files. And both B and CProg needs libA.so to link against >> (or A.lib on windows.) So to confirm, the gcc comands for these >> projects would be like the following >> >> gcc -o libA.so -I./include -Iboost-1_37 -Lboost_1-37 -lboostlibs >> files.... >> gcc -o libB.so -I./include -lA -Lpath-to-A files... >> gcc -o CProg -I./include -Lpath-to-A -Lpath-to-B -lA -lB -Iboost_1-37 >> >> How does this work with your proposed scheme above. I think it >> should work, but I'd like you confirm this. >> >> -ash >> > Before I begin, there is a minor point I'd like to bring up. I don't > know about the portions of Boost that need to be compiled into a > library, but the compile-time parts of Boost are essentially > guaranteed to not be shared. So in your above case, "A" would have a > copy of Boost, "B" would have its own copy of Boost, and CProg would > have its own copy of Boost separate from the other two. They are all > interoperable so long as they're built from the same version, but > it's generally frowned upon to pass objects from static libraries > across the .dll barrier. It can cause problems if those libraries > use globals, as each of these will have their *own* version of those > globals. However, ignoring that issue for the purposes of this > conversation. Mmm yes, you are right - linking with A should just need the boost inc dirs. If the project needs the libs to link, then it needs to say so itself. On 14 May 2009, at 05:46, Jason McKesson wrote: > [snip] > > Let's take the following situation: > > project "lowLevel" > kind "StaticLib" > > project "HideLib" > kind "StaticLib" > <needs "lowLevel" to compile. Users of HideLib do not need > "lowLevel" to compile themselves, but those who do linking need > "lowLevel.lib" to link themselves.> > > project "ShowLib" > kind "StaticLib" > <needs "lowLevel" to compile. Users of ShowLib also need "lowLevel" > to compile and link themselves.> > > project "HideShare" > kind "SharedLib" > <needs "lowLevel" to compile and link. Users of HideShare do not > need "lowLevel" to compile themselves. They don't need to link to > "lowLevel", because it's already linked to us.> > > project "ShowShare" > kind "SharedLib" > <needs "lowLevel" to compile and link. Users of ShowShare need > "lowLevel" to compile and link themselves; they need a duplicate > copy of "lowLevel" in their address space.> > > All of these projects are assumed to have usage projects that > provide the appropriate information that gets copied into the > project that connects to them. > > What we have here are 4 separate kinds of relationships one can have > to "lowLevel". Notice how the behavior changes somewhat based on > whether the project is a linked (shared lib or application) or a > static library. In the case of HideLib vs. HideShare, HideShare is > able to provide full recursion prevention. HideShare links to > everything internally, so since it doesn't expose those things > externally, users of HideShare don't need anything that HideShare > doesn't specifically want to expose. Whereas HideLib is able to keep > compile-time information private, but since it's a static library, > it must expose static links. > > By contrast, users of the two "Show" versions can't really tell a > difference. In both cases they need access to the compile *and* link > information (if they do linking, of course) of "lowLevel". > > So there are really only 3 relationships. And the difference between > HideLib and HideShare is implicit by the kind of project they are, > which brings things down to 2. So what we need are two kinds of > usage types, one that means "users of me don't need these, but I do > internally" and the other that says "users of me do need these". > > Another problem, not this one precisely, is that we're overloading > the meaning of "links". I initially used "links" because it already > had a specific meaning to the various actions if the project was > already part of the solution. The problem is that this meaning is > not consistent between a project that is in the solution and a bare > static library file if the project being including it is a static > library. This goes back to a conversation I had with the other Jason > waaaay back in 2007. The determination was that static library > projects that link to other static library projects should always > include the symbols of the source library, whether it was a sibling > project in the solution or just a loose library file. That was never > implemented, though admittedly I never filed the bug on it that I > was supposed to either. So... > > Anyway, even if it were consistent, it isn't the meaning that we > need here. So I think I'm going to fully abandon "links" as a way of > connecting usage information to dependent projects. Oh, I'll make > use of "links" to connect two projects together where appropriate, > but I'd rather use new identifiers that don't have additional > baggage to create the actual connections. > > So I'm thinking of "uses" as being the "users of me don't need > these, but I do internally," and "externaluses" as being the "users > of me need these". Projects explicitly named in the "links" field > will be ignored for these purposes. > > Man, that was long. That started out in a very different place from > where it ended... You do write long messages don't you. how about an API config block? Something like this: project "A" kind "SharedLib" links { "boostfoo" } include {"private/include" } api() includedir { "boost-1_37" } defines { "XP_UNIX" } links { "A" } -- Maybe this isn't needed. I'm not sure if this is actually possible to do like this, but if it is, then anything you pass define in the api block is used by how ever you end up using the project, since its the kind of project that changes how it links, not how you use the project, isn't it. *Me reads your post again to check* Hmmm no, that wouldn't quite work with your distinction between HideLib and ShowLib you had above, unless.. project "lowLevel" kind "StaticLib" api() includedir { "..." } links { "lowLevel" } project "HideLib" kind "StaticLib" -- needs "lowLevel" to compile. Users of HideLib do not need "lowLevel" -- to compile themselves, but those who do linking need "lowLevel.lib" to link themselves. uses "lowLevel" -- no api() block project "ShowLib" kind "StaticLib" -- needs "lowLevel" to compile. Users of ShowLib also need "lowLevel" -- to compile and link themselves. api() uses "lowLevel" project "HideShare" kind "SharedLib" -- needs "lowLevel" to compile and link. Users of HideShare do not need "lowLevel" -- to compile themselves. They don't need to link to "lowLevel", because it's -- already linked to us. uses "lowLevel" -- no api() project "ShowShare" kind "SharedLib" -- needs "lowLevel" to compile and link. Users of ShowShare need "lowLevel" -- to compile and link themselves; they need a duplicate copy of "lowLevel" -- in their address space. api() uses "lowLevel" That is to say, if you use a project/lib inside an API block, it is copied recursively into your api block, and also affects the compilation of your own project. If you use it outside of an api block, it just affects compilation/linking of the current project. Does this make sense, and perhaps more importantly is it implementable? -ash |