Config.cmake file for custom made shared libraries - cmake

I have this project that I have done for experimentation with Qt and shared libraries. This is basically a couple of Qt Widgets from the tutorials for Qt and what I think is the right CMakeLists configuration so a MylibConfig.cmake is automatically generated from a MylibConfig.cmake.in to share the library. The problem is that I don't want the end user to add the dependencies of my library to its own CMakeLists.txt. This is, in my case, the library depends on Qt4, but I want that the end user to not have to do find_package(Qt 4 REQUIRED). Imagine that I want to provide an enclosed functionality to someone that does not need or want to know about what my library is built on. Is there a way in the automatic generation of the MylibConfig.cmake that it automatically finds all necessary packages or is the only option to add the fin package manually in the MylibConfig.cmake.in?
Thank you very much.

In fact, both mentioned projects do find of dependencies from their *Config.cmake files. And nowadays that is the only option -- CMake can't help you to do it "automatically".
So, some way or another, your config module should do the same.
The easy way is to add find_dependency() calls (cuz you know exactly what other packages, your project is based on).
A little bit harder is to do it "automatically" (writing your own helper function) -- for example by inspecting properties of your target(s), "searching" where all that libraries come from and finally generating find_dependency() calls anyway.

Related

In cmake, what is a "project"?

This question is about the project command and, by extension, what the concept of a project means in cmake. I genuinely don't understand what a project is, and how it differs from a target (which I do understand, I think).
I had a look at the cmake documentation for the project command, and it says that the project command does this:
Set a name, version, and enable languages for the entire project.
It should go without saying that using the word project to define project is less than helpful.
Nowhere on the page does it seem to explain what a project actually is (it goes through some of the things the command does, but doesn't say whether that list is exclusive or not). The cmake.org examples take us through a basic build setup, and while it uses the project keyword it also doesn't explain what it does or means, at least not as far as I can tell.
What is a project? And what does the project command do?
A project logically groups a number of targets (that is, libraries, executables and custom build steps) into a self-contained collection that can be built on its own.
In practice that means, if you have a project command in a CMakeLists.txt, you should be able to run CMake from that file and the generator should produce something that is buildable. In most codebases, you will only have a single project per build.
Note however that you may nest multiple projects. A top-level project may include a subdirectory which is in turn another self-contained project. In this case, the project command introduces additional scoping for certain values. For example, the PROJECT_BINARY_DIR variable will always point to the root binary directory of the current project. Compare this with CMAKE_BINARY_DIR, which always points to the binary directory of the top-level project. Also note that certain generators may generate additional files for projects. For example, the Visual Studio generators will create a .sln solution file for each subproject.
Use sub-projects if your codebase is very complex and you need users to be able to build certain components in isolation. This gives you a very powerful mechanism for structuring the build system. Due to the increased coding and maintenance overhead required to make the several sub-projects truly self-contained, I would advise to only go down that road if you have a real use case for it. Splitting the codebase into different targets should always be the preferred mechanism for structuring the build, while sub-projects should be reserved for those rare cases where you really need to make a subset of targets self-contained.

Duplicate symbols (two projects in a workspace use the same code)

A is a module project. There are some test targets and the relevant reusable code is compiled in a separate (static library) target. A uses the third party Lumberjack logging library. The Lumberjack code was simply dropped into the project.
B is a different module project, but otherwise it has the same properties as A.
C is the main project. It depends on A and B. It links the libraries of A and B.
Compiling C will result in duplicate Lumberjack symbols.
How can I have multiple separate module projects so that...
they don't know of each other,
use the same third party code,
can be compiled and tested on their own,
included in a main project without duplicate issues?
So, to elaborate on sergio's answer, I was able to succesfully build a test setup as follows.
I included the Lumberjack code in a separate project that builds Lumberjack as a static library.
I created a new project ProjectA with a static library target ModuleA and a test app target DemoA. I copied the Lumberjack project folder into the project folder of ProjectA and then added it as a subproject. I didn't make ModuleA dependent on Lumberjack or link Lumberjack in ModuleA. Instead, I made DemoA dependent on both and link both libraries. This way, I am able to compile the test target, but the library target doesn't include Lumberjack.
I created a second project ProjectB with the analogue setup as ProjectA.
In the main project, I included ProjectA, ProjectB and Lumberjack as subprojects. Unfortunately this will make Lumberjack included 3 times in the main project, which is a little bit inconvenient and ugly (for instance when selecting dependent targets, you can't really tell which one is which).
Finally, I made the main project's target dependent on Lumberjack, ModuleA and ModuleB and link all three libraries. Now, the main project can compile without duplicate symbol error and the submodules can also be compiled and tested on their own.
Since you are targeting OSX, the solution to your issue is building Lumberjack as a framework (as opposed to link the sources code in your A and B modules) and then using that framework wherever it is required (i.e., in any project using A or B modules).
Indeed, Lumberjack already includes a project that will build a Lumberjack.framework, check this: CocoaLumberjack/Xcode/LumberjackFramework/Desktop/Lumberjack.xcodeproj.
Elaborating more on this, you would define your A and B modules as you are doing now, but without dropping Lumberjack source code in it.
What you do instead is, whenever you want to use the A static library in a executable (say, your test target), you add the library to the target and also the lumberjack framework (exactly as you do with OSX SDK frameworks).
Adding the dynamic framework is just a different way to "drop the sources", if you want, but done properly.
When you want to use both A and B in a C project, you add both static libraries and your Lumberjack framework to C.
As you can see, this way of doing will comply with all your four requirements, at the expense of introducing one dependency: you need to make clear in your static libraries documentation that they depend on the Lumberjack framework. This is actually not a big issue, since the latter is available in its own project and any one will be able to build it on his own.
If you want to improve on the handling of this dependencies, cocoapods are the way to go (a cocoapod is a file associated to your library which describes its dependencies, so when you install your library, the cocoapods system will automatically install also the dependencies). But this is highly optional. One single dependency is not a big issue to document or comply with.
Hope this answers your question.
I hate to reference an existing answer but here's one solution that's cumbersome but works: What is the best way to solve an Objective-C namespace collision?
I have this same problem and I'm working on a better solution though. Another idea that might work but I'm not yet sure how to implement it I asked here: Selectively loading classes in Objective-C
A third idea I had because of something someone said on my question was to wrap one of the libraries in a framework and create functions that reference the functions you need. Then load using something like #import <myFramework/MFMyAliases.h>
Have you tried looking at the libraries with ar? If you are very lucky, running for example
ar -t libA.a
gives you a list of files like
__.SYMDEF SORTED
Afile1.o
Afile2.o
Lumberjack1.o
Lumberjack2.o
Afile3.o
SomeOtherLibrary.o
where the Lumberjack files are clearly separable from the rest. Then, you can kick them out
with
a -d Lumberjack1.o Lumberjack2.o
and link C against this trimmed library while using the full library when testing A alone.
I was trying to achieve the same thing before few months and "Easy, Modular Code Sharing Across iPhone Apps: Static Libraries and Cross-Project References" article got all what i needed. please check it out if its useful.
Are A and B binaries?
If not you could simply uncheck the compile checkbox for all *.m files of one of the projects, so as to avoid building duplicate objects.
Also if you could use A and B thorough Cocoapods it would be best.
Try this.
It is sharing libraries/modules between different projects.

How do I link multiple libraries in a Firebreath plugin?

Does anyone know where I can find a Firebreath sample (either Mac OS X or Windows) that illustrates how to create a plugin that includes 1 or more other libraries (.DLLs or .SOs) that each rely on other sub-projects built as static libraries (LIBs)?
For example, let's say that the Firebreath plugin is called PluginA, and that PluginA calls methods from DLL_B and DLL_C. DLL_B and DLL_C are C++ projects. DLL_B calls methods from another project called LIB_D, and DLL_C calls methods from a project called DLL_E.
Therefore, the final package should contain the following files:
PluginA.dll
DLL_B.dll (which also incorporates LIB_D)
DLL_C.dll
DLL_E.dll
I am currently forced to dump all source files in the pluginA solution, but this is just a bottleneck (for example I cannot call libraries written in other languages, such as Objective-C on Mac OS X).
I tried following the samples on Firebreath, but couldn't get them to work, and I found no samples from other users that claimed they were able to get it to work. I tried using CMAKE, and also running the solutions directly from X-Code, but the end result was the same (received linking errors, after deployment DLL_C couldn't find DLL_E etc.)
Any help would be appreciated - thank you,
Mihnea
You're way overthinking this.
On windows:
DLLs don't depend on a static library because if they did it would have been compiled in when they were built.
DLLs that depend on another DLL generally just need that other DLL to be present in the same location or otherwise in the DLL search path.
Those two things taken into consideration, all you need to do is locate the .lib file that either is the static library or goes with the .dll and add a target_link_library call for each one. There is a page on firebreath.org that explains how to do this.
On linux it's about the same but using the normal rules for finding .so files.

Is it worth it to create static libraries for iOS?

There is code that I want to include in most of my projects. Things like AFNetworking, categories for CoreData and unit testing, etc.
It seems logical to include all of these in a static library, and then use it in each project. I've noticed though, that many third-party libraries (like AFNetworking, and it's predecessor ASIHTTP) are included in projects by copying over all of their source files and then manually linking the necessary libraries to the project target.
This seems to me like the easiest way. It took a fair amount of time to figure out how to include an existing static library into a project. Even after I knew how, it still seems like a pain to do it for every new project. Also, the header search paths that you specify are to a local directory with the static library's files. Wouldn't it be easier, and is there a way, to copy the static library's files into the project? This is the same idea as including the class files directly like most libraries seem to do already, but it would be more organized because everything would be lumped into one library project, instead of having class files everywhere and having to include every one of them.
Static libraries feel like they should be the right way to go. Make a library that can be used with all projects that includes classes that every project will need. Makes sense. I am just conflicted because it seems like the right way to go is to leave everything out of a 'formal' library, and just copy over all of the class files instead.
I guess I am just looking for what experienced developers find to be the best option.
I would be among the first to admit that the process of referencing a static library in Xcode is not entirely intuitive. However, using a static library is the best option, without a doubt.
The main reason is maintainability: when you copy source code of a library to many places, you must remember to update all of them to the latest code when you upgrade to the next version of the library. This may be a rather error-prone process, especially when the underlying library source changes significantly (e.g. new files are added, old files are renamed, etc.)
There's a halfway solution - make an XCode project that builds your static library from source and put that into a shared repository (ie.. git submodule etc) which is included from each project's main repository.
Each of your projects would include this submodule and project. Then they get the latest source code each time they pull that submodule. If you set this up as a build dependency it will build a static library the first time you build and then XCode is smart enough just to include it each subsequent build so you get the benefit of fast build times.
You also get the advantage of having the source right there for stepping though / debugging.
If it's in a separate XCode project and a new version of a library adds or removes a source file you would only need to change that shared project - all your individual projects wouldn't change at all.
What about using CocoaPods? This tool does exactly what you want in a declarative way: you have a file (Podfile) where you declare your dependencies, and the tool downloads all the dependencies and builds a static library that gets added to your project.
I would agree that static libraries feel like they might be the correct way to go for a number of reasons, but can also introduce some issues.
The positives would be creating an easy way to add a library to a project. Although not completely intuitive, it is rather trivial to add a static library to a project after one does it a few times. Add the files, add the search path, done. This could also be useful in certain source control situations. Also, updating a library may be easier.
I think the real problem here is for the open source community. By including, say AFNetworking, for example, as a static library, you lose all access to the implementation files. This is a great feature of including source rather than a library. It lets you change code to how you see fit, and hopefully give back.

Xcode search paths for public headers in dependencies

I am trying to clean up some of my projects, and one of the things that are puzzling me is how to deal with header files in static libraries that I have added as "project dependencies" (by adding the project file itself). The basic structure is like this:
MyProject.xcodeproj
Contrib
thirdPartyLibrary.xcodeproj
Classes
MyClass1.h
MyClass1.m
...
Now, the dependencies are all set up and built correctly, but how can I specify the public headers for "thirdPartyLibrary.xcodeproj" so that they are on the search path when building MyProject.xcodeproj. Right now, I have hard-coded the include directory in the thirdPartyLibrary.xcodeproj, but obviously this is clumsy and non-portable. I assume that, since the headers are public and already built to some temporary location in ~/Library (where the .a file goes as well), there is a neat way to reference this directory. Only.. how? An hour of Googling turned up blank, so any help is greatly appreciated!
If I understand correctly, I believe you want to add a path containing $(BUILT_PRODUCTS_DIR) to the HEADER_SEARCH_PATHS in your projects build settings.
As an example, I took an existing iOS project which contains a static library, which is included just in the way you describe, and set the libraries header files to public. I also noted that the PUBLIC_HEADERS_FOLDER_PATH for this project was set to "/usr/local/include" and these files are copied to $(BUILT_PRODUCTS_DIR)/usr/local/include when the parent project builds the dependent project. So, the solution was to add $(BUILT_PRODUCTS_DIR)/usr/local/include to HEADER_SEARCH_PATHS in my project's build settings.
HEADER_SEARCH_PATHS = $(BUILT_PRODUCTS_DIR)/usr/local/include
Your situation may be slightly different but the exact path your looking for can probably be found in Xcode's build settings. Also you may find it helpful to add a Run Script build phase to your target and note the values of various settings at build time with something like:
echo "BUILT_PRODUCTS_DIR " $BUILT_PRODUCTS_DIR
echo "HEADER_SEARCH_PATHS " $HEADER_SEARCH_PATHS
echo "PUBLIC_HEADERS_FOLDER_PATH " $PUBLIC_HEADERS_FOLDER_PATH
.
.
.
etc.
I think that your solution is sufficient and a generally accepted one. One alternative would be to have all header files located under an umbrella directory that can describe the interface to using the depended-on libraries and put that in your include path. I see this as being similar to /usr/include. Another alternative that I have never personally tried, but I think would work would be to create references to all the headers of thirdPartyLibrary from MyProject so that they appear to be members of the MyProject. You would do this by dragging them from some location into MyProject, and then deselecting the checkbox that says to copy them into the project's top level directory. From one perspective this seems feasible to me because it is as if you are explicitly declaring that your project depends on those specific classes, but it is not directly responsible for compiling them.
One of the things to be wary of when addressing this issue is depending on implementation-specific details of Xcode for locating libraries automatically. Doing so may seem innocuous in the meantime but the workflows that it uses to build projects are subject to change with updates and could potentially break your project in subtle and confusing ways. If they are not well-defined in some documentation, I would take any effect as being coincidental and not worth leveraging in your project when you can enforce the desired behavior by some other means. In the end, you may have to define a convention that you follow or find one that you adopt from someone else. By doing so, you can rest assured that if your solution is documented and reproducible, any developer (including yourself in the future) can pick it up and proceed without tripping over it, and that it will stand the testament of time.
The way we do it is to go into build target settings for the main project and add:
User Header Search Path = "Contrib"
and check that it searches recursively. We don't see performance problems with searching recursively even with many (10-15 in some projects) dependencies.