coapp / coapp.powershell

ClrPlus Signing
52 stars 43 forks source link

Static library projects consuming static libraries #73

Open swn1 opened 10 years ago

swn1 commented 10 years ago

This is pretty esoteric and I'm probably doing something stupid, like a typo, but I'm still kind of new to all this and I'm having trouble diagnosing my code.

The context is this: legacy application, part in FORTRAN, part in C++, originally the fortran compiler integrated into the Visual C++ build system and one static library project was built from a folder full of mixed-language sources, exactly like I'd do it with make.

Subsequent releases of the compilers did away with the multi-language project capability. I think it could be done again now but there's no support for controlling the fortran options via project property sheets so it's not very attractive.

So what I've got is a fortran project producing a .lib and consumed explicitly (AdditionalDependencies) by a C++ static library project. The linker incorporates the contents of the fortran lib into the C++ lib and other projects consume that by visual studio inter-project references.

When I attempt to convert the connection to one based on nuget (so the typical developer does not have to have fortran installed) the fortran library ends up in the Linker.AdditionalDependencies item but in VS2013 this is not feeding into the linker when it runs in librarian mode (ie, static lib projects).

I tried adding aliases that I thought would cause it to end up in the Lib.AdditionalDependencies group as well but I'm not seeing anything like that in the targets file and the fortran .lib is not being passed to linker/librarian when the consuming project builds.

Now, even if I get this working, projects that consume the C++ library (and I have a lot of them) will become dependent on the fortran runtime nuget package. It took me a while but I got that working by separating the .lib and .dll components of the redistrubutable. Prior to this effort to adopt nuget the redist was being bulk copied to the solution output folder (we build everything into one folder per configuration) and the consuming projects all have the common output folder on their additional libraries directories paths.

I initially put all the redist components in the bin group and left the path logic as I found it but this broke the project that directly consumes the nuget. On the first run the linkage fails because the components have not yet been copied to the output folder. Only once the link succeeds does the copy happen. Catch-22.

I think to solve this I"m going to need to include the .lib components in both the main package (for direct consumers) and the redist package (for indirect consumers)

The logic that isn't working is: ... } [x64,release] { lib: {....\Release-x64\InterfaceLibFORTRAN\InterfaceLibFORTRAN.lib} } lib += {

add-each-file : ::nuget.targets.[${condition}].LibLibs;

    }
}
targets {
    @alias LibLibs = ItemDefinitionGroup.Lib.AdditionalDependencies;
}
props {
    @alias LibLibs = ItemDefinitionGroup.Lib.AdditionalDependencies;
}

}

I'm still running the release version, I know it's pretty old but I'm not seeing any fixed tickets that I recognize as impacting this problem. My issue #71 will shortly have similar-looking code that does work; I do not yet understand why one does what I expect and the other does not.

mmatrosov commented 10 years ago

It seems like the question is not about CoApp or NuGet, but about Visual Studio linker. If you really want to wrap your old Fortran libraries so that developers don't have to install Fortran runtime, you should make a wrapper dynamic dll, not static lib. Believe me, there is no simple way to make fully stand-alone static lib, there are dozens of pitfalls there. Thus, consider making a stand-alone dll, which links all it needs, and then put this dll into package.

swn1 commented 10 years ago

In a greenfield situation, sure. But in a large legacy code base one wants to be minimally disruptive. I am seeking a way to factor the fortran build out of the C++ build without altering any more logic than necessary. When the first-stage C++ consumer project completes the state of the source tree should be equivalent to its state when the fortran is built locally, from the point of view of indirect consumers.

My question IS about CoApp -- I want to understand what is blocking me from injecting the property I need into the project I already have. The secondary issue, about making the libs visible to consumers-of-the-consumer, that's something I think visual studio provides no support for so a copy task is going to be the only option.

Changing anything about he way this stuff is built incurs risks, in part because there are DLL entry points that are not covered by unit tests. If one gets left out of the link it's not discovered until a customer runs some obscure production job that invokes that entry point. My caution may seem all short-hair and pocket protector-ish but experience counsels caution in these situations.