How to cleanup nix style cabal if soemthing is out of order? - cabal

Remember the old days before we had nix-style cabal.
When we got into cabal hell, we could delete the 2 directories
.cabal and .ghc and restart with clean cabal environnement.
Now I think, on one of my machines something went wrong and my nix-style
v2-cabal repository is out of order.
If I do cabal v2-install --dry-run directory I get:
Resolving dependencies...
cabal: Could not resolve dependencies:
[__0] next goal: directory (user goal)
[__0] rejecting: directory-1.3.4.0 (constraint from user target requires
==1.3.3.2)
[__0] trying: directory-1.3.3.2
[__1] next goal: ghc (user goal)
[__1] rejecting: ghc-8.6.5, ghc-8.6.4 (constraint from user target requires
==8.6.3)
[__1] rejecting: ghc-8.6.3/installed-8.6... (conflict: directory==1.3.3.2, ghc
=> directory==1.3.3.0/installed-1.3...)
[__1] rejecting: ghc-8.6.1, ghc-8.4.4, ghc-8.4.3, ghc-8.4.1, ghc-8.2.2,
ghc-8.2.1 (constraint from user target requires ==8.6.3)
[__1] fail (backjumping, conflict set: directory, ghc)
After searching the rest of the dependency tree exhaustively, these were the
goals I've had most trouble fulfilling: directory, ghc
The problem is with GHC-8.6.3.
On another machine, this works fine, therefore I think, something is wrong.
How can I fix this? Is it enough to delete the following directories?
~/.cabal/store/ghc-8.6.3
~/.cabal/lib/x86_64-linux-ghc-8.6.3
~/.cabal/share/x86_64-linux-ghc-8.6.3
~/.ghc/x86_64-linux-8.6.3
Are there any other directories / files, that I have to delete?
Is there something like a cabal v2-clean command?
I don't want to delete the installed packages of other GHC releases, therefore I don't want to delete the .cabal and .ghc directories totally.

Almost certainly the problem is you have a conflicting lib in your global ghc environment file: https://ghc.gitlab.haskell.org/ghc/doc/users_guide/packages.html#package-environments
You can clean entries out from that file by hand, or manage it with a tool such as https://github.com/phadej/cabal-env

Related

Shows Missing library : ff while building echidna using stack install

I am trying to build echidna using stack install.
https://github.com/crytic/echidna
I am continuously getting the missing library error while installing at a progress state of 171/178.
I believe it to be more of stack error than library error. Error shown is as follows
I have tried installing the library but not getting any C library of such sort.ye
SO, i've installed every library using
sudo apt-get install lib*ff*-dev
isn't working yet.
-- While building package hevm-0.31 using:
/home/aman/.stack/setup-exe-cache/x86_64-linux/Cabal-simple_mPHDZzAJ_2.2.0.1_ghc-8.4.3 --builddir=.stack-work/dist/x86_64-linux/Cabal-2.2.0.1 configure --with-ghc=/home/aman/.stack/programs/x86_64-linux/ghc-8.4.3/bin/ghc --with-ghc-pkg=/home/aman/.stack/programs/x86_64-linux/ghc-8.4.3/bin/ghc-pkg --user --package-db=clear --package-db=global --package-db=/home/aman/.stack/snapshots/x86_64-linux/lts-12.10/8.4.3/pkgdb --package-db=/home/aman/Desktop/new/echidna2/echidna/.stack-work/install/x86_64-linux/lts-12.10/8.4.3/pkgdb --libdir=/home/aman/Desktop/new/echidna2/echidna/.stack-work/install/x86_64-linux/lts-12.10/8.4.3/lib --bindir=/home/aman/Desktop/new/echidna2/echidna/.stack-work/install/x86_64-linux/lts-12.10/8.4.3/bin --datadir=/home/aman/Desktop/new/echidna2/echidna/.stack-work/install/x86_64-linux/lts-12.10/8.4.3/share --libexecdir=/home/aman/Desktop/new/echidna2/echidna/.stack-work/install/x86_64-linux/lts-12.10/8.4.3/libexec --sysconfdir=/home/aman/Desktop/new/echidna2/echidna/.stack-work/install/x86_64-linux/lts-12.10/8.4.3/etc --docdir=/home/aman/Desktop/new/echidna2/echidna/.stack-work/install/x86_64-linux/lts-12.10/8.4.3/doc/hevm-0.31 --htmldir=/home/aman/Desktop/new/echidna2/echidna/.stack-work/install/x86_64-linux/lts-12.10/8.4.3/doc/hevm-0.31 --haddockdir=/home/aman/Desktop/new/echidna2/echidna/.stack-work/install/x86_64-linux/lts-12.10/8.4.3/doc/hevm-0.31 --dependency=QuickCheck=QuickCheck-2.11.3-3XHQpBYb83U2mMvNz2AjQX --dependency=abstract-par=abstract-par-0.3.3-Ie3MD7O3orK6ZR8i7FuBEv --dependency=aeson=aeson-1.3.1.1-7JlrwYHW7OR9ca4RRZ9oOf --dependency=ansi-wl-pprint=ansi-wl-pprint-0.6.8.2-9fh9v74MJQDJeSHE7X3Co6 --dependency=async=async-2.2.1-7DQr5PBcpiwJNOuf7ZiSPa --dependency=base=base-4.11.1.0 --dependency=base16-bytestring=base16-bytestring-0.1.1.6-I0igvRcEwRNBMqqPC2yQBh --dependency=base64-bytestring=base64-bytestring-1.0.0.1-4OCIe2BZn8jKI191JIXI37 --dependency=binary=binary-0.8.5.1 --dependency=brick=brick-0.37.2-HmDqAExuwtV4o98FRmS9eK --dependency=bytestring=bytestring-0.10.8.2 --dependency=cereal=cereal-0.5.7.0-ILaYAmVTyR1IcEsGXXUCfI --dependency=containers=containers-0.5.11.0 --dependency=cryptonite=cryptonite-0.25-GgyZs9E1viv2owjaLxA3vq --dependency=data-dword=data-dword-0.3.1.2-CMzWV6RCGtK8L6wsVSErKS --dependency=deepseq=deepseq-1.4.3.0 --dependency=directory=directory-1.3.1.5 --dependency=fgl=fgl-5.6.0.0-E3fRSNebqkULRqplV3ljSc --dependency=filepath=filepath-1.4.2 --dependency=ghci-pretty=ghci-pretty-0.0.2-I5PJbL8ge6MChp3KxZbHqH --dependency=haskeline=haskeline-0.7.4.3-5EI2v7Zmtnz57a7mmnEGOS --dependency=lens=lens-4.16.1-B0f4CyKKTUGAKBzzY965AX --dependency=lens-aeson=lens-aeson-1.0.2-Jly9eqrxMbj6GutGwOKn69 --dependency=megaparsec=megaparsec-6.5.0-G48ltiRFbVUHATB1lTnNRx --dependency=memory=memory-0.14.16-GTCi0eCrvrnI3inLDBWVMK --dependency=monad-par=monad-par-0.3.4.8-Jjk0JT5qYVK4xEO13GFUu8 --dependency=mtl=mtl-2.2.2 --dependency=multiset=multiset-0.3.4.1-DOPR5uXspss8vZY4jdOdOo --dependency=operational=operational-0.2.3.5-4jEcCWo4nKu1T4LZlKqe58 --dependency=optparse-generic=optparse-generic-1.3.0-1jcIewFKPXBLcRetZisV2l --dependency=process=process-1.6.3.0 --dependency=quickcheck-text=quickcheck-text-0.1.2.1-2lR7Kay7WBV5AMKAdKDpZZ --dependency=regex-tdfa=regex-tdfa-1.2.3.1-9PkkapJrmiKFVG38JA02jN --dependency=restless-git=restless-git-0.7-83nBoDMPYLtJIx01bvXzKs --dependency=rosezipper=rosezipper-0.2-GAlMD5j8Qb83GzjCYQknnx --dependency=s-cargot=s-cargot-0.1.4.0-J9AhWfrUxDQ6YMTyzXkHth --dependency=scientific=scientific-0.3.6.2-5di0UflhS5I1xpiiCPzjKz --dependency=semver-range=semver-range-0.2.7-dBvW3ofcsgDQf0zazTsJd --dependency=temporary=temporary-1.3-5Z6bOFbSCb7VhnH5UnI2r --dependency=text=text-1.2.3.0 --dependency=text-format=text-format-0.3.2-Fd261TSu6ptAAzilVN6BFx --dependency=time=time-1.8.0.2 --dependency=transformers=transformers-0.5.5.0 --dependency=tree-view=tree-view-0.5-Kkrk0dCM0oj2Q4xwPbd7Gg --dependency=unordered-containers=unordered-containers-0.2.9.0-IkfpzvG0LzrHAbTzfMidvY --dependency=vector=vector-0.12.0.1-4awQG9XUvVEBfJgKGHBhOb --dependency=vty=vty-5.21-A2OCwk39Wv3J3RjR3BvHey --dependency=witherable=witherable-0.2-2RYbFmOnVolGAqiDDS1CLe --dependency=wreq=wreq-0.5.2.1-IjuXB0jwsxA7O3uIVjcJXu --extra-include-dirs=/home/aman/Downloads/Compressed/ff13c/source/ --extra-include-dirs=/usr/local/opt/readline/include --extra-lib-dirs=/usr/local/opt/readline/lib
Process exited with code: ExitFailure 1
Logs have been written to: /home/aman/Desktop/new/echidna2/echidna/.stack-work/logs/hevm-0.31.log
Configuring hevm-0.31...
Cabal-simple_mPHDZzAJ_2.2.0.1_ghc-8.4.3: Missing dependency on a foreign
library:
* Missing (or bad) C library: ff
This problem can usually be solved by installing the system package that
provides this library (you may need the "-dev" version). If the library is
already installed but in a non-standard location then you can use the flags
--extra-include-dirs= and --extra-lib-dirs= to specify where it is.If the
library file does exist, it may contain errors that are caught by the C
compiler at the preprocessing stage. In this case you can re-run configure
with the verbosity flag -v3 to see the error messages.
The stack install must find this library and end up successfully installing the library I'm using.
So, it is clear from the error provided above, that the installation was not able to find the libff file.
The best solution is to build the libff library manually and copy the required builds at the place it should be.
The best way to debug the problem is to look at the executed command closely and try to find the possible places where the libff should be...
Looking into the very 2nd error line, i.e. the complete command it was trying to execute
here, I sighted the following options being executed
--extra-include-dirs=/usr/local/opt/readline/include --extra-lib-dirs=/usr/local/opt/readline/lib
In order to solve this, I looked for the required libff library and cloned it from GitHub. I cloned the required dependencies and places them in the directory it should be.
https://github.com/scipr-lab/libff
I then followed the "Build guide" to build the required library.
Then with the superuser on, I created the directories, /usr/local/opt/readline/lib and /usr/local/opt/readline/include, and it was solved. And pasted the required builds in it.
Used stack install again, and it worked.
Note:
I thought many beginners may have similar problem while installing the required tools for their use. These small ideas may help them.

CMake: how to break a PRE_LINK infinite loop?

I'm trying to automatically label my application sign-on line with a build number. This application is a plain vanilla C one without graphic UI; it is intended for command line, therefore it is a "simple" one.
The sign-on id is located in a "template" source file which is customized by CMake with a configure_file() command. Recently, I fancied to include a build number in this sign-on id. Consequently, the customization can no longer be statically done at CMake time, but everytime make is invoked.
To achieve that, there are two possibilities in CMake:
add_custom_target(), but it is triggered even when nothing else changes in the source tree which does not reflect the state of the tree;
add_custom_command(), which can be triggered only when the application (target) needs to be linked again.
I opted for the second solution and did not succeed.
Here is an extract of my CMakeLists.txt, the sign-on id being in file ErrAux.c (template in PROJECT_SOURCE_DIR, configured in PROJECT_BINARY_DIR):
add_executable(anathem ... ${PROJECT_BINARY_DIR}/ErrAux.c ...)
add_custom_command(TARGET anathem PRE_LINK
COMMAND "${CMAKE_COMMAND}" "-DVERS=${PROJECT_VERSION}"
"-DSRC=${PROJECT_SOURCE_DIR}"
"-DDST=${PROJECT_BINARY_DIR}"
-P "${CMAKE_HOME_DIRECTORY}/BuildNumber.cmake"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Numbering build"
VERBATIM
)
This launches script BuildNumber.cmake just before the link step. It computes the next build number and customizes ErrAux.c with configure_file().
It works fine, except ...
It happens late in the make sequence and the update to ErrAux.c goes unnoticed. The sign-on id in the executable contains the previous build number.
Next time I run make, make notices the generated ErrAux.c is younger than its object module and causes it to be compiled again, which in turn causes a link which triggers a build number update. This happens even if no other file has changed and this loop can't be broken. This is clearly shown in the compiling log:
Scanning dependencies of target anathem
[ 13%] Building C object AnaThem/CMakeFiles/anathem.dir/ErrAux.c.o
[ 14%] Linking C executable anathem
Numbering build
3.0.0-45
[ 36%] Built target anathem
The crux seems to be that add_custom_command(TARGET ...) can't specify an output file like add_custom_command(OUTPUT ...) does. But this latter form can't be triggered in PRE_LINK mode.
As a workaround, I forced a compilation to "refresh" the object module with:
add_custom_command(TARGET anathem PRE_LINK
COMMAND "${CMAKE_COMMAND}" "-DVERS=${PROJECT_VERSION}"
"-DSRC=${PROJECT_SOURCE_DIR}"
"-DDST=${PROJECT_BINARY_DIR}"
-P "${CMAKE_HOME_DIRECTORY}/BuildNumber.cmake"
COMMAND echo "Numbering"
COMMAND echo "${CMAKE_C_COMPILER}" "\$(C_DEFINES)" "\$(C_INCLUDES)" "\$(C_FLAGS)" -c "${PROJECT_BINARY_DIR}/ErrAux.c"
COMMAND "${CMAKE_C_COMPILER}" "\$(C_DEFINES)" "\$(C_INCLUDES)" "\$(C_FLAGS)" -c "${PROJECT_BINARY_DIR}/ErrAux.c"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Numbering build"
VERBATIM
)
An explicit compilation is forced after sign-on id customization. It mimics what is found in the various Makefile's and my not be safe for production. It's a cheat trick on both CMake and make.
UPDATE: Option -c is required to postpone link step until the final application liniking process.
This addition creates havoc in the link, as shown by the log, where you see a double compilation (the standard make one and the add_custom_command() one):
Scanning dependencies of target anathem
[ 13%] Building C object AnaThem/CMakeFiles/anathem.dir/ErrAux.c.o
[ 14%] Linking C executable anathem
Numbering build
3.0.0-47
Numbering
/usr/bin/cc -DANA_DEBUG=1 -I/home/prog/projects/AnaLLysis/build/AnaThem -I/home/prog/projects/AnaLLysis/AnaThem -g /home/prog/projects/AnaLLysis/build/AnaThem/ErrAux.c
/usr/lib/gcc/x86_64-redhat-linux/6.3.1/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
AnaThem/CMakeFiles/anathem.dir/build.make:798: recipe for target 'AnaThem/anathem' failed
make[2]: *** [AnaThem/anathem] Error 1
If I force a full recompilation, to make sure all sources are compiled, *main.c* included, I get the same error on `main`.
The only logical explanation is my manual C invocation is faulty and somehow destroys vital information. I checked with *readelf* that `main` is still in the symbol table for *main.c.o* and that it is still taken into account by the link step (from file *link.txt*).
UPDATE: Even with the correct link, I'm still experiencing the infinite loop syndrom. The generated application still has its sign-on id lagging behind the actual build counter.
Can someone give me a clue for the right direction?
FYI I'm quite new to CMake, so I may do things really wrong. Don't hesitate to criticize my mistakes.
The key to the solution is to put the generated module where make expects to find it. CMake organizes the build tree in a non-trivial way.
The shortcomming in my added compilation in add_custom_command() was to believe that by default the binary will be stored in the "usual" CMake locations. Since I forge manually my compiler command, this is not the case.
I found the module in the source directory, which is a consequence of the WORKING_DIRECTORY option, with name ErrAux.o and not ErrAux.c.o.
To obtain the correct behavior, I force an output location with:
-o "${PROJECT_BINARY_DIR}/CMakeFiles/anathem.dir/ErrAux.c.o"
Now, when I run make again, nothing happens since nothing changed.
Side question
To make the solution portable (if needed), are there CMake variables for CMakeFiles and anathem.dir directories? Or in the latter case, for the current target as "anathem" as the target name in add_custom_command()?

BitBake: example not found in the base feeds

I have a BitBake recipe (example_0.1.bb) with a do_install task where I attempt to install a .so file:
do_install() {
install -d ${D}${libdir}
install -m 0644 ${S}/example.so ${D}${libdir}
}
FILES_${PN} += "${libdir}/example.so"
This fails during the build process and returns:
ERROR: example not found in the base feeds
However, if I add a test file to the package, both the .so file and the test file are added to the rootfs.
do_install() {
install -d ${D}${libdir}
install -m 0644 ${S}/example.so ${D}${libdir}
echo "bar" >> ${TOPDIR}/foo
install -m 0644 ${TOPDIR}/foo ${D}${libdir}
}
FILES_${PN} += "${libdir}/libceill.so"
FILES_${PN} += "${libdir}/foo"
How can I add only the .so file without the junk test file?
So you've got a library that is non-standard in that it's not installing a versioned library (libfoo.so.1.2.3, maybe symlinks such as libfoo.so.1 -> libfoo.so.1.2.3), and then an unversioned symlink for compilation time (libfoo.so -> libfoo.so.1). The default packaging rules assume standard libraries.
What's happening is that packages are populated by their order in PACKAGES, which has PN-dev before PN. FILES_PN-dev by default contains /usr/lib/lib*.so, and FILES_PN contains /usr/lib/lib*.so.. When you add /usr/lib/lib.so to FILES_PN what you want to happen isn't happening because PN-dev has already taken the files.
If your library doesn't come with any development files at all (e.g. no headers) then you can set FILES_${PN}-dev = "" to empty that package, and then your addition of lib*.so to FILES_${PN} will work as expected.
Yes, this is something that we should make easier (I've been thinking about a small class for libraries like this) and warn in sanity checks when it happens.
Oh and I'm surprised that the library ends up in the image in your second example, as example will contain /usr/lib/foo and example-dev will contains /usr/lib/libceill.so. Unless of course you've got dev-pkgs enabled, which will automatically install example-dev if you've got example in an image.
Add the line
FILES_SOLIBSDEV = ""
An explanation from the Yocto mailing list:
I had FILES_${PN} += “${libdir}/.so” in there and that didn't work.
Maybe it was because I was missing the FILES_SOLIBSDEV = “" you mentioned.
I'll play with it some more and see what happens. I first started out with
FILES_${PN} += “${libdir}/.so” and when that didn't work I tried other
things in the FILES_${PN} = line to try and get it picked up. When I
couldn't get any of it to work and then saw others (well, at least the link
I provided) were seeing the same thing I figured it was time to quit
spinning my wheels and consult the big guns :)
Heh :) The issue there is that the patterns are matched in the order of the
PACKAGES variable. The first package to include a file gets it, and
${PN}-dev is in PACKAGES before ${PN}. By emptying FILES_SOLIBSDEV, that’ll
remove the .so from FILES_${PN}-dev, letting the ${PN} package get it
instead.
Add the line:
FILES_${PN}_dev_remove="${FILES_SOLIBDEV} "
It will move out the package for development path.

Linking to Armadillo libraries with CMake

I am trying to install MLPack on windows 8.
I configure the CMakeLists.txt file with:
set(ARMADILLO_LIBRARY "C:\\Program Files (x86)\\armadillo\\lib")
set(ARMADILLO_INCLUDE_DIR "C:\\Program Files (x86)\\armadillo\\include")
Then when I ran CMake I had a whole series of warning like these ones:
WARNING: Target "mlpack" requests linking to directory "C:\Program Files (x86)\armadillo\lib". Targets may link only to libraries. CMake is dropping the item.
In \mlpack-1.0.4\src\mlpack directory I found another CMakeLists file with:
target_link_libraries(mlpack
${ARMADILLO_LIBRARIES}
${Boost_LIBRARIES}
${LIBXML2_LIBRARIES}
)
that I changed to (not sure if that was a good idea):
target_link_libraries(mlpack
${Boost_LIBRARIES}
)
link_directories(mlpack
${ARMADILLO_LIBRARIES}
${LIBXML2_LIBRARIES}
)
then CMake seems to be running smoothly:
-- Found Armadillo: C:\Program Files (x86)\armadillo\lib (found suitable version "3.800.2", minimum required is "2.4.2")
-- Found LibXml2: C:\cpp\libraries\libxml2-2.7.8.win32\lib (found suitable version "2.7.8", minimum required is "2.6.0")
-- Boost version: 1.53.0
-- Found the following Boost libraries:
-- program_options
-- unit_test_framework
-- Boost version: 1.53.0
-- Found the following Boost libraries:
-- random
-- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE)
-- Configuring done
-- Generating done
-- Build files have been written to: C:/cpp/libraries/mlpack-1.0.4
but now when running make I have tons of such errors :
Linking CXX executable ..\..\..\..\gmm.exe
CMakeFiles\gmm.dir/objects.a(gmm_main.cpp.obj):gmm_main.cpp:(.text+0xb9): undefined reference to `wrapper_dgemv_'
CMakeFiles\gmm.dir/objects.a(gmm_main.cpp.obj):gmm_main.cpp:(.text$_ZN4arma6auxlib10det_lapackIdEET_RKNS_3MatIS2_EEb[__ZN4arma6auxlib10det_lapackIdEET_RKNS_3MatIS2_EEb]+0x115): undefined reference to `wrapper_dgetrf_'
which after investigation seems to be related to Armadillo.
Any idea what is happening ? I guess I should use target_link_libraries for Armadillo but I am not sure how.
The issue is hopefully pretty easy to resolve. When you do this...
set(ARMADILLO_LIBRARY "C:\\Program Files (x86)\\armadillo\\lib")
set(ARMADILLO_INCLUDE_DIR "C:\\Program Files (x86)\\armadillo\\include")
you're effectively short-circuiting the find_package(Armadillo 2.4.2 REQUIRED) call, since it expects to have to do the work to find these paths. However, when find_package does the work, the variable ARMADILLO_LIBRARY gets set to the path to the library itself - not the path to the lib's directory.
So the problem boils down to setting ARMADILLO_LIBRARY to the path to the lib's directory rather than the lib itself. This ultimately yields a linker error since the target gmm (added in src\mlpack\methods\gmm\CMakeLists.txt) links to mlpack, and mlpack has been set to link to ${ARMADILLO_LIBRARIES}, which isn't set correctly.
It turns out that find_package(Armadillo ...) already checks in "$ENV{ProgramFiles}/Armadillo/lib" and "$ENV{ProgramFiles}/Armadillo/include", and I expect these resolve to "C:\\Program Files (x86)\\armadillo\\lib" and "C:\\Program Files (x86)\\armadillo\\include" on your machine.
So to fix this, you should delete the lines setting ARMADILLO_LIBRARY and ARMADILLO_INCLUDE_DIR, and revert your change in src\mlpack\CMakeLists.txt (using link_directories is generally a bad idea anyway).
After making these changes, you should delete at least your CMakeCache.txt (in the root of your build tree), or even your entire build tree before re-running CMake to avoid the possibility of using bad cached values from previous failed attempts.
I realize this is a late answer, and I hope you have it figured out by now. Even so, I believe your issue is that the ARMADILLO_LIBRARY variable should hold the exact location of the library, instead of the directory the library is in. So, maybe this would work:
set(ARMADILLO_LIBRARY "C:\\Program Files (x86)\\armadillo\\lib\\armadillo.lib")
set(ARMADILLO_INCLUDE_DIR "C:\\Program Files (x86)\\armadillo\\include")
The variable LIBXML2_LIBRARIES should also contain the actual path of libxml2.lib (or whatever the actual library is called).
Have you seen this page of instructions I wrote a while back for compiling mlpack on Windows?
http://www.mlpack.org/trac/wiki/MLPACKOnWindows
Feel free to file a bug report on Trac if you have further problems in the future. I only stumbled upon this by chance, so I don't monitor Stack Overflow for issues.
I ran into the same problem. There are two bullets aramadillo library faq which ask you to uncomment the lines
#define ARMA_USE_LAPACK
#define ARMA_USE_WRAPPER
in the file
include/armadillo_bits/config.hpp
which is in the armadillo source tree.
When you recompile after uncommenting the lines, you can see the symbols in the armadillo shared library/dll. Hope this helps!

How do you export a system library using cmake?

How can I export the libraries that a cmake library depends on, such that an executable depending on that library does not have to manually depend on the dependencies of that library?
That's a bit of a mouthful, so here's an example:
dummy (application) ----> depends on liba
liba ----> depends on libpng
Compiling dummy generates errors:
-- Found LIBPNG
-- Found LIBA
-- Configuring done
-- Generating done
-- Build files have been written to: /home/doug/projects/dummy/build
Linking C executable dummy
../deps/liba/build/liba.a(a.c.o): In function `a_dummy':
/home/doug/projects/dummy/deps/liba/src/a.c:6: undefined reference to `png_sig_cmp'
collect2: ld returned 1 exit status
make[2]: *** [dummy] Error 1
make[1]: *** [CMakeFiles/dummy.dir/all] Error 2
make: *** [all] Error 2
I can fix that by adding this into CMakeLists.txt for dummy:
TARGET_LINK_LIBRARIES(dummy png)
However, dummy has no knowledge of how liba implements its api. At some point that may change to being libjpg, or something else, which will break the dummy application.
After getting some help from the cmake mailing list I've been directed to this example for exporting things:
http://www.cmake.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file
However, following that approach leaves me stuck at this line:
export(TARGETS ${LIBPNG_LIBRARY} FILE "${PROJECT_BINARY_DIR}/ALibraryDepends.cmake")
Clearly I'm missing something here; this 'export' command looks like its designed to export sub-projects to a high level; ie. nested projects inside liba.
However, that is not the problem here.
When configuring liba (or any cmake library) I will always generate a list of dependencies which are not part of that project.
How can I export those so they appear as part of LIBA_LIBRARY when I use find_package() to resolve liba?
Using static libraries is not an option (static library for something that links to opengl? no.)
Given your comment to arrowdodger's answer about the fear of
installing something would mess up your system I chose to give
a conceptional comment in form of an answer because of its
length.
Chaining cmake project works via find_package, which looks for
*Config.cmake and *-config.cmake files.
Project A's CMakeLists.txt:
#CMakeLists.txt
project(A)
install(FILES
${CMAKE_CURRENT_SOURCE_DIR}/AConfig.cmake share/A/cmake
)
#AConfig.cmake
message("Yepp, you've found me.")
$ mkdir build
$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX=/tmp/test-install ..
$ make install
Project B's CMakeLists.txt:
project(B)
find_package(A)
Then
$ mkdir build
$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX=/tmp/test-install ..
$ make install
results in
...
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
Yepp, you've found me.
B found A because it installed AConfig.cmake into a location
where cmake will find it 'share/A/cmake' AND was given the same
value for CMAKE_INSTALL_PREFIX.
Now this is that. Lets think about what you can do in
AConfig.cmake: AFAIK everything you want to. But the most common
task is to pull information about the targets of A via include(),
do some additional find_package invoctions for 3rd party
packages (HINT HINT) and create the variables
A_LIBRARIES
A_INCLUDE_DIRS
What you want to include is a file that was created by
install(EXPORT A-targets
DESTINATION share/A/cmake
)
in A's CMakeLists.txt , where A-targets refers to a global cmake
variable that accumulated all target informations when used in
install(TARGETS ...
EXPORT A-targets
...
)
statments. What is created at make install is
/tmp/test-install/share/A/cmake/A-targets.cmake
which then resides alongside AConfig.cmake in the same directory.
Please take another look at the wiki page on how to use this file
within AConfig.cmake.
Regarding the export() command: This comes handy if your
projects have gotten HUGE and it takes a considerable amount of
time to install them. To speed things up, you want to use what's
in A's build/ directory directly. It's an optimization and also
explained in the wiki. It still works via find_package(), see
http://cmake.org/cmake/help/cmake-2-8-docs.html#command:export
But I strongly suggest that you go for the usual make install
route for now.
I found my own solution to this problem using the accepted solution above, which I leave here for others:
In liba/CMakeLists.txt:
# Self
set(A_INCLUDE_DIRS ${A_INCLUDE_DIRS} "${PROJECT_SOURCE_DIR}/include")
set(A_LIBRARIES ${A_LIBRARIES} "${PROJECT_BINARY_DIR}/liba.a")
# Libpng
FIND_PACKAGE(libpng REQUIRED)
set(A_INCLUDE_DIRS ${A_INCLUDE_DIRS} ${LIBPNG_INCLUDE_DIRS})
set(A_LIBRARIES ${A_LIBRARIES} ${LIBPNG_LIBRARIES})
ADD_LIBRARY(a ${SOURCES})
# Includes
INCLUDE_DIRECTORIES(${A_INCLUDE_DIRS})
# Allow other projects to use this
configure_file(AConfig.cmake.in "${PROJECT_BINARY_DIR}/AConfig.cmake")
In liba/AConfig.cmake:
set(A_LIBRARIES #A_LIBRARIES#)
set(A_INCLUDE_DIRS #A_INCLUDE_DIRS#)
In dummy/CMakeLists.txt:
FIND_PACKAGE(A REQUIRED)
INCLUDE_DIRECTORIES(${A_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(dummy ${A_LIBRARIES})
This yields an AConfig.cmake that reads:
set(A_LIBRARIES /home/doug/projects/dummy/deps/liba/build/liba.a;/usr/lib/libpng.so)
set(A_INCLUDE_DIRS /home/doug/projects/dummy/deps/liba/include;/usr/include)
And a verbose compile that reads:
/usr/bin/gcc -std=c99 -g CMakeFiles/dummy.dir/src/main.c.o -o dummy -rdynamic ../deps/liba/build/liba.a -lpng
Which is exactly what I was looking for.
If liba doesn't provide any means to determine it's dependencies, you can't do anything.
If liba is library developed by you and you are using CMake to build it, then you should install libaConfig.cmake file with liba itself, which would contain necessary definitions. Then you include libaConfig in dummy's CMakeLists.txt to obtain information about how liba have been built.
You can look how it's done in LLVM project, relevant files have cmake.in extension
http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/modules/
In the end, in dummy project you should use
target_link_libraries( ${LIBA_LIBRARIES} )
include_directories( ${LIBA_INCLUDE_DIR} )
link_directories( ${LIBA_LIBRARY_DIR} )
If that liba is used only by dummy, you can build it from single CMake project. This is more convenient, since you don't need to install liba each time you recompile it and it will be rebuilt and relinked with dummy automatically every time you run make.
If you liked this approach, the only thing you should do - define in liba' CMakeLists.txt variables you need with PARENT_SCOPE option (see set() command manual).
Finally, you can use shared libs, .so's don't have such problem.

Resources