cmake build executable with relative paths for dependencies (relocatable executable) - c++

I have a package that is using cmake as its compiler. If I install the dependencies it needs first using a package manager then run cmake e.g.
$ sompackage-manager install depend1 depend2
$ wget http://a.b.c/somepackage.tgz
$ tar -xf somepackage.tgz
$ cd somepackage/
$ ls
CI CMakeFiles CONTRIBUTING.md README.md
CMakeCache.txt CMakeLists.txt doc LICENSE
cmake .
This will work fine. cmake finds all the dependencies and the project will create a folder in the build directory named bin that the executable will be in. I can then move the executable where ever id like. I assume the executable either knows the full path of the dependencies or has a list of full paths to check.
What id like to do is this:
create a folder like $HOME/newpackage. Then install the dependencies (the dependencies happens to use a configure script) to that directory e.g.
$ mkdir $HOME/newpackage/depend1
$ wget http://a.b.c/depnd1.tgz
$ tar -xf depend1.tgz
$ cd depend1
$ ./configure --prefix=$HOME/newpackage/depend1
Once all the dependencies are installed to $HOME/newpackage/depend1
Id then like to go back to the somepackage build directory and tell cmake to build the package to $HOME/newpackage/ dir but also to look for the dependencies relative to where the executable is i.e a path like ./. The end result would allow me to move the newpackage directory with the executable and the dependencies folders without breaking any paths.
I am having trouble finding the right cmake options or wether or not they are available.
Is this possible with cmake and what is the best way to go forward?

Related

Need help completing command line installation of {fmt} on Windows 10

I'm a Linux user who's trying to set up a dev environment on Windows. I've cloned the fmt repo and built it the way I'm used to on Linux:
C:\Users\me\Development> git clone https://github.com/fmtlib/fmt.git
C:\Users\me\Development> cd fmt
C:\Users\me\Development> mkdir build
C:\Users\me\Development> cd build
C:\Users\me\Development> cmake ..
C:\Users\me\Development> cmake --build . --config Release
Now I want to install it so that I can include it in projects. Normally I would $ sudo make install but I'm not sure what to do on Windows and the fmt doc page has nothing for Windows installation.
When I did this same set of steps with FLTK there was a variable that I had to set to help me find things:
# CMakeLists.txt
set(FLTK_DIR "Path/to/installation")
find_package(FLTK REQUIRED NO_MODULE)
But it seems to be looking for the installation point, not the build dir. How can I get this to work?
You can run:
cmake --install . [--prefix <install-dir>]
The prefix is optional. On Windows, the default CMAKE_INSTALL_PREFIX is set to:
C:/Program Files (x86)/<project name>
Which in the case fmtlib would be:
C:/Program Files (x86)/FMT
Another option is to use vcpkg on Windows, which will install fmtlib locally in its own vcpkg install prefix. Then you can use it via:
find_package(fmt REQUIRED)
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE fmt::fmt)
You just have to pass the vcpkg cmake toolchain file to your cmake invocation:
cmake .. -DCMAKE_TOOLCHAIN_FILE=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake

How to use Sphinx in a Python project that depends on being built in place?

I have a large mostly Python project that I am trying to document. Part of this project is dependent on C++ source code which is made accessible via Cython.
When running the code like normal it runs fine, but in trying to do auto documenting with Sphinx I have run into issues. I think this guy had the right idea, but I cant make it work.
My Makefile looks like this
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
#$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
#$(SPHINXBUILD) -M $# "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
How can I tell Sphinx to run python setup.py build_ext --inplace and then reference the output .so file(s) before analyzing the code?
Thank you for your time.
You would want to add the step from the answer you linked as part of the Makefile generated from sphinx to before any sphinx specific command was executed.
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
#$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
#cd /path/to/setup.py; python setup.py build_ext --inplace
#$(SPHINXBUILD) -M $# "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
Adding it above the catch-all command that sphinx generates means that the build command to generate cython code would be executed prior to the the sphinx related command.
I would suggest instead to structure the project directory to be more standard to what is used in python. Instead of having documentation be in the same directory as the source code instead have a separate directory for source code and documentation.
root directory/
myproject/ (source code for Cython module)
libs/ (generated .so files from Cython)
tests/ (directory to hold test cases that should run after building)
__init__.py
docs/
Makefile (from sphinx)
Makefile (project)
setup.py
The Makefile for the project would be responsible for building the source code and then building the documentation. Its Makefile would look similar to below:
.all:
#python setup.py build_ext
#cd tests; $(MAKE) python -m unittest
#cd docs; $(MAKE) html
The first part of all would generate the source code (and should be updated to place the .so files generated to the libs/ folder). The second part would go into the tests/ directory and run unittests (example with python's unittest library). The third part would go into the docs/ directory and run make for the target html using the Makefile generated by Sphinx. To do this you would also want to update the tests and docs to include libs/ in their path so that way they can import the .so files generated from the build. (Note: # symbol prevents the line from being output to the console. This should be omitted if it is desired to be seen as part of a build)

How can I convert a configure script to a CMakeLists file?

I'm wanting to use this library in my cmake project, however it comes with a configure file instead of CMakeLists.txt
#! /bin/sh
# waf configure wrapper
# based on http://code.google.com/p/waf/source/browse/configure
CUR_DIR=$PWD
#possible relative path
WORKINGDIR=`dirname $0`
cd $WORKINGDIR
#abs path
WORKINGDIR=`pwd`
cd $CUR_DIR
WAF=$WORKINGDIR/tools/waf
# Generates a Makefile. Requires that $WAF is set.
#
generateMakefile()
{
cat > Makefile << EOF
#!/usr/bin/make -f
# Waf Makefile wrapper
WAF_HOME=$CUR_DIR
all:
#$WAF build
all-debug:
#$WAF -v build
all-progress:
#$WAF -p build
install:
$WAF install --yes;
uninstall:
$WAF uninstall
clean:
#$WAF clean
distclean:
#$WAF distclean
#-rm -rf build
#-rm -f Makefile
check:
#$WAF check
dist:
#$WAF dist
.PHONY: clean dist distclean check uninstall install all
EOF
}
generateMakefile
"${WAF}" configure $*
exit $?
Are there automated tools for the conversion? Does CMake supoprt the use of configure files? Is there a rule of thumb for conversion - i.e. replace ... with add_library?
You don't need to convert an upstream library to cmake to be able to use it in cmake projects. As long as you're able to install and/or link to that library, you can configure your cmake project to use it.
A common pattern to consume third-party libraries with cmake is to use cmake's find_package() function by supplying your own special-purpose cmake module files to find and configure the library.
Say, you're hoping to load libfoo. Here are the steps:
create a directory within your project tree to store your custom cmake modules (say, ./cmake/modules)
in that directory create a text file named FindFoo.cmake.
Within FindFoo.cmake add checks to determine if foo is actually present in the system. If it is then set the relevant variables. Otherwise, throw an error. The ideal thing is to create a build target for that library, which you can simply add as dependencies to other cmake targets.
Configure your cmake project to use your local modules by adding set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/"),
Finally, configure your cmake project to include your Foo library by calling find_package(Foo REQUIRED).
The way to do the conversion is to read the configure script and understand what it does and how/why. Then write a CMakeLists.txt file that achieves the same.
There are no shortcuts.

Install NTL without root privileges and modify it's build path in makefile

I want to install the HElib library (for which NTL is a dependency) on a remote machine on which I do not have root privileges, i.e. I cannot use "sudo make install" to install NTL. The NTL library is not installed in usr/local as per HElib's makefile.
LDLIBS = -L/usr/local/lib $(NTL) $(GMP) -lm
How can I install NTL without root privileges and how do I modify the Makefile in order for it to run?
In NTL's makefile you can change the line:
DEF_PREFIX=/usr/local
to become
DEF_PREFIX=$(HOME)/dev
Then you should be able to set in HElib's Makefile:
LDLIBS = -L$(HOME)/dev/lib $(NTL) $(GMP) -lm
Replace dev with the path to your development folder in your $HOME directory.

CMake build multiple targets in different build directories

I have the following CMake structure:
CMakelists.txt
toolchain.cmake
folder1
----CMakelists.txt
folder2
----CMakelists.txt
etc..
My first-level CMakelists.txt file includes the other subdirectories. Now I want to build my code for a different target.
The manual way is:
1.
mkdir hostBuild
cd hostBuild
cmake ..
make
2.
mkdir crossBuild
cd crossBuild
cmake .. --DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
make
Is it possible that this process can run automatically?
For example, I just have to run cmake . at my first level.
Is something like this is possible?
No. The recommendation would be to just put your manual steps into a shell script.
CMake can only handle one compiler/make environment at a time (if you switch the compiler you need a different binary output directory).
Especially a toolchain file that does contain SET(CMAKE_SYSTEM_NAME ...) does change the whole outcome of the configuration/generation process.
For details on what CMake does see: CMake: In which Order are Files parsed (Cache, Toolchain, …)?
And you could make use of some CMake command line options in your shell script:
if [ ! -d hostBuild ]; then
cmake -E make_directory hostBuild
cmake -E chdir hostBuild cmake ..
fi
cmake --build hostBuild
...