Maven project with native dependency and copying files - dll

I have the following scenario:
mylib is a library (for which I have the sources, so I'd like to put them into a Maven project mylib:mylib for example). This library has a jar dependency for which I only have the jar, and it is not to be found in the Maven repository (and I do NOT want to install it there either). To make it compile, something like this would work: add the jar file to the mylib project in a "lib" folder, e.g. "lib/thirdpartylib.jar" and in mylib's pom.xml, add a dependency with self-chosen group/artifact/version and a "<scope>system</scope><systemPath>${project.basedir}/lib/thirdpartylib.jar</systemPath>" entry. The mylib project will compile fine.
Note that mylib also has a runtime dependency to a dll file, say thirdparty.dll. But for compilation this is not important.
However, now what I am wondering how to achieve the following:
Any other projects, e.g. project "X", that uses mylib, will need the
- mylib.jar
- thirdpartylib.jar
- thirdpartylib.dll
,
and it'll have to set the java.library.path to the directory (e.g. ".") such that the thirdparty jar and dll are found by the executing VM.
My concern is this: I would like the thirdparty jar/dll things to be the responsibility of the mylib project. I.e. I want to define the knowledge, that you need to copy the thirdparty jar and dll to the target folder and that java.library.path refers to them, to be part of the mylib project (the mylib pom knows how the thing is to be used in other projects). Yet, I want this knowledge (i.e. copy instructions, regardless how they are exactly done in Maven) to be transitively handed over to any other project using mylib, like X for example. Is that somehow possible?
[My hack solution for now would be that I have a copy of the thirdparty things in X, but even then I dunno how to copy/deal with the dll file, so I'd have to write a readme saying that the dll file has to be copied to the bin folder of the executing VM).
Any suggestions are appreciated!

The base idea is the following:
Maven is good in handling with one result per Maven POM.
It is possible to have libraries and dependencies to these libraries in your local repositories only.
So you have to do the following steps:
Define for the additional library a separate project (or a module in your project) and define the library as the result.
Change your POM so that this POM has now a dependency to the new project.
Do the same steps for your DLL (see the post Managing DLL dependencies with Maven) how to do that).
Deploy your additional library and your DLL to your local repository.
Now you should be able to use Maven for the build process again, and by using additional plugins like the maven-assembly-plugin, you are able to pack all together.

Related

Maintaining multiple projects which consume conan packages

Background:
I have a Visual Studio solution(s) with multiple (50+) projects (libraries static/dynamic and final executables). There is internal Visual Studio reference mechanism used to comsume required libraries for particular executables. Of course each project uses external packages, there are "duplicates" like boost, gtest, there are also some "unique" references for only one or few projects.
What's more, libraries are used in other solutions (project sharing) to deploy other executables.
This is my general project structure:
MainDir
|
- DebugDlls (build output)
- Debug64Dlls (build output)
- ReleaseDlls (build output)
- Release64Dlls (build output)
- Libraries
|
- lib1
- lib2
- ...
- Executables
|
- exe1
- exe2
...
I'm about to migrate from NuGet to conan as a dependency manager for external libraries since there are more ready to use conan packages that NuGet one and it's cross-platform. I'd like to do it project by project, dependency by dependency.
One global conan file to rule them all is not an option since each library has to be as standalone as possible so I'm able to simply grab one and use for new executable. What's more it would be impossible to track dependencies of particular library or executable.
My idea is to put a separate conanfile in each project and define dependencies.
Here is the first issue: I need some global/automatic management of common libraries like boost to not mix versions/variants and spare some time on version updates.
this one may be handled by a global file which defines reusable depndencies
is there something ready to use in conan, like template?
Second issue is to copy dlls from dependencies into proper build output so I'm able to execute the binaries.
this one should be fixable also by some global file with proper defines.
Third one is to execute conan install in each project
once again, a hand crafted script will do the job.
I was digging across the conan documentation but it's not very well organized and I was unable to find proper solution in my case. Maybe I missed something?
What would be the best approach here? Is there any build in conan mechanism for that (like CMake add_subdirectory). I would not like to reinvent the well if one already exists :)
I'm about to use conan 1.x

How do I specify a specific CMake target as a dependency?

Our CMake project, hosted on GitHub, has a CMake git submodule as a dependency. The file structure, then, is roughly:
project/
CMakeLists.txt
extern/
big_lib/
CMakeLists.txt
include/
*.hpp
static/
CMakeLists.txt
shared/
CMakeLists.txt
We have authorship of both project and big_lib.
The top level CMakeLists.txt for project includes something like:
add_subdirectory(${PROJECT_SOURCE_DIR}/extern/big_lib)
target_link_libraries(${PROJECT_NAME} big_lib::static)
big_lib::static is a library we don't install/publish; it's not specified as such in the big_lib configuration, it's for internal consumption only - namely for tests. We deliver a client facing shared library, but the shared library is not appropriate for project.
This is why ExternalProject_Add may not be the most appropriate solution for satisfying our dependency - as it is my understanding installing the dependency in the build directory won't install the specific build target we need. Also, I haven't had luck getting it to work yet.
What I've also noticed is that we're building all targets in big_lib, of which there are hundreds - mostly tests, and that shared library I don't want or need. I suspect this is because we're including the entire library from it's base directory.
I've tried:
add_subdirectory(${PROJECT_SOURCE_DIR}/extern/big_lib/static)
But it seems there's configuration from the big_lib base directory that now goes unspecified, which is why I'm including the base directory in project instead of this.
So my questions are:
Is there a better way to specify the static build target so only that gets built?
Is there a better way to organize the configuration of big_lib so I can add only the static library as the dependency folder, and not duplicate configuration from the base directory between static and shared?
What options am I not aware of? Maybe I should use ExternalProject_Add and specify some sort of custom build command where I issue just the static lib as the build target and install target, and then link against that artifact?

How to include external libraries in CMakeLists?

I have been trying to build my project with CMakeLists for a couple of days now with some success but I'm not sure on what it is exactly that I am doing.
I am currently using 5 external libraries. (Assimp, glew, glfw, glm, DevIL)
And my main platform is windows but platform independence is a big plus.
So the question I have is how to proceed when I want to include an external library to my project?
This is what I think I know so far.
(1) If you are "lucky" you can just use find_library and link it with target_link_libraries you are good to go.
(2) Since glm is a header only library, all I need is an include_directories.
(3) If the external library has its own CMakeLists, you do add_subdirectory and set include_directories to where the header files are.
This is what I know I don't understand.
(4) If the external library has .h files and .cpp files but no CMakeLists. How do I include (and build?) this library?
(5) (This is the most important question for me!) If the external library has .h files and either .lib or .dll files, how do I include this library? In both cases! (lib/dll)
Thanks in advance for any and all replies!
Best regards
Edvin
If you want to do the quick-and-dirty way you can just
create a super-repo with all your dependencies (or alternatively, write a script that downloads or clones them)
write a shell script that builds all the source-only dependencies
hardcode the include dirs, libraries and compile flags of the dependencies into the CMakeLists.txt of you main project (well, relative to super-repo root)
build the dependencies before you configure your main project
If a dependency has no CMakeLists.txt or any other build script suitable for your system, you need to find or write one.
If you want to do it elegantly and reusable you need to study the topics of CMake config-modules. For a quick introduction please check out this Stackoverflow answer: How to use CMake to find and link to a library using install-export and find_package?
You will need to write config-modules for the dependencies (or find a fork which has it). Your main project will contain only a list of find_package commands and you list your dependencies with the target_link_libraries command and all other details will be taken care by the config modules.
Generally you don't need to include third-party projects directly into your main project's CMakeLists (add_subdirectory or ExternalProject_add) since you will not be working on them so they will not change. There's no need to clutter your IDE workspace with them. It's best to download/clone/build/install them with a separate script before you configure your main project.

In CMake, is it possible to build a dependency imported from a build tree?

I am trying to use the CMake feature for exporting/importing targets from a build tree (see this wiki page). I have this dependency library:
add_library(dependency SHARED dependency.cpp)
export(TARGETS dependency FILE dependency-targets.cmake)
And an executable uses this library in another project:
include(${DEPENDENCY_PATH}/dependency-targets.cmake)
add_executable(main-app main.cpp)
target_link_libraries(main-app dependency)
This works fine. While I do understand that this export/import mechanism "only" provide a convenient way to reference external binaries, I am wondering whether dependency could be compiled when running make in main-app? Either using the import mechanism (which I doubt) or using another one ?
You could look into the "superbuild" pattern and ExternalProject.
The gist of the idea is that you set up one "superbuild" project which will use just ExternalProject_Add() commands; this will set up your real project and all its dependencies.

CMake: automatically find target dependencies in other CMake projects

If we have a case of highly decentralized development environment, where there are many repositories and projects, is there an existing functionality in CMake that automatically finds dependencies between targets without a top level CMake file?
The workflow is something like this, you specify a directory and all targets are default-configured in the given tree. Then you can go and build any of the projects. I am looking for a behavior similar to that when you build the Android OS.
There is no build-time dependency tracking in CMake across different projects. For this case you need to have a project on the top-level which adds all the subdirectories, so that the target names are available inside a single CMake project.
I am aware of one helper script around CMake which provides the required inter-project dependencies: https://github.com/aldebaran/qibuild
I would say that is getting close to a mature code base. However, it requires additional descriptor files for each project. Might be worth to have a look at it.