For some strange reason, ParseConfig does not work, while manually invoking the commands inside work fine.
The following:
test = ['sh', '-c', 'PKG_CONFIG_LIBDIR=/mylib pkg-config --cflags --libs mylib']
env.ParseConfig( test )
print env.get( "CPPPATH" )
env.MergeFlags( env.backtick(test) )
print env.get( "CPPPATH" )
gives me:
None
['/mylib/include']
I seem to miss something obvious here - but cannot find what.
Related
Typical makefile.am, which works, would look like this for my project:
noinst_LTLIBRARIES = libwinsane.la
CLEANFILES = init.cpp
libwinsane_la_CXXFLAGS = \
-I$(top_srcdir)
libwinsane_la_SOURCES = \
init.cpp
noinst_HEADERS = \
init.h
the issue is that I need to also process resource files. I need to use something like this:
noinst_LTLIBRARIES = libwinsane.la
libwinsane.o: init.o manifest.o
ld -relocatable -o $# init.o manifest.o
manifest.o: manifest.rc utf8.xml
windres -o $# manifest.rc
clean:
rm -f init.o manifest.o libwinsane.o
While this last example is valid makefile by itself (except noinst_LIBRARIES), its obviously wrong syntax for automake. But maybe there is a way for automake to just accept it and produce library in the end somehow?
Off the top of my head, and without 100% verifying its consistency with https://www.gnu.org/software/automake/manual/html_node/Program-and-Library-Variables.html or testing it, something like this should work more or less:
CLEANFILES =
noinst_LTLIBRARIES = libwinsane.la
libwinsane_la_SOURCES =
libwinsane_la_SOURCES += init.cpp
libwinsane_la_SOURCES += init.h
libwinsane_la_CXXFLAGS = -I$(top_srcdir)
libwinsane_la_DEPENDENCIES = manifest.$(OBJEXT)
libwinsane_la_LIBADD = manifest.$(OBJEXT)
CLEANFILES += manifest.$(OBJEXT)
manifest.$(OBJEXT): manifest.rc utf8.xml
windres -o $# $(srcdir)/manifest.rc
A few additional remarks:
The windres recipe probably does not work for out of source builds if utf8.xml has not just been buitl in $(builddir) and is therefore located in $(srcdir). Adding something like -I $(srcdir) to the windres command line will probably fix this, but cannot verify that without a MWE.
You will want to make windres configurable and replace the hard coded windres call by $(WINDRES), made user configurable by AC_ARG_VAR and (if $WINDRES has not been set) AC_CHECK_TOOL, and probably protected with a check in configure.ac that $WINDRES actually works. Depending on your project you can then either AC_MSG_ERROR(...) in case $WINDRES does not work, or AM_CONDITIONAL([HAVE_WINDRES], ...) and then put the Makefile.am parts related to manifest.$(OBJEXT) inside a if HAVE_WINDRES / endif conditional. The actual windres command might be called something like x86_64-w64-mingw32-windres when cross-compiling.
Why do you have CLEANFILES += init.cpp? I have left that out, as you do not want make clean to delete your source files. Or does init.cpp belong to BUILT_SOURCES?
Update: Apparently, I have overlooked something for compiling and linking with libtool: cannot build libtool library from non-libtool objects - any workaround?
I'm new to Linux & shell and I'm struggling with checking if the compilation is successful.
g++ code.cpp -o code.o 2>error.txt
if [ ! -e error.txt ]
then
do something
else
echo "Failed to compile"
I guess an error file is created even if the compilation is successful. What is the content of the error file when there is no error? I need to change the if condition to check if the compilation is successful.
It's just the order of things. What happens when the shell parses the string g++ code.cpp -o code.o 2>error.txt is:
The shell creates error.txt, truncating the file if that name already exists.
g++ is called with its error output redirected to the new file.
If g++ does not write any data, then the file remains as it was (empty) at the end of step 1.
You probably aren't so much interested in the error file as you are the return value. You probably ought to just do:
if g++ code.cpp -o code; then : do something; done
or even just:
g++ code .cpp -o code && : do something
but if really want to do something else with the errors, you can do:
if g++ code.cpp -o code.o 2> error.txt; then
rm error.txt
: do something
else
echo >&2 Failed to compile code.cpp.\ See "$(pwd)"/error.txt for details.
fi
Make sure you escape at least one of the spaces after the . so that you get 2 spaces after the period (or just quote the whole argument to echo). Although it's become fashionable lately to claim that you only need one space, all of those arguments rely on the use of variable width fonts and any command line tool worth using will be used most often in an environment where fixed width fonts are still dominant. This last point is totally unrelated to your question, but is worth remembering.
The code snippet is as follows:
$(shell javac $(MY_PATH)/test/TestFile.java)
$(shell java -cp $(MY_PATH)/test/ TestFile)
There is no space or tab in the start. The error i am getting is
* missing separator. Stop.
The error is coming in second line only and not in the first line.
Basically my TestFile is not in java path.
I have tried all the solutions here but none helped me out. I guess the error has something to do with the directory path I provided. The same code snippet works with cmd prompt in windows but not in linux machine. Can't figure the exact problem. Kindly help. Thanks.
This is how makefiles supposed to be used:
.PHONY: run
JAVAC:=javac
JAVA:=java
TARGET:=TestFile
SOURCES:=TestFile.java
OBJS:=$(patsubst %.java, %.class, $(SOURCES))
$(TARGET): $(OBJS)
%.class: %.java
$(JAVAC) $^
run: $(TARGET)
$(JAVA) $(TARGET)
make run will compile and run. make will only compile. Of course it all could be set to one target, but better don't do that.
I'm working on a few multi platform projects that all depend on common framework.
I want to add support for Google Native-Client (NaCl). The way I aproached the problem is first to compile the framework as static library (this is how I've been doing it on all other platforms).
I have to say that I have never used SCons before. I think I start grasping it. Starting from a build.scons from a tutorial I can get some code compiling and linking. Now I would want to skip the linking process but seems like the nacl_env was never intended to compile static libraries.
Reading the SCons help didn't help me much since the Library node is missing from the nacl_env.
I don't think I understand SCons enough to write the whole build process from scratch so I was hopping to not have to do so.
1. Am I approaching the problem correctly?
2. Any tips or sample nacl static libs, build using SCons?
Ok, what I did is way more trickery than what you probably need.
I wanted my static library to handle the initialization steps of the NaCl module, and then call some project-specific function.
I ended up turning my whole framework and the contents of the built-in libppapi_cpp.a into a single .o file, and then that into a single .a file, a static library.
I needed a single .o file, because otherwise I would run into dependency problems releated to initialization, I could not solve.
build_lib.sh (framework):
#!/bin/bash -e
SDK="/home/kalmi/ik/nacl_sdk/pepper_15"
function create_allIn_a {
TMPDIR="`mktemp -d`"
echo $TMPDIR
cp $O_FILES $TMPDIR
pushd $TMPDIR &> /dev/null
$AR x $LIBPPAPI_CPP_A
$LD -Ur * -o ALL.o
$AR rvs $OUTPUT_NAME ALL.o
$RANLIB $OUTPUT_NAME
popd &> /dev/null
}
./scons
BIN_BASE="$SDK/toolchain/linux_x86/bin"
LD="$BIN_BASE/i686-nacl-ld"
AR="$BIN_BASE/i686-nacl-ar"
RANLIB="$BIN_BASE/i686-nacl-ranlib"
LIBPPAPI_CPP_A="$SDK/toolchain/linux_x86_newlib/x86_64-nacl/lib32/libppapi_cpp.a"
O_FILES="`find $(pwd)/opt_x86_32 | grep .o$ | grep --invert-match my_main.o | tr "\n" " "`"
LIBDIR="../../../bin/lib/lib32"
mkdir -p $LIBDIR
if [ -f $LIBDIR/libweb2grid_framework.a ]; then
rm $LIBDIR/libweb2grid_framework.a
fi
OUTPUT_NAME="`readlink -m $LIBDIR/libweb2grid_framework.a`"
create_allIn_a
BIN_BASE="$SDK/toolchain/linux_x86/bin"
LD="$BIN_BASE/x86_64-nacl-ld"
AR="$BIN_BASE/x86_64-nacl-ar"
RANLIB="$BIN_BASE/x86_64-nacl-ranlib"
LIBPPAPI_CPP_A="$SDK/toolchain/linux_x86_newlib/x86_64-nacl/lib64/libppapi_cpp.a"
O_FILES="`find $(pwd)/opt_x86_64 | grep .o$ | grep --invert-match my_main.o | tr "\n" " "`"
LIBDIR="../../../bin/lib/lib64"
mkdir -p $LIBDIR
if [ -f $LIBDIR/libweb2grid_framework.a ]; then
rm $LIBDIR/libweb2grid_framework.a
fi
OUTPUT_NAME="`readlink -m $LIBDIR/libweb2grid_framework.a`"
create_allIn_a
./scons -c
The my_main.o file is excluded from the static library, because that file contains the function that is to be provided by the project that uses this framework.
The build.scons file for the framework is truly ordinary.
build.scons (for some project that uses this framework):
#! -*- python -*-
#What to compile:
sources = [ 'src/something.cpp', 'src/something_helper.cpp' ]
###############################################################x
import make_nacl_env
import nacl_utils
import os
nacl_env = make_nacl_env.NaClEnvironment(
use_c_plus_plus_libs=False,
nacl_platform=os.getenv('NACL_TARGET_PLATFORM'))
nacl_env.Append(
# Add a CPPPATH that enables the full-path #include directives, such as
# #include "examples/sine_synth/sine_synth.h"
CPPPATH=[os.path.dirname(os.path.dirname(os.path.dirname(os.getcwd())))],
LIBS=['web2grid_framework','srpc'],
LIBPATH=['../../../bin/lib/lib32','../../../bin/lib/lib64'],
LINKFLAGS=['-pthread']
)
nacl_env.AllNaClModules(sources, 'client')
Some lines worth highlighting:
use_c_plus_plus_libs=False,
LIBS=['web2grid_framework','srpc'],
LIBPATH=['../../../bin/lib/lib32','../../../bin/lib/lib64'],
LINKFLAGS=['-pthread']
I am not saying that this is a clean method, but it gets the job done.
So, there's two questions here
1. Using SCONS:
NaCl uses SCONS for it's examples, simply to help compiling of the examples easier. In reality, SCONS simply directs to the GCC/G++ compilers in the SDK build directories. (SCONS will take the input scripts, and create the final param string to send to GCC)
GCC is a common compiler, and is well documented on the net : http://gcc.gnu.org/
How you integrate NaCl compilation into your work-flow is up to you (ie you're not forced to use SCONS).
For instance, if you'd like to go to GCC directly, you can simply call :
<path to bin>/x86_64-nacl-gcc -m64 -o test.nexe main.c
For a more detailed look into how to compile NaCl modules, please read the documentation # gonacl.com on compiling which will detail how to compile with and without SCONS.
2.Compilng Static libs with GCC
Here is an example : http://www.adp-gmbh.ch/cpp/gcc/create_lib.html
~Main
In Linux I am trying to compile something that uses the -fwritable-strings option. Apparently this is a gcc option that doesn't work in newer version of gcc. I installed gcc-3.4 on my system, but I think the newer version is still being used because I'm still get the error that says it can't recognize the command line option -fwritable-strings. How can I get make to use the older version of gcc?
You say nothing about the build system in use, but usually old versions of gcc can be invoked explicitly, by something like (this is for an autotools-based build):
./configure CXX=g++-3.4 CC=gcc-3.4
For a make-based build system, sometimes this will work:
make CXX=g++-3.4 CC=gcc-3.4
Most makefiles ought to recognise overriding CC and CXX in this way.
If editing the configuration/Makefile is not an option, Linux includes a utility called update-alternatives for such situations. However, it's a pain to use (links to various tutorials included below).
This is a little simpler - here's a script (from here) to easily switch your default gcc/g++ version:
#!/bin/bash
usage() {
echo
echo Sets the default version of gcc, g++, etc
echo Usage:
echo
echo " gcc-set-default-version <VERSION>"
echo
exit
}
cd /usr/bin
if [ -z $1 ] ; then
usage;
fi
set_default() {
if [ -e "$1-$2" ] ; then
echo $1-$2 is now the default
ln -sf $1-$2 $1
else
echo $1-$2 is not installed
fi
}
for i in gcc cpp g++ gcov gccbug ; do
set_default $i $1
done
If you 1) name this script switch-gcc, 2) put it in your path, and 3) make it executable (chmod +x switch-gcc), you can then switch compiler versions just by running
sudo switch-gcc 3.2
Further reading on update-alternatives:
https://lektiondestages.blogspot.com/2013/05/installing-and-switching-gccg-versions.html
https://codeyarns.com/2015/02/26/how-to-switch-gcc-version-using-update-alternatives/
https://askubuntu.com/questions/26498/choose-gcc-and-g-version
Maybe you could just give the whole path of the gcc-3.4 install while compiling your program:
/path_to_gcc_3.4/gcc your_program
If you can find where the writeable strings are actually being used, another possibility would be to use strdup and free on the subset of literal strings that the code is actually editing. This might be more complicated than downgrading versions of GCC, but will make the code much more portable.
Edit
In response to the clarification question / comment below, if you saw something like:
char* str = "XXX";
str[1] = 'Y';
str[2] = 'Z';
// ... use of str ...
You would replace the above with something like:
char* str = strdup("XXX");
str[1] = 'Y';
str[2] = 'Z';
// ... use of str ...
free(str);
And where you previously had:
char* str = "Some string that isn't modified";
You would replace the above with:
const char* str = "Some string that isn't modified";
Assuming you made these fixes, "-fwritable-strings" would no longer be necessary.