Build directory for ./configure? - configure

Recently, I compiled gdb by using configure and make. To guarantee that the code was built into another directory (build), I executed the configure script from the build directory. (with ../binutils/configure)
Is this strategy (executing configure from within the wished build directory to specify the build directory) written down in some standard, a written convention or similar or does there not exist such a common practice?

It is e.g. documented here:
The GNU Build System distinguishes two trees: the source tree, and the
build tree. These are two directories that may be the same, or
different.
https://www.gnu.org/software/automake/manual/html_node/VPATH-Builds.html
E.g. the make distcheck makes use of this when doing its test build, and makes the source directory read-only so that any misconfigured build rule that creates files in the srcdir instead of builddir gets reported as an error during that check:
https://www.gnu.org/software/automake/manual/html_node/Checking-the-Distribution.html
So while autotools may not advertise this differentiation of source and build directories as strongly as Cmake does it actually has stronger support for it as Cmake is missing such a check feature.

Related

Cmake implicit link directory paths and how to set/override to enable building a common sandbox on different OS versions w.r.t lib dependencies

I work with a large source tree that builds with cmake (rev 3.9.6). I often check the tree
out into a common NFS mounted path, and then build the sandbox on different machines (mounted
thru a common NFS path).
I would ideally like to be able to first build the tree on a CentOS7 system, and
then log into a CentOS8 system, type make from the top of the tree, and see
there is no need to reconfigure anything (cmake) or rebuild anything (all
make dependencies satisfied).
All the binaries built on the CentOS7 system run on the CentOS8 system and it looks
like all tests pass on both CentOS7 and CentOS8. It also works to build the source tree
from scratch on a CentOS8 system as well (after dealing with how compiler warnings changed for
the newer compilers on CentOS8).
In practice I've found that building first on CentOS7 causes cmake generated files
(build.make) to end up with a CentOS7 gcc compiler specific path in them as a make dependency.
Or it looks to me like these generated cmake files from the CentOS7 build,
<top of tree>/CMakeFiles/3.9.6/{CMakeCCompiler.cmake,CMakeCXXCompiler.cmake}
set the serarch paths for the compiler and system libraries via,
set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-redhat-linux/4.8.5;/usr/lib64;/lib64;/usr/lib")
set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-redhat-linux/4.8.5;/usr/lib64;/lib64;/usr/lib")
The first path, /usr/lib/gcc/x86_64-redhat-linux/4.8.5, is unique to the compiler
version on CentOS7 and so does not exist on CentOS8. A cmake generated dependency using this path (in build.make files)stops
make dead in its tracks when typing make at the top of the sandbox in NFS on a CentOS8 machine
because it can't resolve the non-existant path:
foo: /usr/lib/gcc/x86_64-redhat-linux/4.8.2/libgomp.so
However, that pathname to libgomp.so thru the CentOS7 gcc path is a soft link,
/usr/lib/gcc/x86_64-redhat-linux/4.8.2/libgomp.so -> ../../../../lib64/libgomp.so.1.0.0
Or the same version of libgomp.so (libgomp.so.1.0.0) will be referenced on CentOS7 by:
/usr/lib/gcc/x86_64-redhat-linux/4.8.2/libgomp.so
/usr/lib64/libgomp.so.1
Alternately, on CentOS8 libgomp.so.1.0.0 is found via the paths:
/usr/lib/gcc/x86_64-redhat-linux/8/libgomp.so
/usr/lib64/libgomp.so.1
I've experimented with removing the gcc specific path from the implicit link cmake
variables to instead have,
set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib64;/lib64;/usr/lib")
set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib64;/lib64;/usr/lib")
But the CentOS7 compiler specific path will still be found via the /usr/lib entry and I cannot exclude
/usr/lib as a search path altogether. I would really just like to exclude /usr/lib/gcc (?) as an implicit search path
and even then I would have to specify linking against libgomp.so.1 or libgomp.so.1.0.0 instead of libgomp.so.
(BTW - I'm not sure setting those cmake variables explicitly before the project statement in the top level
CMakeLists.txt file worked, but I did not see any way to modify/change how the CMakeC[XX]Compiler.cmake files
are generated in the first place).
Now I could add a custom command to trigger PRE_BUILD on every cmake target to edit any cmake generated build.make
with that the dependency such that,
foo: /usr/lib/gcc/x86_64-redhat-linux/4.8.2/libgomp.so
... edited thru custom command becomes...
foo: /lib64/libgomp.so.1.0.0
This does in fact work and allows make to finish checking (and find) all dependencies when I run it from the top
of the tree on CentOS7 or CentOS8 (after first building on CentOS7). But I would prefer not to retroactively edit
cmake generated files.
So happy to hear any suggestions or if it's just unreasonable to expect to achieve this kind
of parity when building the same NFS mounted sandbox on two revs of the OS with different compiler (revisions and paths), i.e.,
the "right" thing to do is to always re-run cmake on CentOS8 and then rebuild everything on CentOS8.

How can I continue an interrupted compilation after an error occurred?

After an error occurred because of a missing flag or incorrectly set environment variable, is it possible to continue compiling once the mistake has been fixed?
I regularly use CMake and make to compile toolkits that take quite a while to compile and, also regularly, I accidentally set variables incorrectly in the process. Just now for example, I was attempting to include OpenInventor headers which on my machine are located in the directory /Users/user/software/prod/coin/include/Inventor.
I mistakenly passed
-DINVENTOR_INCLUDE_DIR=/Users/user/software/prod/coin/include/Inventor
rather than the correct
-DINVENTOR_INCLUDE_DIR=/Users/user/software/prod/coin/include
This only became an issue after 30 minutes when about 95% of the compilation was completed. Because I knew that reconfiguring using CMake would force a recompilation from scratch, I tried to add -I/Users/user/software/prod/coin/include to CMAKE_CXX_FLAGS in CMakeCache.txt but to no avail–it still recompiled from scratch. Since only a single source file actually includes the headers in question, it would be desirable if I could start compiling from the point where it exited with an error once the relevant path has been corrected. How can I do this and, as an aside, why does it force the compiler to start from scratch?
I'm using CMake version 3.11.1 and clang (Apple LLVM version 9.1.0) on macOS 10.13
CMake does not need to recompile everything just because it regenerates its makefiles. It will still perform normal make avoidance operations. However CMake does track the compiler options used to build each target, so if you make a change in the compiler options for all the targets then they'll all need to be rebuilt.
If this compiler option is only needed for one target, you can add it to just that target an no others, with something like this:
set_property(SOURCE my_source.c APPEND PROPERTY
COMPILE_FLAGS -I/foo/bar)
then it should only rebuild that one source file.
CMake looks for files' "last modified" times to decide which files need recompilation. But if you change the input to CMake itself, then it needs to regenerate the Makefiles and therefore recompile everything. But still, one hack may be possible...
CMake stores information about the include directories and the libraries to be linked in various text files in the build directory. So one hack (not recommended, but works) can be to modify these text files.
In the particular example that you mentioned, the hack would be to search and replace all occurrences of /Users/user/software/prod/coin/include/Inventor with /Users/user/software/prod/coin/include in all the files of the build directory.
(As an aside, if you don't already know, you can use make -j <n> to build using multiple threads which can considerably decrease the build times.)

Is it possible to change the name of generated makefile in CMake?

I have a project which uses Makefiles. On a branch, I have CMake based build system. Now some team-members wants the OLD make-files based system intact, when cmake is added. But this is not possible after cmake . command overwrites the old Makefile.
Now I can easily avoid it if I can tell CMake to generate makefiles with some non-standard names e.g. makefile.cmake etc. Is it possible?
I am open to consider other options as well. In any case, old Makefiles must not be touched.
Cmake creates a build system in the working directory. So create any empty directory, and run cmake <path-to-source> from there.
Unfortunately, the name "Makefile" in hard-coded several times, in the sources of CMake. You cannot change it. As Peter has pointed out in the other answer, that change is not necessary, because CMake support out-of-source builds.

Generate a makefile to include in the deliverable

I have a problem.
I am currently working on a linux application (let's call it BigApp in this scenario). This application needs to be customizable via shared objects(so) and ini/text files.
The prerequisites for creating such shared objects are:
Generating a C file in a custom location (done from code)
an additional h file from the source repository of BigApp (done via makefile)
an executable shell script in the application bin folder (done), which sets up some parameters, calls the internal c file generator described above at number 1, and calls some kind of build script described below.
"the" build script which should compile the h file and the generated C file into a shared object.
The problem I have here is that once BigApp is installed, step 3 (compiling a new shared object) should be done by anyone with some basic linux-like skills. Also, the build script at number 4 should somehow use the same settings which were used when compiling and installing BigApp.
BigApp uses automake (makefile.am, configure.ac files for root and subfolders).
I assume I need a Makefile.am template to generate a particular makefile for the shared object when running configure on the BigApp, but I have no idea how to do this while avoiding it being run when I "make" the BigApp.
I could use any kind of suggestions or references to a tutorial.
Thank you!
EDIT: at the time, the build script for the shared library/object is a small shell script which simply calls gcc two times, but with no particular platform settings, and no relation to the BigApp makefiles.
It's been a while since you posted this question but what you should do is turn your current makefile for your shared libraries into a Makefile.in (or even write a Makefile.am using Automake) that gets completed by your configure script (created using Autoconf) for BigApp. You should study the GNU Build system manuals.

Passing C/C++ #defines to makefile

I develop C/C++ using the Eclipse IDE. Eclipse also generates a makefile which I don't want to edit as it will simply be overwritten.
I want to use that makefile for nightly build within Hudson.
How do I pass #defines which are made in the project file of the IDE to the makefile ? (and why doesn't Eclipse already include them in the generated makefile?)
I actually had this figured out once, then accidentally overwrote it :-( But at least I know that it can be done...
If you are running make from the command line, use
make CPPFLAGS=-DFOO
which will add -DFOO to all compilations. See also CFLAGS, CXXFLAGS, LDFLAGS in the make manual.
You could write a small program to include the headers and write a makefile fragment which you include in the main makefile (requires GNU make).
This is a fairly ugly solution that requires a fair amount of hand hackery. More elegant would be to parse the project file and write the makefile fragment.
For GCC use -D define.
OP commented below that he wants to pass the define into make and have it pass it on to GCC.
Make does not allow this. Typically you just add another make rule to add defines. For instance 'make release' vs 'make debug'. As the makefile creator you make the two rules and have the defines right in the make file. Now if Eclipse is not putting the defines into the makefile for you, I would say Eclipse is broken.
If you're using autotools another options is to have 2 directories 'bin/debug' and 'bin/release'.
# Simple bootstrap script.
# Remove previously generated filed and call autoreconf.
# At the end configure 2 separate builds.
echo "Setting up Debug configuration: bin/debug"
../../configure CXXFLAGS="-g3 -O0 -DDEBUG=1"
echo "Setting up Release configuration: bin/release"
cd bin/release/
../../configure CXXFLAGS="-O2"
Setup Eclipse. Open the project's properties (Project->Properties->C/C++ Build->Builder Settings) and set the Build Location->Build Directory to
${workspace_loc:/helloworld/bin/debug}
Replacing 'helloworld' with your project's directory relative to the workspace (or you can supply an absolute path ${/abs/path/debug}). Do the same thing with the Release config, replacing "/debug" with "release" at the end of the path.
This method seems like a waste of disk space, but a valid alternative to achieve completely separate builds.

Resources