Using pg_config with waf - c

I use waf as my build system and I want to compile a small C program using Postgres. I have included postgres.h in my program so I need to find the path to it in my wscript file. I know that I can get the path I need by running:
pg_config --includedir-server
which gives me:
/usr/include/postgresql/9.3/server
So I thought I could use something like this:
cfg.check_cfg(
path='pg_config',
package='',
uselib_store='PG',
args='--includedir-server',
)
And then build my program by:
bld.program(
source=['testpg.c'],
target='testpg',
includes=['.', '../src'],
use=['PQ', 'PG'],
)
But this fails with postgres.h: No such file or directory. I ran ./waf -v and confirmed that the proper -I flag is not being passed to gcc. My guess is this happens because pg_config does not add a -I prefix to the path it returns. Is there a way I can make waf to add the prefix, or make pg_config to add it?

Should pg_config had the standard output of pkg_config like programs (ie outputs something like -Ixxx -Iyyy), your code would work, has check_cfg parse this kind of output.
As there is no complicated parsing, you can go for:
import subprocess
includes = subprocess.check_output(["pg_config", "--includedir-server"])
includes.replace("\n", "")
conf.env.INCLUDES_PG = [includes]
And then use it:
bld.program(
source=['testpg.c'],
target='testpg',
use=['PG'],
)
See the library integration in the waf book. It explains the naming rule that make it works.
You can write a small plugin to ease the use :)

Related

Create directory structure in /var/lib using autotools and automake

I'm using autotools on a C project that, after installation, needs a particular directory structure in /var/lib as follows:
/var/lib/my-project/
data/
configurations/
local/
extra/
inputs/
I'm currently using the directive AS_MKDIR_P in configure.ac like so:
AS_MKDIR_P(/var/lib/my-project/data)
AS_MKDIR_P(/var/lib/my-project/configurations/local)
AS_MKDIR_P(/var/lib/my-project/configurations/extra)
AS_MKDIR_P(/var/lib/my-project/inputs)
But it needs the configure script to be run with root permissions which I don't think is the way to go. I think the instructions to create this directory structure needs to be in Makefile.am, so that make install creates them rather than configure, but I have no idea how to do that.
You really, really, really do not want to specify /var/lib/my-project. As the project maintainer, you have the right to specify relative paths, but the user may change DESTDIR or prefix. If you ignore DESTDIR and prefix and just install your files in /var/lib without regard for the user's requests, then your package is broken. It is not just slightly damaged, it is completely unusable. The autotool packaging must not specify absolute paths; that is for downsteam packagers (ie, those that build *.rpm or *.deb or *.dmg or ...). All you need to do is add something like this to Makefile.am:
configdir = $(pkgdatadir)/configurations
localdir = $(configdir)/local
extradir = $(configdir)/extra
inputdir = $(pkgdatadir)/inputs
mydatadir = $(pkgdatadir)/data
config_DATA = cfg.txt
local_DATA = local.txt
extra_DATA = extra.txt
input_DATA = input.txt
mydata_DATA = data.txt
This will put input.txt in $(DESTDIR)$(pkgdatadir)/inputs, etc. If you want that final path to be /var/lib/my-project, then you can specify datadir appropriately at configure time. For example:
$ CONFIG_SITE= ./configure --datadir=/var/lib > /dev/null
This will assign /var/lib to datadir, so that pkgdatadir will be /var/lib/my-project and a subsequent make install DESTDIR=/path/to/foo will put the files in /path/to/foo/var/lib/my-package/. It is essential that your auto-tooled package honor things like prefix (which for these files was essentially overridden here by the explicit assignment of datadir) and DESTDIR. The appropriate time to specify paths like /var/lib is when you run the configure script. For example, you can add the options to the configure script in your rpm spec file or in debian/rules, or in whatever file your package system uses. The auto-tools provide a very flexible packaging system which can be easily used by many different packaging systems (unfortunately, the word "package" is highly overloaded!). Embrace that flexibility.
According to autotools documentation (here and here), there are hooks that you can specify in Makefile.am that will run at specific times during the installation. For my needs I will use install-exec-hook (or install-data-hook) which will be run after all executables (or data) have been installed:
install-exec-hook:
$(MKDIR_P) /var/lib/my-project/data
$(MKDIR_P) /var/lib/my-project/configurations/local
$(MKDIR_P) /var/lib/my-project/configurations/extra
$(MKDIR_P) /var/lib/my-project/inputs
MKDIR_P is a variable containing the command mkdir -p, or an equivalent to it if the system doesn't have mkdir. To make it available in Makefile.am you have to use the macro AC_PROG_MKDIR_P in configure.ac.

Shell command to compile C in Gprbuild

Using GtkAda, I'm trying to use the resource API to include the Glade file directly inside my code.
For this, we can generate C code from a set of resources using glib-compile-resources which can then be linked to the Ada code.
The problem is that this C code requires Gtk includes which we usually get from the pkg-config command under Linux such as
gcc -c -x c `pkg-config --cflags gio-2.0` myglade.gresource.c
I'd like to know how to provide the same kind of information in a GPRBuild project file.
FYI, I already tried to use the pkg-config command inside the compiler package for C language without any success. Of course, I managed to build by hand but that's a bit long :)
This might work for you:
project Config_Demo is
Pkg_Config := external_as_list ("PKG_CONFIG", " ");
package Compiler is
-- only this file needs the extra switches
for Switches ("myglade.gresource.c") use Pkg_Config;
end Compiler;
end Config_Demo;
and then
gprbuild -P config_demo -XPKG_CONFIG="`pkg-config -cflags gio-2.0`"
Your best bet will be to do what GtkAda does: Look at its shared.gpr.in file, it uses the token #GTK_LIBS_GPR# which will be replaced by the configure script, giving a usable shared.gpr.
Thing is, you need to issue the pkg-config call and build your gpr file from the result somehow. GPRBuild is not equipped to do this for you and process the result. If you're comfortable with GNU autotools, you can look further at how GtkAda achieves it:
GTK_LIBS_GPR is set in aclocal.m4 using a macro that converts the C-style flags to a GPR array. The value comes from GTK_LIBS which is queried here via pkg-config.
If you're not comfortable with GNU autotools, you can write your configure script using basic shell commandos, a scripting language like Python or with whatever other tool you're comfortable with.

How do I execute my program without ./a.out command?

I have written a c program. I want to pipe the program and I want to make it look meaningful. So instead of writing ./a.out each time, I want to name it changetext. To achieve that, I compiled my program following way: gcc -o changetext myprog.c. To the best of my knowledge, this should replace the use of ./a.out and changetext should do that instead. But I'm getting command not found. I am new to c and unix environment. Any suggestion appreciated.
As I said in a comment, you can either put a dot slash (./) in front of the executable to run it
./changetext
Or you put in in a directory that is referenced in the PATH environment variable. A nice explanation of this safety feature can be found here (thanks to rubenvb):
http://www.linfo.org/dot_slash.html
It says that this is more or less to distinguish built-in commands from user-written commands with the same name. I am not convinced though. The shell could simply prefer built-in names to user-supplied ones, and look in the current directory as well as in the PATH.
But this is the *nix way.
In order to compile and run a program such as your changetext with just the command chanhetext, you must put the binary in a directory listed in your PATH environment variable. It is recommended that you put programs that you made for your own use in the ~/bin/ directory. The command you would use to accomplish this would be the following, assuming ~/bin/ already exists:
gcc -o ~/bin/changetext myprog.c
If it does not exist, you can simply create it, then log out and back in.
If you are tired of doing the ./ before the program name you can always make an alias such as
alias a='./a.out' or alias changetext='./changetext'
this just basically look for everytime you type changetext or a and then replaces it to have the ./ infront of it

C to NASM conversion

I'm trying to find a way to convert simple C code to NASM assembly. I have tried using objconv and downloaded and unzipped and built it since I am using a MAC; however, it doesn't seem to be working. I keep getting "-bash: objconv: command not found". Does anyone know another way or can help me solve the -bash error.
Bash is the program that takes the words you type in a terminal and launches other programs. If it is reporting an error, it is because it cannot find the program you want to run (at least in this case).
You need to either find a pre-packaged installation of objconv, or you need to do the work to "integrate" your copy of objconv yourself.
If you can identify the executable you want to run (probably called objconv) you need to add that to your path. The easiest way (if it is just for you) is to verify that your ~/.bashrc or ~/.bashprofile has a line that looks something like
PATH=$PATH:${HOME}/bin
Don't worry if it doesn't look exactly the same. Just make sure there's a ${HOME}/bin or ~/bin (~ is the short version of ${HOME}).
If you have that then type the commands
cd ~/bin
ln -fs ../path/to/objconv
and you will create a soft link (a type of file) in your home binary directory, and the program should be available to the command line.
If you create the file, and nothing above has any errors, but it is not available to the command line, you might need to set the executable bit on your "real" (not link) copy of objconv.
If this doesn't work, by now you should be well primed for a better, more specific question.
If you have gcc installed, try gcc -masm=intel -S source.c to generate assembly files in a syntax very similar to that of MASM.

How to use FLEX in CMAKE

I am trying to figure out what I am doing wrong when trying to use just flex in a Cmake file to build a shared lib.
i basically have the following
find_package(FLEX)
FLEX_TARGET(Test ../src/test.l ../src/test.c)
set(SRC_FILES mysource.c ${FLEX_Test_OUTPUTS})
add_libary(testlib ${SRC_FILES})
target_link_libraries(testlib crypto c ${FLEX_LIBRARIES})
this is giving me a problem saying it cant find ../src/test.c
any ideas how I can make sure Lex ran first? secondly,how can i pass my -L and -d options to lex (like I am doing in my normal, pre-cmake version of this makefile)
Why do you want output file to be in the source dir?
I'd recommend using ${CMAKE_CURRENT_BINARY_DIR}:
FLEX_TARGET(Test ../src/test.l ${CMAKE_CURRENT_BINARY_DIR}/../src/test.c)
As for
any ideas how I can make sure Lex ran first?
you don't need to do it, CMake can guess this dependency by it's own. I think the problem is either in using source dir for output file, or the ../src dir doesn't exist before flex runs.
secondly,how can i pass my -L and -d options to lex
List them after the output parameter:
FLEX_TARGET(Test ../src/test.l ${CMAKE_CURRENT_BINARY_DIR}/../src/test.c -L -d)

Resources