Can anybody suggest how to link shared libraries using SCons in this specific case.
I have 2 folder locations currently:
slib/ which contains only static libraries
dlib/ which contains only dynamic libraries
I can only add the prebuilt libraries to slib folder.
dlib folder is reserved for the dynamic libraries i create from source code.
My executable always links against this dlib folder.
Now in my case, I want to add some shared libraries (not built by me) into slib folder but I want those libraries to land in dlib folder so that my executable finds it when linking. In short i want my application (requiring those shared libraries) to use one folder when compiling and different folder when running.
Is there a way in SCons I can regenerate those libraries in a different folder ?
I am not allowed to manually copy from source to destination nor i can use
InstallAs( target = 'XYZ/dlib', source = 'ABC/slib' )
Related
We have a big project with many modules (shared libs). They have no static dependencies and work more like plugins. We want the build system to be able to use find_package(modA) when building a specific executable (exeA). We also don't want the project files generated to include every module (which will be hard to handle in VisualStudio etc), so it should just include (add_library) the modules needed for the executable built by a specific CMakeLists.txt (exeA).
One way to do this would be to use a helper function to find all Config.cmake files from the project root folder and either add them to CMAKE_PREFIX_PATH or generate _ROOT variables. Then the executable CMakeLists.txt could just do find_package(modX) on any dependencies.
Q: Is there any way to locate all *Config.cmake files in a folder recursively and add them to CMAKE_PREFIX_PATH or _ROOT? Or any helper (except file(GLOB_RECURSE)) that could help in locating these paths that could be used in a more specific helper macro.
I'm trying to move my project to CMake, and at the same time have some optimization on the compilation process.
Here's the deal:
I have several subdirs that are (have to be) each compiled into a static library (this works).
I want to gather all the object files from each subdir into another bigger, complete, static library.
It looks like this:
.
libBig.a # made from object from subdir1 and subdir2
subdir1/
src/
libSubdir1.a
subdir2/
src/
libSubdir2.a
Today, I managed to use a global variable in which every subdir CMakeLists.txt will append its own source files. I use this variable as a "source" input in my big library:
# the big library depends on all the source files
# ${all_src} is automatically filled with each subdir's cpp file
get_property( BigLib_src GLOBAL PROPERTY all_src)
add_library( Big STATIC ${BigLib_src}) # recompiles all the sources
Now, this works, not too bad, but the thing is, all my source files get compiled twice: once for the subdir library, and once for the big library.
CMake seems to forget that it has already built them.
I have to keep the subdir libraries and ar can't merge two static libraries.
Do you know how to do that?
You can use the new OBJECT library feature introduced in CMake 2.8.8. The idea is explained here. Basically, the OBJECT library is a similar concept to the convenience library known from Autotools to group object files.
Check the complete CMake OBJECT library tutorial.
As of CMake 2.8.8, you can do this using the OBJECT library type. See mloksot's answer. The old situation was that each target had its own directory and CMake would build every dependent object for every target. This guards against a case where one source file could be used multiple times with different CFLAGS. (Note that by default CMake is more conservative than automake here: automake will stop reusing object files for different targets only if the targets are built with different CFLAGS (and probably CPPFLAGS, too).
I'm using a compiled library that I made, libexp.a. (Was compiled with PIC so its good for this use case).
I want to use it statically in my shared library and I can do that via Mixing static libraries and shared libraries.
So now I'm trying to get that working with CMake, my libexp.a is in the root directory and I do:
find_library(EXP NAMES exp PATHS ${PROJECT_SOURCE_DIR} NO_DEFAULT_PATH)
Then using it in target_link_libraries via ${EXP}, but during link time I still get a linking error of couldn't find -lexp. What is the right way to get this done? Using over 3.6
I have a problem building multiple Fortran-90+ executable targets using CMake, when I use Fortran modules that are shared by all executables, and build in parallel using make -j. The issue seems to be that the compiled object files are placed in different subdirectories for each target, CMakeFiles/targetName.dir/src/file.f90.o, while the module files are placed in the same directory for every target (I can change this directory by setting Fortran_MODULE_DIRECTORY, but it will still be the same dir for all module files). The problem is then that all targets start writing these module files in parallel, and I get a
Fatal Error: Can't rename module file 'module.mod0' to 'module.mod': No such file or directory
when using gfortran (which apparently creates a .mod0 file and then renames it to .mod). The problem does not arise when I issue make without the -j option (serial build).
I can see two solutions, but I don't know how to implement them. Firstly, put the object files for all targets in the same directory rather than target-specific directories. This may be the preferred option, since I won't have to compile the shared source files N times for N targets. The make process will then recognise that the object files exist, and not compile the corresponding source files again, hence not touching the .mod(0) files again (I may need to make all following targets depend on the first).
The second solution would be to put the .mod(0) files in the target-specific directories, so that they are not overwritten or removed by the other targets. This would solve my problem, even though it would still involve more compiling than necessary. I have no idea how to accomplish either option, so any hint there or alternative solution is welcome.
The answer I was looking for was provided in the comments to the question by #RaulLaasner:
I would create an additional target in the form of a core library of the relevant source files, which can then be linked to all executables. This should work in parallel. The mod files can still be in put into a single directory.
I used add_library() and target_link_libraries() to achieve this.
Note that e.g. Gentoo ebuild scripts add --as-needed to the linker, which may cause undefined references in your core library when you link it and external libraries to form the executable. To prevent this, make sure you link the external libraries to your core library first. To this end, my CMakeListst.txt contains:
add_library( "Core" STATIC src/functions.f90 src/routines.f90 ) # creates libCore.a
target_link_libraries( Core ${EXTERNAL_LIBRARIES} ) # link external libraries to libCore.a
...
add_executable( myProgram1 src/myProgram1.f90 ) # creates the first executable
target_link_libraries( myProgram1 Core ) # links libCore.a to myProgram1
The last two lines can be repeated to build the other executables (e.g. using foreach()).
I'm writing a small library.
I'd like to build it as shared library and generate "MyLibraryConfig.cmake" file which then can be used by my other projects to find my library.
The only problem I have is to figure out the name/path to file which is used for linking under Windows - there are two files being generated: mylibrary.dll and mylibrary.dll.a.
So I'd like to generate MyLibraryConfig.cmake file with something like:
"set(MYLIBRARY_LIBRARIES /blah/blah/mylibrary.dll.a)"
so then MYLIBRARY_LIBRARIES can be used with target_link_libraries for my other projects.
How can I get name for this linkable file? I'd be nice if the solution was platform independed (returning .so wile on Linux and .dll.a on Windows)
thanks in advance
If you're planning on making your library available to your other projects without installing it then you want the CMake command export. For example:
export(TARGETS MyLib FILE ${CMAKE_SOURCE_DIR}/MyLibraryConfig.cmake)
This creates the file MyLibraryConfig.cmake in the same directory as your top-level CMakeLists.txt, and can just be included in other CMake projects.
If you're planning on installing your library, then you want to make use of install(EXPORT ...) instead:
install(TARGETS MyLib EXPORT MyLibraryConfig
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib/static)
install(EXPORT MyLibraryConfig DESTINATION cmake)
This will install the file MyLibraryConfig.cmake to <install path>/cmake, and can then be included by other projects.