I'm creating an R package that uses a third-party (closed-source) API for importing .edf files into R (from SR Research Eyelink eye trackers). Someone who has already gotten this to work in Linux has shared his code, and I was able to get it to work on Mac. It was a matter of changing the src/Makevars files to point to the API as it's installed on the mac:
PKG_LIBS=-framework edfapi -F/Library/Frameworks/
To make it work in linux, Makevars needs to have:
PKG_LIBS=-L/usr/local/lib -ledfapi -lm
I know that for windows-specific options, I need to create a Makevars.win file, but how do I have the build options change for Mac versus Linux? I would like to do something like:
if [[ `uname` -eq Darwin ]] ; then
PKG_LIBS=-framework edfapi -F/Library/Frameworks/
fi
if [[ `uname` -eq Linux ]] ;then
PKG_LIBS=-L/usr/local/lib -ledfapi -lm
fi
but putting this into Makevars doesn't work. From researching this it seems that I need a combination of setting options in configure and Makevars, but I haven't quite figured it out. I am comfortable with R programming and know just enough C++ to make some basic functions, but I still don't understand all the nuances involved in the building process. If someone could explain the main purpose of configure/configure.ac versus Makevars/Makevars.in that would be helpful as well.
Ideally I would like to bundle the API along with the R package and have the different versions in a platform-specific folder. The API consists of just 3 header files and a binary (and it rarely changes). I realize this would prevent me from putting the package on CRAN but that is fine. I've managed to successfully build the package with the API files in a different folder, but at runtime it still looks for it in the standard spot (/Library/Frameworks). I realize this is a more loaded question and I can create a separate post as well.
This post helped me figure it out: stackoverflow.com/a/32590600/1457051
configure (in the package root directory) looks like this:
#!/bin/bash
#make the Makevars file
if [ ! -e "./src/Makevars" ]; then
touch ./src/Makevars
fi
#if mac
if [[ `uname` -eq Darwin ]] ; then
echo "PKG_LIBS=-framework edfapi -F/Library/Frameworks/" > ./src/Makevars
#if linux
elif [[ `uname` -eq Linux ]] ;then
echo "PKG_LIBS=-L/usr/local/lib -ledfapi -lm" > ./src/Makevars
fi
Makevars is created and the appropriate options are added based on the platform. There may be a more direct solution, but this works for my purposes.
Related
In a regular VisualStudio project you can setup the precompiled header by going to Configuration Properties -> C/C++ -> Precompiled Headers.
However, when dealing with a Cross Platform (Linux) project, the Precompiled Header option is missing.
Is there any way to configure the Precompiled Header?
Apparently in VisualStudio 2022 there's still no easy way to add support for precompiled headers. But luckily I've stumbled upon on this interesting solution provided by GTANAdam on his Github page: https://gist.github.com/GTANAdam/3703fd5cb70d9a22159f58443a129f8b
With some minor changes I've managed to make things work for my projects.
The chmod +x precompile.sh is needed, else you might get the error bash: ./precompile.sh: Permission denied
And instead of using the suggested sh precompile.sh I've ended up using ./precompile.sh. Additionally the precompile.sh file now contains the header #!/bin/bash (instead of #!/bin/sh)
Sample of my precompile.sh file:
#!/bin/bash
gch="PCH.hpp.gch"
header="PCH.hpp"
function compile
{
echo "Generating precompiled header.."
g++ -I../ -std=c++14 -c -x c++-header PCH.cpp -o PCH.hpp.gch
}
if [[ -f $gch ]]; then # File exists
if [[ $header -nt $gch ]]; then
compile
else
echo "Precompiled header already exists.."
fi
else
compile
fi
Some things to note. If you're editing your bash script file on windows platform, note that on windows, at every new line of the script, the text editors might add CR LF instead of just LF, and Linux bash might start dropping errors like: : not foundsh: 2: precompile.sh:
I've recently started using a lightweight IDE called Geany. It's really efficient, very light on resources and has all the basic functionality I need. It has built in syntax highlighting for lots of programming languages including C++ which I'm coding in, however some of the highlighting doesn't seem to function properly.
Looking at the above screenshot I took, you can see that there is some syntax highlighting going, however the user declared function "addition" has no colouring applied to it, even after changing its colour in the configuration files. I found out that when I change the colour of "operator" in the configuration file, it changes every semicolon, bracket etc. to that colour, so clearly the dectection there isn't great.
I think this issue is due to the way the syntax highlighter works, which I believe is scintilla looking at the Geany GitHub source files. Here is the lexer file specifically for C++: https://github.com/geany/geany/blob/master/scintilla/lexers/LexCPP.cxx
I have a few questions:
Can the lexer file for C++ be updated with a better one so it can actually detect user defined functions as well as other parts of the language?
Is there a way of viewing all the different syntax's that scintilla picks up on (string, operator, preprocessor etc.)?
Are there any better syntax highlighters that could be possibly integrated into Geany?
I made an external plugin that enable surgical filetype editing, with color selectors.
https://github.com/webdev23/Geany-editor-dynamic-color-schemes
It is dynamically editing the filetypes.xml config.
Thinking to make the capability to import highlight themes from some other editor. Doable from this base.
Otherwise, one line install + all plugins, all themes, config completions:
sudo apt install geany geany-plugins &&
curl -o geany-themes-master.zip https://codeload.github.com/codebrainz/geany-themes/zip/master && unzip geany-themes-master.zip && cd geany-themes-master && ./install.sh &&
curl -o geany16.zip https://codeload.github.com/RobLoach/base16-geany/zip/master && unzip geany16.zip && echo -e "Config written. Close Geany to apply." > ~/info_geany.txt && cd base16-geany-master && find . -type f -name "*.conf" -exec cp -n {} ~/.config/geany/colorschemes/ \; &&
geany ~/info_geany.txt && rm ~/info_geany.txt && sed -i 's/autocomplete_doc_words=false/autocomplete_doc_words=true/' ~/.config/geany/geany.conf && sed -i 's/pref_editor_tab_width=4/pref_editor_tab_width=2/' ~/.config/geany/geany.conf && sed -i 's/symbolcompletion_min_chars=4/symbolcompletion_min_chars=2/' ~/.config/geany/geany.conf && sed -i 's/pref_editor_tab_width=4/pref_editor_tab_width=2/' ~/.config/geany/geany.conf && sed -i 's/color_scheme=/color_scheme=base16-atelierlakeside.dark.conf/' ~/.config/geany/geany.conf && echo "Install done."
I followed all the steps successfully as mention in the Qt documentation:
Qt for Linux/X11 - Building from Source
Qt for Linux/X11 -
Deployment
But I still couldn't make static Qt application, the executable generated by the above documented steps still needs Qt shared objects on other system.
Any ideas?
You need to deploy the application, for this purpose I use the utility
cqtdeployer
This utility itself collects all the necessary dependencies of your application and you do not have to spend your time on it, or you can automate this process.
You can install from github releases (Windows)
or
from snapstore (Linux)
sudo snap install cqtdeployer
You can use as follows:
Windows:
%cqtdeployer% -bin myApp -qmake path/to/Qt/5.x.x/build/bin/qmake.exe -qmlDir path/to/my/qml/files/dir
Linux:
cqtdeployer -bin myApp -qmake path/to/Qt/5.x.x/build/bin/qmake -qmlDir path/to/my/qml/files/dir
path/to/Qt/5.x.x/build/bin/qmake - This is the way qmake is used to build your program.
path/to/my/qml/files/dir - this is the path directly to your qml file (which you wrote)
And Run application with sh script (Linux) or exe (Windows)
If you'll use the version from snap then make sure that you have all the permissions.
If you need use windows version just install application from installer
Updated
If you want create a simple installer for you application just add qif option for command of cqtdeployer.
Example :
cqtdeployer -bin myApp -qmake path/to/Qt/5.x.x/build/bin/qmake -qmlDir path/to/my/qml/files/dir qif
Details on all the intricacies of cqtdeployer can be found on the official wiki project.
The best way to deploy your application is not necessarily to statically link it for the following reasons:
LGPL licencing means that your application must now be made public and may not sold (I think) - i.e. since its statically linked and the qt libs are within your executable your executable is now part of the open source.
Its a massive pain in the arse... I have gone around this loop and know the pain well.
Installing qt-everywhere is also not so great, I just don't see how you can garantee that the libraries will be the same version as the ones that your program needs.
So what I started to do was create my own script to deploy qt for me. The basic "jist" of this is that you use ldd to find out which qt libraries you need and copy them into a sub folder (./lib) within the same folder as your executable to make an install bundle.
Note: on Windows there is a deployqt application which does somthing similar (can't remember exactly what it is called).
Below I have copied a version of my deploy script. Note that it is quite old now, but I don't see why it should not work (its not written particularly well), but if not it will give you a start place. Also look out for the plugin's. In this script I have added code to copy the audio plugin since I was using that. If you are using other plugins then you will need to copy those (they are usually in sub dir's of the qt libs like .../audio)... I had a todo to try to figure out what plugins are needed from the .pro file but I never got around to that (I would have to pass in the .pro file to this script as well)...
To run, just run this script and pass in the directory that your executable lives in.
#!/bin/bash
# Rememeber start dir
START_DIR=$PWD
# Determine which dir to deploy in and cd to that dir
if [ -d "$1" ]; then
DEPLOY_DIR=$1
else
DEPLOY_DIR=$PWD
fi
echo "Deploy dir: $DEPLOY_DIR"
cd $DEPLOY_DIR
# Run ldd on all files in the directory and create a list of required qt libs
flag=false
for entry in `ldd $DEPLOY_DIR/* | grep -i qt`; do
if $flag; then
# Only add to the array if it is not already in it
if ! [[ $libsArray =~ $entry ]]; then
echo "adding $entry"
libsArray="$libsArray $entry"
fi
flag=false
fi
# If we see a "=>" then the next line will be a library
if [ $entry == "=>" ]; then
flag=true
fi
done
echo
echo
# Create the required folder structure. Note here we are need the qt audio plugin so we are going to manually copy that as well.
mkdir -p lib
mkdir -p lib/audio
# Now copy these files to the deploy directory
for entry in $libsArray; do
echo "cp -v -f $entry $DEPLOY_DIR/lib"
cp -v -f $entry $DEPLOY_DIR/lib
done
# Now get the audio lib - this is a plugin that we are using so we need these libs as well.
# Add other plugins here as well.
# TODO: maybe we can read this in from the *.pro file.
cp -v -f `qmake -query QT_INSTALL_BINS`/../plugins/audio/* $DEPLOY_DIR/lib/audio
# Go back to start dir
cd $START_DIR
Once you have all the files you need you should be able to copy the whole lot to another PC and run it. Note: you may have to set the export LD_LIBRARY_PATH=<path-to-libs> so that the libs can be found... or install the libs into somewhere like /usr/lib/your-appplication/.
But installing libs is another question/subject!
My job mostly consists of engineering analysis, but I find myself distributing code more and more frequently among my colleagues. A big pain is that not every user is proficient in the intricacies of compiling source code, and I cannot distribute executables.
I've been working with C++ using Boost, and the problem is that I cannot request every sysadmin of every network to install the libraries. Instead, I want to distribute a single source file (or as few as possible) so that the user can g++ source.c -o program.
So, the question is: can you pack the Boost libraries with your code, and end up with a single file? I am talking about the Boost libraries which are "headers only" or "templates only".
As an inspiration, please look at the distribution of SQlite or the Lemon Parser Generator; the author amalgamates the stuff into a single source file which is trivial to compile.
Thank you.
Edit:
A related question in SO is for Windows environment. I work in Linux.
There is a utility that comes with boost called bcp, that can scan your source and extract any boost header files that are used from the boost source. I've setup a script that does this extraction into our source tree, so that we can package the source that we need along with our code. It will also copy the boost source files for a couple of boost libraries that we use that are no header only, which are then compiled directly into our applications.
This is done once, and then anybody who uses the code doesn't even need to know that it depends on boost. Here is what we use. It will also build bjam and bcp, if they haven't been build already.
#!/bin/sh
BOOST_SRC=.../boost_1_43_0
DEST_DIR=../src/boost
TOOLSET=
if ( test `uname` = "Darwin") then
TOOLSET="--toolset=darwin"
fi
# make bcp if necessary
if ( ! test -x $BOOST_SRC/dist/bin/bcp ) then
if ( test -x $BOOST_SRC/tools/jam/*/bin.*/bjam ) then
BJAM=$BOOST_SRC/tools/jam/*/bin.*/bjam
else
echo "### Building bjam"
pushd $BOOST_SRC/tools/jam
./build_dist.sh
popd
if ( test -x $BOOST_SRC/tools/jam/*/bin.*/bjam ) then
BJAM=$BOOST_SRC/tools/jam/*/bin.*/bjam
fi
fi
echo "BJAM: $BJAM"
pushd $BOOST_SRC/tools/bcp
echo "### Building bcp"
echo "$BJAM $TOOLSET"
$BJAM $TOOLSET
if [ $? == "0" ]; then
exit 1;
fi
popd
fi
if ( ! test -x $BOOST_SRC/dist/bin/bcp) then
echo "### Couldn't find bpc"
exit 1;
fi
mkdir -p $DEST_DIR
echo "### Copying boost source"
MAKEFILEAM=$DEST_DIR/libs/Makefile.am
rm $MAKEFILEAM
# Signals
# copy source libraries
mkdir -p $DEST_DIR/libs/signals/src
cp $BOOST_SRC/libs/signals/src/* $DEST_DIR/libs/signals/src/.
echo -n "boost_sources += " >> $MAKEFILEAM
for f in `ls $DEST_DIR/libs/signals/src | fgrep .cpp`; do
echo -n "boost/libs/signals/src/$f " >> $MAKEFILEAM
done
echo >> $MAKEFILEAM
echo "### Extracting boost includes"
$BOOST_SRC/dist/bin/bcp --scan --boost=$BOOST_SRC ../src/*/*.[Ch] ../src/boost/libs/*/src/*.cpp ../src/smart_assert/smart_assert/priv/fwd/*.hpp $DEST_DIR
if [ $? != "0" ]; then
echo "### bcp failed"
rm -rf $DEST_DIR
exit 1;
fi
Have you considered just writing a build script for a build system like SCons?
You could write a python script to download boost, unpack it compile the needed files (you can even run bjam if needed) and compile your own code.
The only dependency your colleagues will need is Python and SCons.
Run the preprocessor on your code and save the output. If you started with one main.cpp with a bunch of includes in it, you will end up with one file where all of the includes have been sucked in. If you have multiple cpp files, you will have to concatinate them together and then run the preprocessor on the concatinated file, this should work as long as you don't have any duplicate global symbol names.
For a more portable method, do what sqlite does and write your own script to just combine and concatinate together the files you created+boost, and not get the system includes. See mksqlite3c.tcl in the sqlite code
http://www2.sqlite.org/src/finfo?name=tool/mksqlite3c.tcl
Why not just check in all the necessary files to SVN, and send you co-workers the URL of the repository? Then they can check out the code whenever they want to, do an 'svn up' any time they want to update to the latest version, etc.
If you're on a Debian-derived variety of Linux, well problems like this just shouldn't come up: let the packaging system and policy manual do the work. Just make it clear that the libboost-dev or whatever package is a build-dependency of your code and needs to be installed beforehand, and then /usr/include/boost should be right there where your code expects to find it. If you're using a more recent version of boost than the distro ships, it's probably worth figuring out how to package it yourself and work within the existing packaging/dependencies framework rather than reinventing another one.
I'm not familiar enough with .rpm based distros to comment on how things work there. But knowing I can easily setup exactly the build environment I need is, for me, one of the biggest advantages of Debian based development over Windows.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 7 years ago.
Improve this question
Is it allowed by the Boost License to just add the source code of the stuff I need to my project (accompanied by the license of course?). I couldn't find any "descriptive" confirmation. I would have seperate Include/boost and Source/boost directories for easy access.
PS: Seeing as boost::filesystem is going into C++0x TR2, and lambda, regex and whatnot are already in c++0x TR1, I don't see any reason to be juggling with C functions like realpath, getcwd and the like. They don't work well anyways...
UPDATE: I'm adding the required files "one-by-one" folder by folder, but the amount is gigantic. Maybe it's better to include the full boost dist....
Yes you can do that. The license is very liberal. The only condition is that if you redistribute your software in source form you need to include a complete copy of the license.
There is a utility that comes with boost called bcp, that can scan your source and extract any boost header files that are used from the boost source. I've setup a script that does this extraction into our source tree, so that we can package the source that we need along with our code. It will also copy the boost source files for a couple of boost libraries that we use that are no header only, which are then compiled directly into our applications. This makes it easy to rerun the script whenever there is a new version of boost released.
For reference, here is what we use
#!/bin/sh
BOOST_SRC=.../boost_1_43_0
DEST_DIR=../src/boost
TOOLSET=
if ( test uname = "Darwin") then
TOOLSET="--toolset=darwin"
fi
# make bcp if necessary
if ( ! test -x $BOOST_SRC/dist/bin/bcp ) then
if ( test -x $BOOST_SRC/tools/jam/*/bin.*/bjam ) then
BJAM=$BOOST_SRC/tools/jam/*/bin.*/bjam
else
echo "### Building bjam"
pushd $BOOST_SRC/tools/jam
./build_dist.sh
popd
if ( test -x $BOOST_SRC/tools/jam/*/bin.*/bjam ) then
BJAM=$BOOST_SRC/tools/jam/*/bin.*/bjam
fi
fi
echo "BJAM: $BJAM"
pushd $BOOST_SRC/tools/bcp
echo "### Building bcp"
echo "$BJAM $TOOLSET"
$BJAM $TOOLSET
if [ $? == "0" ]; then
exit 1;
fi
popd
fi
if ( ! test -x $BOOST_SRC/dist/bin/bcp) then
echo "### Couldn't find bpc"
exit 1;
fi
mkdir -p $DEST_DIR
echo "### Copying boost source"
MAKEFILEAM=$DEST_DIR/libs/Makefile.am
rm $MAKEFILEAM
# copy source libraries
mkdir -p $DEST_DIR/libs/signals/src
cp $BOOST_SRC/libs/signals/src/* $DEST_DIR/libs/signals/src/.
echo -n "boost_sources += " >> $MAKEFILEAM
for f in `ls $DEST_DIR/libs/signals/src | fgrep .cpp`; do
echo -n "boost/libs/signals/src/$f " >> $MAKEFILEAM
done
echo >> $MAKEFILEAM
echo "### Extracting boost includes"
$BOOST_SRC/dist/bin/bcp --scan --boost=$BOOST_SRC ../src/*/*.[Ch] $DEST_DIR
if [ $? != "0" ]; then
echo "### bcp failed"
rm -rf $DEST_DIR
exit 1;
fi
i would recommend linking to boost externally instead of include the source directly into your projects.
beside the huge spiderweb dependency issue, linking them externally mean you can always refer to latest stable build (assume u checkout from the repository) without explicitly overwrite each old source in your project.