Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding package imports in the .cbproj file

I am using Embarcadero RAD Studio 2010 (C++). The project file (.cbproj) has five different tags that contain lists of .bpis or .libs. I would like some information about how each of these lists of library files is used by the linker (when building with or without runtime packages).

LinkPackageImports

LinkPackageStatics

AllPackageLibs

PackageLibs

PackageImports
I think I already understand this last one. It contains the list of runtime packages that can be set from the Project Properties in the IDE.

The motivation for this question is that I am trying to eliminate unnecessary dependencies from my application. These five tags in the .cbproj each seem to contain an arbitrary assortment of different libs and bpis. Some of the libraries I know I do not need, and some of the libraries I think I do not need. Removing some libraries from some of the lists seems to have no effect, while removing other libraries from other lists causes linker errors of the form [ILINK32 Error] Fatal: Unable to open file 'FILENAME.OBJ'

I am slowly resolving all the linker issues, but it would be really helpful to know exactly what I am telling the linker to do when I include a library name in one of these five lists.

like image 513
Jeff Wilhite Avatar asked Aug 02 '12 22:08

Jeff Wilhite


1 Answers

I'm sure this information must exist somewhere, but I have been unable to find it in any forums or documentation. I have deduced all of this from my own experimentation, but I would appreciate feedback from a more official source.

PackageImports -- This appears as the "Runtime packages" list in Project Options in the IDE. If you add or remove anything from the "Runtime packages" list in the IDE, this tag will be updated to reflect that. If this tag is empty or missing from the cbproj file, it will be automatically populated with a list of all the run-time packages associated with all the design-time packages installed in RAD Studio. This tag has no effect when building from the command-line. The IDE seems to use the PackageImports tag just to compute the libraries it is actually going to link.

Placing a library in this list does not (by itself) create any new dependencies; you are essentially telling the IDE "If you have to link any of these libraries, link them dynamically rather than statically".

AllPackageLibs -- This is the IDE's list of all the libraries that it thinks are required for the project to link successfully. This tag has no effect when building from the command-line. If you make a change to the project (e.g. add a file) the IDE will attempt to recompute the contents of AllPackageLibs. It computes this from the #pragma links it finds in the files of the project. (I determined this by commenting out all of the #pragma links in the project and noticing that AllPackageLibs was not repopulated when I made a project modification.)

LinkPackageStatics -- If the IDE finds a library in AllPackageLibs that does not appear in PackageImports, it decides to statically link that library. In that case, the IDE will automatically copy the library name to LinkPackageStatics. If building from the IDE, this tag will always be recomputed from AllPackageLibs and PackageImports, so anything you add here manually will be ignored by the linker. However, if building from the command-line, all of the files in this tag (.libs or .bpis) will be linked and will appear in the 'objfiles' section of ilink32's command line.

LinkPackageImports -- If the IDE finds a library in AllPackageLibs that does appear in PackageImports, it decides to dynamically link that library. In that case, the IDE will copy the library name (with a .bpi extension) to LinkPackageImports. If building from the IDE, this tag will always be recomputed from AllPackageLibs and PackageImports, so anything you add here manually will be ignored by the linker. However, if building from the command-line, all of the files in this tag (.libs or .bpis) will be linked and will appear in the 'libfiles' section of ilink32's command line.

PackageLibs -- Anything in PackageLibs (.libs or .bpis) will be directly added to LinkPackageStatics by the IDE (regardless of what PackageImports contains). These libs are added to LinkPackageStatics in front of the libs that come from AllPackageLibs. Command-line builds are not affected by this tag.

Anytime you are expecting the IDE to modify LinkPackageStatics or LinkPackageImports for you, you will need to first build the project in the IDE; then make a minor change to the project options (and undo it); then save the project. At this point the IDE will write out the LinkPackageStatics or LinkPackageImports to the cbproj so that your project can be linked on the command line.

Other ways to link libaries -- There are also a couple of ways for specifying files to be linked which do not involve these four tags. You may add the .lib directly to the project (right-click project | Add...), or you may insert the line #pragma comment (lib, "libraryname.lib") in one of the files that is compiled with the project.

If you add the .lib directly to the project, it will appear on the command-line with all the other libraries to be linked. If you use the #pragma comment trick, the library will not appear on the command line, and you will not be able to see that it was linked (except by using tdump and looking at the exports).

Summary

When linking from the command-line, the only cbproj tags (of these five) that have any effect are LinkPackageStatics (libs to add to the objfiles section) and LinkPackageImports (libs to add to the libfiles section). The contents of these tags are computed by the IDE from AllPackageLibs and PackageImports, but you can set them manually in the .cbproj if you need to link from the command line.

When linking from the IDE, you will usually want the IDE to manage your libraries for you. If you need to add a library that the IDE does not automatically detect, you should open the .cbproj file in an external editor and add the missing library to the AllPackageLibs tag. If you want the library to be dynamically-linked, you should also add the library name to the "Build with runtime packages" list (aka PackageImports).

If you want to be sure you are dynamically-linking all your libraries, look at the LinkPackageStatics tag in the .cbproj file. If any libraries are in that list, they are being statically-linked. To fix this, copy the names of those libraries into the PackageLibs tag (and change their extensions to bpi); then remove the LinkPackageStatics tag.

like image 65
Jeff Wilhite Avatar answered Nov 11 '22 01:11

Jeff Wilhite