1

I'm compiling some C++ code into a library. Suppose my source files are mylib.cpp and util.cpp. The code in util.cpp is used in the library implementation, but is not part of the library in the sense that code using the library cannot call it (it's not in the public headers) and should not be aware of its existence; but my_lib.cpp includes util.hpp and does rely on the compiled util.cpp object code.

Now, if I compile mylib.o and util.o, then perform:

ar qc libmylib.a mylib.o util.o

my library works just fine; but - the utility code is exposed as symbols. Thus, if I link this library with some other code, there might be clashes of double-definitions. Or that other code might inappropriately rely on symbols being available (e.g. with its own header).

How can I ensure that only the object code in mylib.o (and in util.o) "sees" the symbols from util.o, while outside code does not?

Note: I believe this question stands also for C and perhaps other compiled languages.

2
  • If privacy is a major concern, I'd probably consider including util.cpp (as well as util.hpp) into the source for mylib.cpp (#include "util.cpp") with appropriate namespace controls so that the code is available inside mylib.cpp but not outside (anonymous namespace, or namespace mylib::Private or some such scheme). This is not particularly conventional, but it is probably effective (once you've worked out the necessary tweaks). The chances are that the combination TU (translation unit) is not so big as to cause your compiler major problems. This doesn't rely on compiler extensions. Commented Feb 5, 2020 at 1:08
  • @JonathanLeffler: Including the .cpp is an interesting suggestion. Make it an answer?
    – einpoklum
    Commented Feb 5, 2020 at 8:49

2 Answers 2

1

Transferring comments into an answer.

If your C++ library has its own namespace, then using that or a sub-namespace is nominally the correct way to control access to the internal utilities. It sounds as if your code is not providing template classes — the constraints for those have to be thought through separately.

If privacy is a major concern, I'd probably consider including util.cpp (as well as util.hpp) into the source for mylib.cpp (meaning #include "util.cpp") with appropriate namespace controls so that the code from util.cpp is available inside mylib.cpp but not outside (using an anonymous namespace, or namespace mylib::Private or some such scheme). This is not very conventional, but it is probably effective (once you've worked out the necessary tweaks). The chances are that the combination TU (translation unit) is not so big as to cause your compiler major problems. This doesn't rely on compiler extensions.

0

Here is my fallback "solution", which is actually a workaround:

I keep the public visibility, but I burden all of the code in util.cpp with some element of naming which will make it effectively unique. For example, I may enclose those functions with a namespace mylib. Not the (demangled) symbols are all mylib::foo() (or mylib::util::foo()). They will be searched, but it is reasonable to assume they won't match anything outside of the mylib code.

In addition to the hassle, this has the detriment of still allowing external code to depend on this internal utility code - if it does so intentionally.

3
  • I don't think that you can truly hide some code from a static library in the general case. Unnamed namespaces have such an effect but limited to a single source file. You could obfuscate some names but that would be a hassle and objects would be still accessible anyway. Your solution based on nested namespaces is clean and commonly used for this purpose. But if confidentiality matters, then I think that you should release a dynamic (shared) library instead of a static one, so that you can explicitly choose what is exported.
    – luciole75w
    Commented Feb 3, 2020 at 17:29
  • @luciole75w: It's not about confidentiality. That is, I don't mind that a forensic examination of the library finds everything. Can you develop your suggestion regarding a dynamic library into an answer?
    – einpoklum
    Commented Feb 3, 2020 at 17:51
  • By confidentiality I was more thinking about access restriction to prevent an external application from linking with your private utils. Well the way to create/use a dynamic (linked) library and expose symbols depends on your compilation tools. With MSVC you can declare variables/functions/types with __declspec(dllexport) to expose them (or list them in a separate file) then the linker will generate an import library to easily link your binaries with. Wih GCC you would use __attribute__((visibility("..."))) but I have not done that for a long time.
    – luciole75w
    Commented Feb 3, 2020 at 19:03

Not the answer you're looking for? Browse other questions tagged or ask your own question.