I've tried to add biicode support to the the testing library Catch and had some problems with external dependencies related to Objective-C and Microsoft Foundation Classes (MFC).
The following is printed if running bii deps:
florianwolters/catch depends on:
system:
algorithm
assert.h
cmath
cstddef
cstdio
cstring
fstream
iomanip
iostream
iterator
limits
map
memory
ostream
set
sstream
stdbool.h
stdexcept
stdint.h
stdlib.h
streambuf
string
sys/time.h
sys/types.h
unistd.h
vector
windows.h
unresolved:
AfxWin.h
Foundation/Foundation.h
objc/runtime.h
sys/sysctl.h
The three files sys/sysctl.h, objc/runtime.h and Foundation/Foundation.h are related to iOS development in Objective-C. The file AfxWin.h is part of the C++ library Microsoft Foundation Classes (MFC) from Microsoft. The biicode block I've created is florianwolters/catch (for further information).
So the question is: How-to deal with such dependencies? It does not make sense to upload source code owned by Apple or Microsoft (it may even be illegal) to bicode, though I haven't checked the licenses yet.
Is the "proper" or recommended way to simply ignore such unresolved issues?
EDIT 2015-01-11:
I've written a blog post about the process here. Please let me know, if I did any mistakes or if you have any suggestions for improving the workflow.
Yes, at the moment it is the proper way. Biicode has pre-defined some system headers, the basic ones for Win and Nix platform, but not all of them. Typically OSX or other specific headers as MFC will not be found in biicode and then will be marked as unresolved.
This is not a problem at all. The same happens for your own libraries. If you wan to use any of your system-installed libraries, you can do very easily as usual (in CMake with Finders, or Imported targets). Biicode will mark included headers for that library as unresolved, which is the way to indicate that it is not managed by biicode. As long as those headers are present in your machine, everything will work fine.
Related
I want to add a smoothing function to my C++ project so I'm trying to use the smooth_mesh() function in the CGAL library. This function requires ceres-solver to work (and glog and Eigen) so I included it in an include folder in my project.
My problem is that when I try to launch a CGAL::Polygon_mesh_processing::smooth_mesh(), it returns an error (even though everything compiles properly):
Area-based smoothing requires the Ceres Library, which is not available.
The full way I use the function is the following:
CGAL::Polygon_mesh_processing::smooth_mesh(mesh,
CGAL::Polygon_mesh_processing::parameters::number_of_iterations(nb_iterations)
.use_area_smoothing(true)
.use_safety_constraints(false)
.edge_is_constrained_map(eif));
There is a very similar question on stack but the given solution did not help me to solve my problem. The answer directed me to use #define CGAL_PMP_USE_CERES_SOLVER but even with that the error is still happening.
It also mentions Cmake but I haven't built my project nor the libraries with CMake because CGAL instructions use vcpkg so I'm guessing that it may be where the problem comes from considering most ceres doc I found use Cmake. But instructions to link ceres and cgal using Cmake are pretty hard to find and/or not very clear (and I'm also very new to Cmake so that's not helping...).
I have tried to add the library manually to my project settings (I'm using Visual Studio on Windows), add some #include linking to ceres in some cgal files but nothing seems to be working.
I'm hoping someone here has run into this problem and managed to solve it.
If you can help me, thank you in advance!
I'm trying to link my project to a external library that I also developed in which also also use CMake to build. When I try to find RelWithDebInfo or MinSizeRel like this:
FIND_LIBRARY(PCM_LIBRARY_DEBUG pcm
PATHS #CMAKE_LIBRARY_OUTPUT_DIRECTORY#
#CMAKE_LIBRARY_OUTPUT_DIRECTORY#/Debug
NO_DEFAULT_PATH
)
FIND_LIBRARY(PCM_LIBRARY_RELEASE pcm
PATHS #CMAKE_LIBRARY_OUTPUT_DIRECTORY#
#CMAKE_LIBRARY_OUTPUT_DIRECTORY#/Release
#CMAKE_LIBRARY_OUTPUT_DIRECTORY#/MinSizeRel
#CMAKE_LIBRARY_OUTPUT_DIRECTORY#/RelWithDebInfo
NO_DEFAULT_PATH
)
SET(PCM_LIBRARIES debug ${PCM_LIBRARY_DEBUG} optimized ${PCM_LIBRARY_RELEASE})
It does not search in ather directories that are not Release or Debug. I also tried creating PCM_LIBRARY_RELWITHDEBINFO and PCM_LIBRARY_MINSIZEREL but the same thing happens because there is only debug and optimized prefixes in SET. Anyone knows how can I link the correct libraries?
This is unfortunately one of the shortcomings of using find_library. There is no easy way around this without introducing tons of boilerplate code.
The problem here is that when passing files as dependencies to target_link_libraries, you can only distinguish between debug and optimized. If you need more fine-grained control, you will have to manipulate the respective target properties like LINK_INTERFACE_LIBRARIES directly. This is not only quite cumbersome, it also requires detailed knowledge about the inner workings of CMake's property system.
Fortunately, there is another way: The aforementioned limitation only applies when specifying dependencies via filenames. When specifying them as targets, this problem does not occur. The most obvious example is if a library and the executable that depends on it are built from the same source:
add_library(foo_lib some_files.cpp)
add_executable(bar_exe more_files.cpp)
target_link_libraries(bar_exe PUBLIC foo_lib)
This 'just works'. The correct library will be chosen for each build configuration. Things get a little more complicated if the library and the executable live in different independent projects. In that case the library has to provide a configure file with an exported target in addition to the binary files.
Instead of calling find_library to locate the binaries, the dependent executable now just loads that config file and can then use the imported target as if it was a target from the same project.
Many modern libraries already use this approach instead of the classical find_library technique (Qt5 is a prominent example). So if you are at liberty to change the CMakeLists of your dependency and you do not need to support very old CMake versions (<2.6), this is probably the way to go.
I am using the managed make functionality of Eclipse CDT. Creating the project using dynamic only libraries is working as expected. But the boost_unit_test_framework should be linked statically, because it contains the main function. On the command line it is not a problem to link to dynamic and static libraries in a mixture. So this is a working example:
g++ -L../Debug -L../boost/lib -o "Test" ./Test.o -ldynLib -Wl,-Bstatic -lboost_unit_test_framework -Wl,-Bdynamic
The dynlib and the standard libraries like libc are linked dynamically and the boost_unit_test_framework is linked statically. BUT how can I enter this information in the Settings of the Project? I can not see any way.
It may be possible to flag this library in every project for static linking, for example in a global place. There is convention used by QNX ([manual]). It is possible to use LIBPREF_library and LIBPOST_library to add Options before or after the specified library.
Update:
I have still no clue how to solve the described problem. But in the meantime I have switched my build system from Managed Make to CMake. And additionally I am now using the Qt Creator because it is able to index boost and does not freeze the UI while updating some internal structures ...
[manual] http://www.qnx.com/developers/docs/6.3.0SP3/neutrino/prog/make_convent.html#USEMAC
I don't think you need to specify the type of linking. Dynamic libraries can't be linked statically, and vice versa. On one of my projects, under Project Properties -> C/C++ Build -> Settings, I have both static and dynamic libraries listed under Libraries. It seems to work out what type they are and link fine either way.
Dynalic libraries goes in : Linker/Libraries/Libraries (-l)
Static libraries goes in : Linker/miscelanous/Other files and objects
My C++ compiler creates "dylib" files which contain dynamic libraries. Whats the difference between .dylib and .so files?
And what is the difference between files in Mach-O format and files in an ELF format? I have to build files for later use under iOS (static libraries only/Mach-O) and Android (ELF).
Thanx!
I found that:
One Mach-O feature that hits many people by surprise is the strict
distinction between shared libraries and dynamically loadable modules.
On ELF systems both are the same; any piece of shared code can be used
as a library and for dynamic loading. Use otool -hv some_file to see
the filetype of some_file.
Mach-O shared libraries have the file type MH_DYLIB and carry the
extension .dylib. They can be linked against with the usual static
linker flags, e.g. -lfoo for libfoo.dylib. However, they can not be
loaded as a module. (Side note: Shared libraries can be loaded
dynamically through an API. However, that API is different from the
API for bundles and the semantics make it useless for an dlopen()
emulation. Most notably, shared libraries can not be unloaded.) [This
is no longer true—you can use dlopen() with both dylibs and bundles.
However, dylibs still can't be unloaded.]
Loadable modules are called "bundles" in Mach-O speak. They have the
file type MH_BUNDLE. Since no component involved cares about it, they
can carry any extension. The extension .bundle is recommended by
Apple, but most ported software uses .so for the sake of
compatibility. Bundles can be dynamically loaded and unloaded via dyld
APIs, and there is a wrapper that emulates dlopen() on top of that
API. [dlopen is now the preferred API.] It is not possible to link
against bundles as if they were shared libraries. However, it is
possible that a bundle is linked against real shared libraries; those
will be loaded automatically when the bundle is loaded.
To compile a normal shared library on OS X, you should use -dynamiclib
and the extension .dylib. -fPIC is the default.
The title mostly covers it, what is the difference between a module and a shared library? I just found this distinction in CMake's add_library command, where they say:
SHARED libraries are linked dynamically and loaded at runtime. MODULE libraries are plugins that are not linked into other targets but may be loaded dynamically at runtime using dlopen-like functionality.
But I can load a shared object using dlopen(), can't I?
The difference is that you can link to a SHARED library with the linker, but you cannot link to a MODULE with the linker. On some platforms.
So... to be fully cross-platform and work everywhere CMake works, you should never do this:
# This is a big NO-NO:
add_library(mylib MODULE ${srcs})
target_link_libraries(myexe mylib)
To be fair, on Windows, they're both just dlls, and so this code might actually work. But when you take it to a platform where it's impossible to link to the MODULE, you'll encounter an error.
Bottom line: if you need to link to the library, use SHARED. If you are guaranteed that the library will only be loaded dynamically, then it's safe to use a MODULE. (And perhaps even preferable to help detect if somebody does try to link to it...)
I think the distinction being made is that shared libraries are specified by the developer at compile-time and must be present for the application to run, even though their methods are loaded at runtime. A module, i.e. plugin, adds additional support at runtime but isn't required. Yes, you can dlopen() a shared library but in that case it would not have been specified as a required part of the program and functions instead as a module.
Another difference is in how ..._OUTPUT_DIRECTORY and ..._OUTPUT_NAME are handled:
Module libraries are always treated as library targets. For non-DLL platforms shared libraries are treated as library targets. For DLL platforms the DLL part of a shared library is treated as a runtime target and the corresponding import library is treated as an archive target. All Windows-based systems including Cygwin are DLL platforms.
For example, this means that if you compile a SHARED library on Windows, LIBRARY_OUTPUT_DIRECTORY will be ignored, because it's looking at ARCHIVE_OUTPUT_DIRECTORY and RUNTIME_OUTPUT_DIRECTORY instead.