How to add requisites dynamically in makefile - linux

I'm learning how to use makefiles for complex projects. I got it working but I don't know how to add pre-requisites under certain conditions without specifying them one by one. In this particular case I'm trying to add header files as requisites of objects goals so if any header file is modified, that particular cpp has to be rebuild again and linked with the rest.
After looking for clues on the manual I tried to use some shell scripting but I guess the substitution I'm doing is expanded after checking for dependencies so it does nothing. I have tried to use the $(if ) expression in the requisites too but I ended up moving it just in case it was some kind of conflict with using it inside a static pattern rule.
Some additional notes:
I'm learning the tool so I would prefer to avoid CMake or any kind of utility that builds the makefile for me (I would gladly use the facilities after being sure I can replicate at some degree what they do by myself)
I also prefer to avoid solutions tied to the language I'm using in the example as it should work with any compiler and other kind of files and goals/requisites.
I have the following files in my working directory:
.
├── Makefile
└── src
├── main.cpp
└── somemodule
├── module.cpp
└── module.h
My makefile has to generate the following structure:
.
├── app
├── Makefile
├── obj
│   ├── main.o
│   └── somemodule
│   └── module.o
└── src
├── main.cpp
└── somemodule
├── module.cpp
└── module.h
My current makefile:
APP := app
SRCDIR := src
OBJDIR := obj
OBJS := obj/main.o obj/somemodule/module.o
SRCS := $(OBJS:.o=.cpp)
$(APP): $(OBJDIR) $(OBJS)
g++ $(OBJS) -o $(APP)
$(OBJDIR):
mkdir -p $(patsubst $(SRCDIR)%,$(OBJDIR)%,$(shell tree src -fid --noreport))
$(OBJS): HEADERS += $(if $(shell if [ -e $(#:obj%.o=src%.h) ]; then echo "y"; fi), $(#:obj%.o=src%.h))
$(OBJS): $(OBJDIR)%.o: $(SRCDIR)%.cpp $(HEADERS)
g++ -c $(patsubst $(OBJDIR)%.o,$(SRCDIR)%.cpp,$#) -o $#
.PHONY: clean
clean:
rm -rf $(OBJDIR)
rm $(APP)

trying to add header files as requisites of objects goals so if any header file is modified, that particular cpp has to be rebuild again and linked with the rest doesn't sound complex: that's table-stakes for a good build system, if I understood it correctly.
I don't understand what your syntax of setting HEADERS is trying to do here but there's no way it can work. Please read carefully the introduction to automatic variables in the GNU make manual; in particular this text:
It’s very important that you recognize the limited scope in which automatic variable values are available: they only have values within the recipe. In particular, [...] they cannot be accessed directly within the prerequisite list of a rule.
Luckily I see no need for any of that. Have you considered using dependency generation methods such as the one discussed here?
In response to the requirement you added when you updated the question:
I also prefer to avoid solutions tied to the language I'm using in the example as it should work with any compiler and other kind of files and goals/requisites.
I answered:
There is no way to do this only using only make because make doesn't know how to parse your code, and so it can't figure out what the dependencies of a source file are. Similarly, you can't do it in a generic way for all different languages because different languages use different syntax for declaring dependencies. If you want to have automatic dependency tracking, and not do it by hand, you must have SOME tool that can parse your source to find the dependencies. You can use GCC or makedepend or even some fancy shell script if you don't need it to be too accurate.

Related

Cargo project with library + multiple binaries, with binaries consisting of multiple files?

The Cargo book describes how to have a library and multiple executable in a single Cargo project.
I'd like to have an executable consist of multiple source files that are specific to that executable and not in the library.
For example
src/lib1.rs, src/lib2.rs, src/lib3.rs in the library itself,
src/bin/exe1.rs + another source file specific to exe1 for the exe1 executable.
Where would I place this last source file so that it's not compiled into the library but compiled into the executable?
The Cargo-supported way to have multiple source files for a single binary in a package is to give it a directory with main.rs. The documentation on “Package Layout” gives this example (I have removed irrelevant elements):
src/
├── lib.rs
└── bin/
├── named-executable.rs
├── another-executable.rs
└── multi-file-executable/
├── main.rs
└── some_module.rs
You want the multi-file-executable case here. Name the directory whatever you want the binary to be named. Your main.rs will then contain mod some_module; in just the same way as if this project had been a simple src/main.rs project.

How do you force automake to copy shared objects to /usr/local/lib?

I currently have a c++ project which depend on some external shared objects (.so). My current directory looks like this:
├── src
│ └── .cpp files
├── include
│ ├── glad
│ │ └── .h files
│ └── fmod
│ ├── core
│ │ └── .h files
│ └── studio
│ └── .h files
├── lib
│ └── fmod
│ ├── core
│ │ └── .so files
│ └── studio
│ └── .so files
├── Makefile.am
├── configure.ac
I want to compile this project while simultaneously copying those .so files towards /usr/lib or /usr/local/lib, however I can't seem to be able to do this!
The following is my configure.ac file
AC_INIT([autoGL], 1.0)
AM_INIT_AUTOMAKE
AC_PROG_CC
AC_PROG_CXX
AC_CONFIG_FILES(Makefile)
AC_OUTPUT
And my Makefile.am
bin_PROGRAMS = autogl
autogl_SOURCES = src/Source.cpp
autogl_SOURCES+= src/glad.c
autogl_LDADD = -lglfw -ldl
autogl_LDADD+= -L lib/fmod/core -lfmod
autogl_LDADD+= -L lib/fmod/studio -lfmodstudio
autogl_LDFLAGS = -Wl,--no-as-needed,-rpath,lib/fmod/core,-rpath,lib/fmod/studio
autogl_CPPFLAGS = -I include
autogl_CPPFLAGS+= -I include/fmod/core
autogl_CPPFLAGS+= -I include/fmod/studio
autogl_CPPFLAGS+= -I include/fmod/fsbank
You can see that I'm linking every library using the link flags -L lib/fmod/---- -library. Initially, the seventh line of my Makefile.am was only
autogl_LDFLAGS = -Wl,--no-as-needed
resulting in the following g++ code, which was successfull and gave me an executable file
g++ -g -O2 -Wl,--no-as-needed -o autogl autogl-Source.o autogl-glad.o -lglfw -ldl -L lib/fmod/core -lfmod -L lib/fmod/studio/ -lfmodstudio
However, when tried to run this, I would get the following error:
./autogl: error while loading shared libraries: libfmod.so.12: cannot open shared object file: No such file or directory
My shared objects are not being copied to /usr/lib or /usr/local/lib.
With the addition of
autogl_LDFLAGS = -Wl,--no-as-needed,-rpath,lib/fmod/core,-rpath,lib/fmod/studio
since we are linking rpath to our lib files, the program has no problem running. However, if I run make install, the rpath being linked would be /usr/bin/lib/fmod/core and /usr/bin/lib/fmod/studio, which clearly don't have the needed files. My .so files are still not being copied anywhere. I want to copy my .so files directly to /usr/local/lib so that my program can run without me having to link it directly.
How can I force automake to copy these .so files directly to a folder of my choice? (preferable /usr/local/lib).
Found a solution!
Autotools also offers the possibility to transfer data. I added the following to my Makefile.am
flashdir=$(prefix)/lib
flash_DATA= lib/fmod/core/libfmodL.so \
lib/fmod/core/libfmodL.so.12 \
lib/fmod/core/libfmodL.so.12.10
.....
This adds all of my .so files to $(prefix)/lib, which usually is /usr/local/lib.
However, there is a problem, particularly in Ubuntu, where /usr/local/lib is not by default on /etc/ld.so.conf.d, so libraries on /usr/local/lib are not used.
To solve this I added the following line to my makefile.am
install-data-hook:
ldconfig $(prefix)/lib
This creates a hook which runs AFTER the lib files are already added to $(prefix)/lib, which, when run, adds the folder to /etc/ld.so.conf.d, so now after make install, everything runs smoothly.

How to properly find and link NDK shaderc lib into your project in Android Studio?

I want to run Vulkan on my android phone, and currently, I'm stuck at the point trying to make CMake find the libshaderc.
What I did is first build the shaderc:
cd <my-ndk-root>/sources/third_party/shaderc
../../../ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk APP_STL:=c++_static APP_ABI=all NDK_TOOLCHAIN_VERSION:=clang libshaderc_combined -j16
And inside my CMakeLists.txt, I have:
get_filename_component(SHADERC_SRC
${ANDROID_NDK}/sources/third_party/shaderc
ABSOLUTE)
add_library(shaderc_lib STATIC IMPORTED)
set_target_properties(shaderc_lib PROPERTIES IMPORTED_LOCATION
${SHADERC_SRC}/libs/${ANDROID_STL}/${ANDROID_ABI}/libshaderc.a)
But the CMake can't find the shaderc_lib, and failed with error:
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
shaderc_lib
Please note that I already checked that I have libshaderc.a under the [my-ndk-root]/sources/third_party/shaderc/libs:
.
└── c++_static
├── arm64-v8a
│   └── libshaderc.a
├── armeabi-v7a
│   └── libshaderc.a
├── x86
│   └── libshaderc.a
└── x86_64
└── libshaderc.a
5 directories, 4 files
I'm not very familiar with CMake and NDK, so if I made some stupid mistakes, please correct me. Thanks in advance!
Make sure your CMake path points to the correct place. Also, your libshaderc.a is static library and you need to link it to your shared lib, e.g. libshaderc-shared.so using below CMake configuration:
target_link_libraries( libshaderc-shared
[my-ndk-root]/sources/third_party/shaderc/libs/c++_static/${ANDROID_ABI}/libshaderc.a )
References:
Here is the guide for how to properly build shaderc https://github.com/google/shaderc.
https://developer.android.com/ndk/guides/graphics/shader-compilers
I am busy learning Vulkan as well, and the only help I can currently provide is the vulkan samples. They work on an android device which supports vulkan. I am using a nokia scirocco 8 as my test device. Have a look at the CMakeLists.txt in the samples as to how to link the shaderc static library. https://github.com/googlesamples/vulkan-basic-samples/

Debian Package Creation- How to install configuration files?

I've been really stuck on this minor (I'm sure) issue so any help would be greatly appreciated. I've created a standard ubuntu package with dh_make. The purpose of this package is to create a package that will set up all the ldap related packages that a system needs including it's configuration. One of the steps I'm trying to do is to copy over an /etc/ldap.conf file while making a backup of the existing file. How do I do this? I tried to create a postinst script that looks essentially like the following, but I'm not clear on how the package stores the files and I get an error saying missing etc/ldap.conf file. What's the best way to do this? Here is my postinst script:
#!/bin/bash -xv
install -v -b etc/ldap.conf /etc/ldap.conf > /tmp/tst 2>&1
Here is my skeleton structure:
root#hqd-clientb-16:~/navldapubuntu-0.1/debian# tree
├── changelog
├── compat
├── control
├── copyright
├── docs
├── etc
   └── ldap.conf
├── install
├── postinst
├── README.Debian
├── README.source
├── rules
├── source
   └── format
├── navldapubuntu
   └── etc
├── navldapubuntu.debhelper.log
├── navldapubuntu.dirs
└── navldapubuntu.doc-base.EX
Here's some additional information of the package I created.
dpkg --contents tnoldapubuntu_0.1-1_all.deb (truncated output)
./usr/
./usr/share/
./usr/share/doc
./usr/share/doc/navldapubuntu/
./usr/share/doc/navldapubuntu/copyright
./usr/share/doc/navldapubuntu/README.Debian
./usr/share/doc/navldapubuntu/changelog.Debian.gz
./etc/ldap.conf
There is a special tool that designed for creation of configuration packages: http://debathena.mit.edu/config-packages
Here is a simple template that could be helpful for a quick start.
List of files
template (directory)
template/debian (directory)
template/debian/control
template/debian/changelog
template/debian/displace
template/debian/rules
template/debian/postinst
template/debian/install
template/debian/docs
template/debian/compat
template/README
template/BUILD
template/files (directory)
template/files/etc/ldap.conf.mycompanyname
Content
template/debian/control:
Source: PACKAGE_NAME
Section: morpho/misc
Priority: optional
Maintainer: MAINTAINER
Build-Depends: debhelper, config-package-dev (>= 5.0~)
Package: PACKAGE_NAME
Architecture: all
Depends: ${misc:Depends}, DEPENDENCY [, DEPENDENCY ...]
Provides: ${diverted-files}
Conflicts: ${diverted-files}
Description: PACKAGE_DESCRIPTION_SHORT
PACKAGE_DESCRIPTION_LONG.
template/debian/displace
/etc/ldap/ldap.conf.mycompanyname
template/debian/install
files/* /
template/debian/postinst
#!/bin/sh
set -e
#DEBHELPER#
POSTINST_SCRIPT
template/debian/rules
#!/usr/bin/make -f
# Exclude *.svn* from building
# you probably don't need this if don't use SVN
export DH_ALWAYS_EXCLUDE=.svn
# Core (check http://debathena.mit.edu/config-packages for more information)
%:
dh $# --with=config-package
# Prevent dh_installdeb of treating files in /etc as configuration files
# you need this if need configuration files been always rewritten
# even if changed
override_dh_installdeb:
dh_installdeb
rm debian/*/DEBIAN/conffiles
template/debian/docs
README
BUILD
And finally you can build this package with the following command:
dpkg-buildpackage -us -uc -I.svn
You need to create a "conffiles" file in the DEBIAN directory, next to the "control" file, and declare /etc/ldap.conf in it. So this file will be automatically considered a configuration file, and changes to it will prompt a "new config file, would you want to overwrite, yadda yadda".

creating makefile [duplicate]

This question already has an answer here:
Closed 11 years ago.
Possible Duplicate:
Creating makefile
Hello, I am trying to create the makefiles and configure for my library which its directory structure is like following:
$projectroot
├── part1
│   ├── src
│   └── lib
├── part2
│ ├── src
│ └── lib
└── part3
├── src
└── lib
As you can see, this project has 3 different parts, Someone would want to install the entire project, or someone might need only one library from project.
I have a Makefile like the following:
SUBDIRS = part1/lib part1/src part2/lib part2/src part3/lib part3/src
part1:
cd part1/lib; make
cd part1/src; make
part2:
cd part2/lib; make
cd part2/src; make
part3:
cd part3/lib; make
cd part3/src; make
The problem comes around when I use
$ make part1 install
that installs the whole project but I want just to install part1, not all the parts
How can I do that?
Your question is really difficult to parse, but I have a feeling that you need an additional set of install targets for each part:
part1_install: part1
cd part1/lib; make install
cd part1/src; make install
Then you can just execute make part1_install (part1 will be built implicitly).

Resources