I have a GTK project I'm trying to internationalize. I need help understanding the basic work-flow of how po/Makefile.in.in from the intltool package gets converted to Makefile.in and then to Makefile.
My immediate problem is that Makefile.in is the same as Makefile.in.in. I get many make errors like #SHELL# is not defined, apparently because somewhere along the line that macro/variable was not replaced, along with many others like #srcdir# and #topdir#. If I delete Makefile.in, there is no rule to create it from Makefile.in.in.
My bigger problem is that I'm fuzzy on how the whole tool-chain works to generate the Makefile in this case. I'm getting by with aclocal/autoconf/configure throughout the rest of the project directories, but adding the internationalized stuff is throwing me for a loop. Thanks for any help.
I think I found the answer to my own question. The following link helped:
https://www.mail-archive.com/gtkmm-list#gnome.org/msg13483.html
Mainly, I had to change
AC_CONFIG_FILES(po/Makefile)
to
AC_CONFIG_FILES(po/Makefile.in)
and use the autogen.sh script suggested on that site instead of the one I was using, namely:
#!/bin/sh
mkdir -p m4
echo "Creating m4/aclocal.m4 ..."
test -r m4/aclocal.m4 || touch m4/aclocal.m4
echo "Running glib-gettextize... Ignore non-fatal messages."
echo "no" | glib-gettextize --force --copy
echo "Making m4/aclocal.m4 writable ..."
test -r m4/aclocal.m4 && chmod u+w m4/aclocal.m4
echo "Running intltoolize..."
intltoolize --force --copy --automake || return 1
echo "Running aclocal..."
aclocal || return 1
echo "Running libtoolize..."
libtoolize || return 1
echo "Running autoheader..."
autoheader || return 1
echo "Running autoconf..."
autoconf || return 1
echo "Running automake..."
automake --add-missing || return 1
echo "You should now run ./configure..."
Related
I'm trying to automate a build process that requires retrieving a list of dependencies from a file and then piping those into a command. I have a loop to auto download the packages I am building, but I need to then read a file and get a list of dependencies. What I'm trying to do is this:
cd ${pkg}
then read this line from a file called PKGBUILD: depends=('dep1' 'dep2')
paru -S dep1 dep2
Is there any way to do this? I'm new to bash but I have (copied) this code already:
The problem with this code is it doesn't retrieve some dependencies as they are in the AUR so makepkg doesn't auto retrieve them.
build_pkgs () {
{ echo; echo "Building AUR Packages - "; echo; }
cd $DIR/aur_pkgs
for pkg in "${PKGS[#]}"; do
echo "Building ${pkg}..."
cd ${pkg} && makepkg -s
mv *.pkg.tar.zst $DIR/x86_64
# Verify
while true; do
set -- $DIR/x86_64/$pkg-*
if [[ -f "$1" ]]; then
{ echo; echo "Package '${pkg}' generated successfully."; echo; }
break
else
{ echo; echo "Failed to build '${pkg}', Exiting..." >&2; }
{ echo; exit 1; }
fi
done
cd $DIR/aur_pkgs
done
}
read this line from a file called PKGBUILD: depends=('dep1' 'dep2')
Archlinux PKGBUILDs are written in bash by themselves - just source it and output.
. PKGBUILD
echo "${depends[#]}"
You would preferably do it "safely" in a subshell and transfer the value of the variable with declare -p so that not to modify parent environment.
But makepkg itself is written in bash, so just see it's sources how it's doing and here.
Anyway, so many archlinux users write their own small set of scripts to setup their own repository - there are so many of them and all of them needed to solve that problem. Instead of reinventing the wheel and fixing same mistakes as others did, consider rather searching for a ready-to-use solutions.
I'm just learning to write bash scripts.
I'm writing a script to setup a new server.
How should I go about testing the script.
i.e.
I use apt install for certain packages like apache, php etc. and then a couple of lines down there is an error.
I then need to fix the error and run it again but it will run all the install commands again.
The system will probably say the package is installed already, but what if there are commands which append strings to files.
If these are run again it will append the same string to the file a second time.
What is the best approach to write bash-scripts like this?
Can you do test runs which rollback everything after an error or end of the script?
Or even better to have the script continue from the line where the error occured the next time it is run?
I'm doing this on an Ubuntu 18.04 server.
it's a matter of how clear you want it to be to read it, but
[ -f .step01-done ] || your install command && touch .step01-done
[ -f .step02-done ] || your other install command && touch .step02-done
maybe a little easier to read:
if ! [ -f .step01-done ]; then
if your install command ; then
touch .step01-done
fi
fi
if ! [ -f .step02-done ]; then
if your other install command ; then
touch .step02-done
fi
fi
...or something in between.
Now, I would suggest creating a directory somewhere and maybe logging output from the commands to some file there (maybe tee it) but definitely putting all these files you are creating with touch there. That way if you start it from another directory by accident, it won't matter. You just need to make sure that apt-get or whatever you use actual returns false if it fails. It should.
You could even make a function that does it in a nice way...
#!/bin/bash
function do_cmd() {
if [ -f "$1.done" ]; then
echo "$2: skipping already completed step"
return 0
fi
echo -n "$2: "
$3 1> "$1.out" 2> "$1.err"
if $?; then
echo "ok"
touch "$1.done"
return 0
else
echo "failed"
echo -e "see \"$1.out\" and/or \"$1.err\" for details."
return 1
# could "exit 1" instead
fi
}
[ -d /root/mysetup ] || mkdir /root/mysetup
if ! [ -d /root/mysetup ]; then
echo "failed to find or create /root/mysetup directory
exit 1
fi
cd /root/mysetup
# ---------------- your steps go here -------------------
do_cmd prog1 "installing prog1" "apt-get install prog1" || exit 1
do_cmd prog2 "installing prog2" "apt-get install prog2" || exit 1
do_cmd startfoo "starting foo service" "service foo start" || exit 1
echo "all setup functions finished."
You would use:
do_cmd identifier "description" "command or function"
description
identifier: unique identifier used when files are generated:
identifier.out: standard output from command
identifier.err: standard error from command
identifier.done: created when command is successful
description: this is actually printed to the terminal when the step is being executed.
command or function: this is the actual command to run
not sure why stackoverflow forced me to format that last bit as code but w/e
I'm writing a bash script and want to do robust error checking in it.
The exit status code for mv to make it fail is easy to simulate a failure. All you have to do is move a file that doesn't exist, and it fails.
However with mkdir I want to simulate it failing. mkdir could fail for any number of reasons, problems with the disk, or lack of permissions, but not sure how to simulate a failure.
Just use
mkdir your_directory/
if [ $? -ne 0 ] ; then
echo "fatal"
else
echo "success"
fi
where $? stands for the exit code from the last command executed.
To create parent directories, when these don't exist, run mkdir -p parent_directory/your_directory/
if ! mkdir your_directory 2>/dev/null; then
print_error
exit
fi
or
mkdir your_directory 2>/dev/null || { print_error; exit; }
mkdir will fail if the directory already exists (unless you are using -p), and return an error code of 1 (on my system), so create the directory first to test this on your own system. (Although I would assume that is standard across all shells.)
Alternatively, make the parent directory read-only.
in your script , you could also put a check for the new dir ....
mkdir -p new_dir ;
if [ -d new_dir ]
cd new_dir && ...... anything else you want .
else
echo "error in directory creation ";
exit 2 ;
fi
If you are lazy a simple set -e in the beginning of you script is enough. Often you just want to print an error and then terminate if something goes wrong.
Not exactly what you asked for, but perhaps what you want.
My end goal is to produce a simple .deb package.
For that I've read it's better to provide 3 build phases in my build infrastructure of the project, rather than do it in the debian/ folder.
So first thing I need is a configure script, however I want the simplest configure script ever that just receives a "--prefix" argument and passes its value to the Makefile system (so the "install" target of the makefile can copy the files over to it).
Can I do this without using autoconf? I know autoconf is great but for the simplest configuration-phase ever I may not need it yet so badly.
Thanks
I wouldn't do it without autoconf. You're basically saying that you want to mimic one specific behavior of autoconf, without knowing all the ramifications and related behaviors that autoconf adds. This violates the principle of least surprise, as users (or even your deb tool) will expect the related behaviors (DESTDIR, --exec-prefix, etc.). Just use autoconf. You can make your configure.ac really simple:
AC_INIT([My App], [1.0], [my-email#me.com])
AM_INIT_AUTOMAKE([-Wall foreign])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
I ended up using this:
#!/usr/bin/env bash
prefix=NONE
test "$prefix" = NONE && prefix=/usr/local
usage ()
{
echo ""
echo "Usage : configure [--prefix=PREFIX]"
echo ""
}
while test x$1 != x; do
case $1 in
--prefix=*)
prefix=`echo $1 | sed 's/--prefix=//'`
;;
--prefix)
shift
prefix=$1
;;
--help)
usage
exit
;;
*)
echo Warning: unknown argument $1 >&2
usage
;;
esac
shift
done
echo -n "SUBDIRS = " > config.make
echo Configuration Summary
echo ---------------------
echo
echo "MyApp has been configured with "
echo " prefix = $prefix"
echo
echo >> config.make
echo
echo -n "prefix=$prefix" >> config.make
Then in the Makefile the first thing I need to do is:
top_srcdir=.
CONFIG_MAKE=$(top_srcdir)/config.make
-include $(top_srcdir)/config.make
I would be interested if there are better solutions than this.
I am very new to Makefiles, so I am probably not doing this the best way (your input is much appreciated, since I would like to learn how/why mine is bad). Anyway, here is my problem:
I have a Daemon that I wrote for a program of mine and I am trying to install it with the Makefile (target is "install"). What the "install" target is supposed to do is move the daemon binary to a location, then move the "service script" to either /etc/init.d/ or /etc/rc.d/ (since different distros have different folders...). Here is my makefile so far:
all:
#echo "Making Components"
#cd Daemon; make
#echo "Components Built"
install:
#echo "Installing Components"
#mkdir -p /usr/lib/
#cp Daemon/myprog_d /usr/lib/myprog_d
-#test -d /etc/init.d && cp Scripts/myprog /etc/init.d/
-#test -d /etc/rc.d && cp Scripts/myprog /etc/rc.d/
-#test ! -d /etc/init.d -a ! -d /etc/rc.d && echo " Warning: Couldn't install script. Manually install Scripts/myprog"
#mkdir -p /var/log/
#echo "Installed."
uninstall:
#echo "Uninstalling Components"
#./Scripts/myprog stop > /dev/null
#rm -f /usr/lib/myprog_d
#echo "Uninstall complete"
clean:
#echo "Cleaning Components"
#cd Daemon; make clean
#echo "Clean complete"
As you can see, the "install" target tests to see if those two directories exist and, if they do, copies the script into them (I haven't yet done it to "uninstall", don't worry).
My first question: Is this the right way to do this? The "all" and "clean" targets work (there is another makefile in "Daemon/", as you can deduce), but I want to know if there is a cleaner way of doing this.
Secondly, because the "test" function returns non-zero, I had to do "-" before it so the error would be ignored. Unfortunately, that results in the "make install" output being:
Installing Components
make: [install] Error 1 (ignored)
make: [install] Error 1 (ignored)
Installed.
Which is very ugly and probably not good practice. What can I do in this case? (I have tried both -# and #-, but # will not suppress the "ignored" output)
Sincerely,
Chris
I'd do it this way:
#if [ -d /etc/init.d ]; then cp Scripts/myprog /etc/init.d/ ; fi
#if [ -d /etc/rc.d ]; then cp Scripts/myprog /etc/rc.d/ ; fi
And I'm a little confused by your next line (-#test ! -d /etc/init.d -a !...) but you can probably do it the same way.
That takes care of the error messages, but if you wanted to keep the makefile as it is, you could suppress them by running make -s.