Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Link all .obj files from another project

I have an executable C++ project that used to contain embedded unit tests. I've moved the tests to another (.dll) project, to use them with the VS Test Runner, and all is well except for a bunch of unresolved external symbol errors.

Things seem to work if I link all of the .obj files from the .exe into the .dll, but there are a lot of them and it's very "dirty" to hardcode them since the list can always change.

I've tried adding the .exe project as a reference and setting "use Library Dependency Inputs" to True, but it doesn't seem to do anything.

like image 274
makhdumi Avatar asked Oct 21 '22 01:10

makhdumi


1 Answers

Upon inspection of Microsoft.CppBuild.targets, I found that .obj files for projects with UseLibraryDependencyInputs set to true, which corresponds to checking 'use Library Dependency Inputs' in VS, are included only if the project is a StaticLibrary.

A quick and dirty way around this then is to override the Task ResolvedLinkObjs inside the .vcxproj, with slight modifications.

Testing this out, I was able to link all the .obj files from the projects I referenced.

I changed the ItemName of the TargetOutputs MSBuild task output to "ProjectReferenceToLink" and added ConfigurationType=StaticLibrary to the passed Properties. The side-effects of treating the .exe project as a StaticLibrary while calling this target aren't immediately obvious, but I haven't noticed anything bad.

  <Target Name="ResolvedLinkObjs" DependsOnTargets="$(CommonBuildOnlyTargets)">
    <MSBuild Projects="@(_MSBuildProjectReferenceExistent)"
             Targets="GetResolvedLinkObjs"
             BuildInParallel="$(BuildInParallel)"
             Properties="%(_MSBuildProjectReferenceExistent.SetConfiguration); %(_MSBuildProjectReferenceExistent.SetPlatform); ConfigurationType=StaticLibrary"
             Condition="'%(_MSBuildProjectReferenceExistent.Extension)' == '.vcxproj' and '@(ProjectReferenceWithConfiguration)' != '' and '@(_MSBuildProjectReferenceExistent)' != ''"
             ContinueOnError="!$(BuildingProject)"
             RemoveProperties="%(_MSBuildProjectReferenceExistent.GlobalPropertiesToRemove)">
      <Output TaskParameter="TargetOutputs" ItemName="ProjectReferenceToLink" />
    </MSBuild>
  </Target>

This can easily be modified to just grab the .objs from one project. A cleaner method would also probably involve not overriding a built-in Target like this but instead inserting it into to the chain.

like image 55
makhdumi Avatar answered Oct 24 '22 04:10

makhdumi