Calling SED for a source in Makefile.am - sed

I've got c++ code that needs a sed done to it prior to compilation. How do I place this into Makefile.am?
I tried the typical makefile setup and the target appears to not exist:
gentest.cc:
$(SED) -i "s|FIND|REPLACE|" gentest.cc
If you are interested as to why I want to do this, it's because I wrote my program (slider3.py) in python and my partner wrote his in c++ (gentest.cc) and his needs to call mine. I'm accomplishing this by editing the argv and then using execv().
... {
char **argv2 = new char*[argc];
memset(argv2,0,sizeof(argv2));
argv2[0] = "__PREFIX__/bin/slider3.py";
memcpy(argv2 + 1, argv + 2, sizeof(char *) * (argc - 2));
int oranges = execv(argv2[0], argv2);
printf("%s\n", strerror(oranges));
return oranges;
} ...
I've already handled getting the #! added to slider3.py and chmod +x by using the method that was not working for gentest.cc. I've also handled adding slider3.py to the list of files that get installed.
EXTRA_DIST=testite.sh slider3_base.py
bin_SCRIPTS = slider3.py
CLEANFILES = $(bin_SCRIPTS)
slider3.py: slider3_base.py
rm -f slider3.py
echo "#! " $(PYTHON) > slider3.py
cat slider3_base.py >> slider3.py
chmod +x slider3.py
gentest is defined this way in Makefile.am:
bin_PROGRAMS = gentest
gentest_SOURCES = gentest.cc
gentest_LDADD = libgen.a #../libsbsat.la $(LIBM)
And this fails to be run during make (note the # pattern is successfully expanded in Makefile):
gentest.cc:
$(SED) -i "s|__PREFIX__|#prefix#|" gentest.cc
Any ideas on how to get sed to run before compiling gentest.cc?

Don't use in-place sed.
Instead:
gentest_SOURCES = gentest-seded.cc
gentest-seded.cc : gentest.cc
$(SED) "s|__PREFIX__|#prefix#|" $< >$#

Have you ever considered #define-ing it in config.h (you're using autotools, right?) or passing it using -D when compiling? This is really not the case for sed.
The details from Andrew Y's answer:
in your C++ source, specify:
argv2[0] = SCRIPTPREFIX "/bin/slider3.py";
then compile with
-DSCRIPTPREFIX='"/your/script/prefix"'

Have you considered calling the Python code directly from the C++? Here is a tutorial on using boost to call python functions from C++. The method you are describing here seems very brittle.

Related

Yocto rust recipe also produces -native output that needs packaging

I tried this approach on hardknott but I couldn't get it to work recipe also produces -native output that needs packaging
It is a rust recipe that generates an x86_64 app which I would like to package the right way in sdk, so that it can be used.
I can separate the main package to -native-bin, and I see it in the recipe-sysroot, but I can't get it to populate the recipe-sysroot of the workdir of the file when building the -native-helper recipe. And I suspect the reason is that I get an error that the main recipe for x86_64 can't be found?
ERROR: Manifest xxxxxx.populate_sysroot not found in vs_imx8mp cortexa53 armv8a-crc armv8a aarch64 allarch x86_64_x86_64-nativesdk (variant '')?
So any helpful information would be appreciated!
Hacked like this:
Recipe.bb:
do_install_append() {
# Set permision without run flag so that it doesn't fail on checks
chmod 644 ${D}/usr/bin/#RECIPE#-compiler
}
# #RECIPE# generates a compiler during the target generation step
#separate this to the -native-bin package, and skip the ARCH checks
#also in the image file for stations_sdk move the app to right dir and add execute flag
PACKAGES_prepend = "${PN}-native-bin "
PROVIDES_prepend = "${PN}-native-bin "
INSANE_SKIP_${PN}-native-bin = "arch"
FILES_${PN}-native-bin = "/usr/bin/#RECIPE#-compiler"
SYSROOT_DIRS += "/"
Image.bb:
# #RECIPE# produces a compiler that is produced as a part of the target generation
#so we use the recipe and hack it to supply the -compiler as part of the
#host binaries
TOOLCHAIN_TARGET_TASK_append = " #RECIPE#-native-bin"
do_fix_#RECIPE#() {
mv ${SDK_OUTPUT}/${SDKTARGETSYSROOT}/usr/bin/#RECIPE#-compiler ${SDK_OUTPUT}/${SDKPATHNATIVE}/usr/bin/#RECIPE#-compiler
chmod 755 ${SDK_OUTPUT}/${SDKPATHNATIVE}/usr/bin/#RECIPE#-compiler
}
SDK_POSTPROCESS_COMMAND_prepend = "do_fix_#RECIPE#; "
This produces at the end the binary in the right directory

config.site for vendor libs on Fedora x86_64

I'm having trouble building a few Autotool-based libraries on Fedora 26, x86_64. The 64-bit Fedora puts third party and vendor libraries in /usr/local/lib64. Ubuntu 17 uses /usr/local/lib so the same projects build OK.
I've been using --libdir=/usr/local/lib64 but three libraries resist it. I lack a config.site for /usr/local so I am trying to add one. The Autoconf manual on Site Defaults is a tad bit confusing to me when it discusses usr/local's config.site. It says:
[discussion of /usr version of confg.site] ...
Likewise, on platforms where 64-bit libraries are built by default,
then installed in /usr/local/lib64 instead of /usr/local/lib, it is
appropriate to install /usr/local/share/config.site:
# /usr/local/share/config.site for platforms that prefer
# the directory /usr/local/lib64 over /usr/local/lib.
test "$libdir" = '${exec_prefix}/lib' && libdir='${exec_prefix}/lib64'
The problem I am having is, is the modification above appended to the /usr/local version of config.site? Or does it replace an existing block of code? Or can I just copy it where it belongs without modification?
Or maybe, what does a cat of /usr/local/share/config.site look like?
Here is the config.site for /usr. Its not clear to me if it needs modification or how to modify it.
$ cat /usr/share/config.site
# This is the config.site file to satisfy FHS defaults when installing below
# /usr.
#
# You may override this file by your config.site using the CONFIG_SITE env
# variable.
#
# Note: This file includes also RHEL/Fedora fix for installing libraries into
# "/lib/lib64" on 64bit systems.
if test -n "$host"; then
# skip when cross-compiling
return 0
fi
if test "$prefix" = /usr \
|| { test "$prefix" = NONE && test "$ac_default_prefix" = /usr ; }
then
test "$sysconfdir" = '${prefix}/etc' && sysconfdir=/etc
test "$sharedstatedir" = '${prefix}/com' && sharedstatedir=/var
test "$localstatedir" = '${prefix}/var' && localstatedir=/var
ARCH=`uname -m`
for i in x86_64 ppc64 s390x aarch64; do
if test $ARCH = $i; then
test "$libdir" = '${exec_prefix}/lib' && libdir='${exec_prefix}/lib64'
break
fi
done
fi
config.site for vendor libs on Fedora x86_64
This answers the question of what config.site looks like for /usr/local/share/config.site. It does not answer the question of why --libdir=/usr/local/lib64 fails to set the directory, as #John Bollinger pointed out in the comments.
The /usr/local/share/config.site is wrong. Though it was copied from Fedora's config.site and placed in /usr/local/share, the prefix directories are wrong. The prefix test should use /usr/local and not /usr.
Below is the corrected one.
$ cat /usr/local/share/config.site
...
if test -n "$host"; then
# skip when cross-compiling
return 0
fi
if test "$prefix" = /usr/local \
|| { test "$prefix" = NONE && test "$ac_default_prefix" = /usr/local ; }
then
test "$sysconfdir" = '${prefix}/etc' && sysconfdir=/etc
test "$sharedstatedir" = '${prefix}/com' && sharedstatedir=/var
test "$localstatedir" = '${prefix}/var' && localstatedir=/var
ARCH=`uname -m`
for i in x86_64 ppc64 s390x aarch64; do
if test $ARCH = $i; then
test "$libdir" = '${exec_prefix}/lib' && libdir='${exec_prefix}/lib64'
break
fi
done
fi
I'm not sure if these are correct, however. They were not modified.
test "$sysconfdir" = '${prefix}/etc' && sysconfdir=/etc
test "$sharedstatedir" = '${prefix}/com' && sharedstatedir=/var
test "$localstatedir" = '${prefix}/var' && localstatedir=/var
Now, the next question is, why Fedora's /usr/share/config.site is not handling prefix=/usr/local properly. That's an open question at Issue 1510073 : Autoconf does not honor libdir in config.site for "libdir=#libdir#" in *.pc file, which has been closed as NOT A BUG.

UNIX 'diff' returns improperly when called using popen in main.c

I have a series of tests for a school project that involves building an assembler.
The tests use popen to catch the output of "make" and "./assembler" -- this is just so the output of these commands don't crowd the output of the test suite.
The problem is that the call to popen that executes "diff" returns a string inside the automated test suite, but not when I call it manually.
Here's the test suite code:
char buf1[256];
FILE* make;
FILE* assemble;
FILE *diff;
make = popen("make", "r");
assemble = popen("./assembler input/simple.s inter.txt out.txt", "r");
diff = popen("diff inter.txt out/ref/simple_ref.int", "r");
fgets(buf1, sizeof(buf1), diff);
printf("\nafter fgets simple -- strlen(buf) is %d\t buf is %s\n", strlen(buf1), buf1);
Here's the segment of the test suite output that corresponds with the above code:
after fgets simple -- strlen(buf) is 8 buf is 1,7c1,6
Here's the series of commands when called manually:
aweeeezy  ⋯  make
rm -f *.o assembler test-assembler core
gcc -g -std=gnu99 -Wall -o assembler assembler.c src/utils.c src/tables.c src/translate_utils.c src/translate.c
aweeeezy  ⋯  ./assembler input/simple.s inter.txt out.txt
Running pass one: input/simple.s -> inter.txt
Running pass two: inter.txt -> out.txt
Assembly operation completed successfully.
aweeeezy  ⋯  diff inter.txt out/ref/simple_ref.int
aweeeezy  ⋯  
When you use popen(), you're launching subprocesses which run at the same time as your program. In the code fragment you showed, the subprocesses will all be running around the same time without coordination.
To replicate the command line behavior, you want to wait until each subprocess is done; which is to say, call pclose() before moving to the next stages of your process. For examples, check something like "Pipes the easy way!" at http://www.tldp.org/LDP/lpg/node12.html

Finding which file defines extern value

I am using raspberry PI to run some assembler code on GPU.
It works like this: you assemble the code into binary file. Then you include it into a C code which pushes data into the GPU. This binary file is defined as
extern uint32_t arrayOfCode[];
However I can not find where is this code included(it is not in any other include files).
The whole code can be found here
Upon running makefile it works.
Where the problem comes is when I am trying to build it as MEX function in Matlab.
Matlab cannot find where is the assembler binary code defined. Thus I have a suspicion that it must be linked somehow in Makefile since that's the only difference in building it.
Does anyone has an idea how to find where is this extern value defined ?
==EDIT 1==
I posted my one solution how to build this into a Matlab library.
But the question remains more or less the same. How this makefile
CXX=g++
ASMSRCS := gemm_float.asm
ASMOBJS := $(subst .asm,.do,$(ASMSRCS))
CPPSRCS := $(shell find . -name '*.cpp' -not -name '._*')
CPPOBJS := $(subst .cpp,.o,$(CPPSRCS))
CPPFLAGS=-Ofast -DTARGET_PI -march=armv6 \
-mfloat-abi=hard \
-ftree-vectorize \
-funroll-all-loops \
-mfpu=vfp \
%.cdat: %.asm helpers.asm
m4 $< | qpu-asm -o $(basename $#).cdat -c g_$(basename $#)Code
%.do: %.cdat
$(CXX) $(CPPFLAGS) -x c -c $< -o $(basename $#).do
%.o: %.cpp
$(CXX) $(CPPFLAGS) -fPIC -c $< -o $(basename $#).o
gemm: $(CPPOBJS) $(ASMOBJS)
g++ -g -O3 -o gemm $(CPPOBJS) $(ASMOBJS) -lblas
Could include "gemm_float.asm" assembled code into the C array defined with the keyword extern. I read that these "%." rules in makefile are rules for dependencies. Okay, that would mean that "gemm" would build anew if I changed something in files that "gemm" depends on. Or I might not understand makefiles well enough.
I was able to fix the issue by separately building C code and assembler code. This is for anyone who cannot use an original makefile for some reason(mine was trying to build this into a mex Matlab library).
First, we build code.asm into binary file
m4 code.asm | ./qpu-asm -o code.bin
Now we have to adjust our C code in such a way that it loads .bin code in it's main function. I used a function from eman's tutorial which simply reads the assembler code from a bin file and saves it into an array for later use.
int loadQPUCode(const char *fname, unsigned int* buffer, int len)
{
FILE *in = fopen(fname, "r");
if (!in) {
fprintf(stderr, "Failed to open %s.\n", fname);
return -1;
}
size_t items = fread(buffer, sizeof(unsigned int), len, in);
fclose(in);
return items * sizeof(unsigned int);
}
Then it is enough to call call this before using any gpu related function.
loadQPUCode("asmCode.bin",arrayOfCode,CONSTANT_RELATIVE_TO_ASMCODE);
With this adjusted C code and binary assembler code I was able to build Matlab library using matlab mex function.
mex main.cpp include1.cpp include2.cpp

How can I use an Ada module in a Perl program using XS?

I started learning Ada recently and knowing that Ada and C object files can be linked together to build a multilingual program or library, is it possible to call Ada code from Perl using XS?
Yes!
In fact, any language that can be called from C can be used from Perl using XS. Here's a solution to how to do it with an Ada module and ExtUtils::MakeMaker.
Setting things up
Module tree
Let's start by creating a module tree using h2xs:
$ h2xs -A -n MyAdaModule
Then let's create a subdirectory to hold our Ada files:
$ cd MyAdaModule
$ mkdir src
Here is the module's specification: src/hello.ads
procedure hello;
... and the body: src/hello.adb
with Ada.Text_IO;
use Ada.Text_IO;
procedure hello is
begin
Put_Line("Hi from Ada!");
end;
Don't forget to update the MANIFEST.
Writing the XS file
Let's write the body of MyAdaModule.xs now. It's pretty much like using a function from a C library:
#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
extern void adainit();
extern void adafinal();
MODULE = MyAdaModule PACKAGE = MyAdaModule
void say_hello()
CODE:
adainit();
hello();
adafinal();
From the gnat documentation we know that we need to call adainit() and adafinal() to initialise and then clean up. These calls surround hello() here but they would probably be in a better place in some other function in your XS file. They would then be called from a BEGIN and END block in your Perl module.
Time to compile!
Ada library
First, we don't want to delegate all the magic linking and binding to MakeMaker so let's create a makefile in the src/ directory that will compile our Ada code into a static library.
To make this library, hello.a, we just have to follow the gnat documentation:
use gnatmake -c to generate a hello.ali and a hello.o;
use hello.ali with gnatbind with the -n switch. This will generate b~hello.adb and b~hello.ads which contain binding code;
compile b~hello.adb into an object file: b~hello.o.
group hello.o and b~hello.o together into an archive with ar
So, in short, we will use this makefile:
all: hello.a
hello.a: hello.o b~hello.o
ar rcs $# $^
hello.o: hello.adb hello.ads
gnatmake -c -o $# $<
b~hello.o: b~hello.adb b~hello.ads
gnatmake -c -o $# $<
b~hello.adb: hello.ali
gnatbind -n $<
hello.ali: hello.o
clean:
rm -rf *.o *.ali *.a b~*
Don't forget to update the MANIFEST.
Makefile.PL
Finally, the MakeFile.PL file needs some editing. It has to call the above makefile to build our library and then use it in the final linking phase. This is done by setting MYEXTLIB to src/hello.a and by adding a rule in the postamble section.
In our case, we also need to link with libgnat (for Ada.Text_IO) which should reside somewhere on your system. This is done by editing LIBS. In this example the path is hardcoded but you should probably figure out a more portable way to find libgnat.
use 5.018001;
use ExtUtils::MakeMaker;
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
WriteMakefile(
NAME => 'MyAdaModule',
VERSION_FROM => 'lib/MyAdaModule.pm', # finds $VERSION
PREREQ_PM => {}, # e.g., Module::Name => 1.1
($] >= 5.005 ? # Add these new keywords supported since 5.005
(ABSTRACT_FROM => 'lib/MyAdaModule.pm', # retrieve abstract from module
AUTHOR => 'A. U. Thor <author#nonet>') : ()),
DEFINE => '', # e.g., '-DHAVE_SOMETHING'
INC => '-I.', # e.g., '-I. -I/usr/include/other'
LIBS => ['-L/usr/lib/gcc/i686-pc-linux-gnu/4.8.2/adalib/ -lgnat'],
MYEXTLIB => 'src/hello.a',
);
sub MY::postamble {
join("\n",
"\$(MYEXTLIB)::",
"\tmake -C src/",
"",
"clean::",
"\tmake -C src/ clean",
);
}
Now try
$ perl Makefile.PL
$ make
$ make test
And surprise: the test doesn't pass! The hello() symbol doesn't exist. Inspecting the MyAdaLib.so generated by make with the nm tool reveals that some symbols have been renamed. In my case, they were prefixed with _ada_. So I'd have to call _ada_hello() instead of hello(). This can be corrected in src/ada.ads using the Export pragma:
pragma Export
(Convention => C,
Entity => hello,
External_Name => "hello" );
From what I understood, this should be done for all public symbols as it ensures the representation of types, records, etc, is understood from a C program.
Now, you should be able to call hello() from the XSUB. Enjoy!