Howto get include directories (ruby.h) for Linux Ruby C extension project? - c

I'm using scons to build a linux C based ruby extension. What is the "right" way to get the include paths right? By "right" I mean it works out of the box on 1.9 and 1.8.
I don't want to use the mkmf/Makefile solution.
Thanks! Dave

If you were using autoconf, you could borrow ruby.ac from rice:
http://github.com/jameskilton/rice/blob/master/ruby.ac
or since you are using a different build system, you can duplicate its behavior. To summarize what it does:
We use the rbconfig module to get ruby config variables like this:
$RUBY -rrbconfig -e "puts(Config::CONFIG['$1'] || '')" <variable>
where $RUBY is the ruby interpreter (sometimes interpreters get installed with a different name, e.g. ruby1.8 or ruby1.9) and <variable> is the desired config variable
We then set our build variables:
if ${ruby_config_rubyhdrdir} is empty: (e.g. ruby 1.8)
CPPFLAGS="-I${ruby_config_archdir}
else:
CPPFLAGS="-I${ruby_config_rubyhdrdir} ${ruby_config_rubyhdrdir}/${arch}
CFLAGS="${ruby_config_CFLAGS} ${ruby_config_CCDLFLAGS}"
LDFLAGS="-L${ruby_config_archdir} -L${ruby_config_libdir} ${ruby_config_LDFLAGS}"
LIBS="${ruby_config_LIBS} ${ruby_config_DLDLIBS}"
where the variables ${ruby_config_*} are determined using the config command above, e.g.:
ruby_config_foo=$RUBY -rrbconfig -e "puts(Config::CONFIG['$1'] || '')" foo
We also need to link with the ruby library, so we append ${ruby_config_LIBRUBYARG}.
The above variables are for compiling and linking; you may also need to install. Ruby library files should be installed to ${ruby_config_sitelibdir}. Ruby extensions should be installed to ${ruby_config_sitearchdir}.
There's also some magic in ruby.ac for building with mingw and linking against the one-click installer on windows (which used to be built with vc6; I'm not sure if it still is or not).

Related

Can the meson project version be assigned dynamically?

I am new to Meson so please forgive me if this is a stupid question.
Simple Version of the Question:
I want to be able to assign a dynamic version number to the meson project version at build time. Essentially meson.project_version()=my_dynamic_var or project( 'my_cool_project', 'c', version : my_dynamic_var') (which of course won't work).
I would rather not pre-process the file if I don't have to.
Some background if anybody cares:
My build system dynamically comes up with a version number for the project. In my case, it is using a bash script. I have no problem getting that version into my top level meson.build file using run_command and scraping stdout from there. I have read that using doing it this way is bad form so if there is another way to do this.. I am all ears.
I am also able to create and pass the correct -DPRODUCT_VERSION="<my_dynamic_var>" via add_global_arguments so I COULD just settle for that.. but I would like the meson project itself to carry the same version for the logs and so I can use meson.project_version() to get the version in subprojects for languages other than c/c++.
The short answer, as noted in comments to the question, appears to be no. There is no direct way to set the version dynamically in the project call.
However, there are some work arounds, and the first looks promising for the simple case:
(1) use meson rewriting capability
$ meson rewrite kwargs set project / version 1.0.0
Then obviously use an environment variable instead of 1.0.0.
(2) write a wrapper script which reads the version from the environment and substitutes it into your meson.build file in the project call.
(3) adopt conan.io and have your meson files generated.
(4) use build options. This option, while not as good as (1) might work for other work flows.
Here's how option (4) works.
create a meson_options.txt file in your meson root directory
add the following line:
option('version', type : 'string', value : '0.0.0', description : 'project version')
then create a meson.build file that reads this option.
project('my_proj', 'cpp')
version = get_option('version')
message(version)
conf_data = configuration_data()
conf_data.set('version', version)
When you go to generate your project, you have an extra step of setting options.
$ meson build && cd build
$ meson configure -Dversion=$BUILD_VERSION
Now the version is available as a build option, then we use a configuration_data object to make it available for substitution into header/source files (which you might want to get it into shared libraries or what not).
configure_file(
input : 'config.hpp.in',
output : 'config.hpp',
configuration : conf_data
)
And config.hpp.in looks something like this:
#pragma once
#include <string>
const static std::string VERSION = "#version#";
When we do the configure_file call, #version# will get substituted for the version string we set in the meson configure step.
So this way is pretty convoluted, but like I said, you may still end up doing some of it, e.g. to print copyright info and what not.
As of 0.60.3 you may directly assign version from run_command which means the following will work without any meson_options.txt.
project('randomName', 'cpp',
version : run_command('git', 'rev-parse', '--short', 'HEAD').stdout().strip(),
default_options : [])
In particular, it is also possible to assign the result of a bash script, simply invoke it instead of git.

Matlab Compiler linking errors (64 bit versus 32 bit)

I have been using the deploytool in Matlab for the past few months in my 2010b 64bit version of Matlab. I just recently found out that I need to create a 32 bit version of my c shared library.
To do this I follow the same methods I had been using previously (pretty much calling the command mcc -W lib:MYLIB -T link:lib -d 'MYOUTPUTFOLDER' -v 'MFILE1' 'MFILE2') in my 2009b 32 version of Matlab. I keep getting the error LNK1811: cannot open input file LIBRARY.obj. I have tried to find this LIBRARY object file but I cannot seem to find it anywhere.
So far I have checked to ensure all of the correct libraries are available (found at $MATLABROOT$\extern\include\win32), I have made sure all of my paths are correct in the compopts.bat file, and I have used the option -T compile:lib which works fine and creates a dll. This would be great but I need a lib file to use later in mbuild.
My current path forward is to take the compopts from my 64 bit version of Matlab (on a different machine) and compare it with my compopts for the 32 bit. I will post if it makes a difference.
To summarize our comments in the question and make it an answer. Here is how I manage to create both x32 and x64 libraries/standalones with mcc.
NB: Maybe there are more elegant solutions to configure deploytool, anyway with brute force I'm sure it works and I can automate global deployment process for my applications ...
Machine setup
Install Matlab x32 and x64 on your machine
Run Matlab x32 and setup compiler options typing msbuild -setup
This will generate a compopts.bat file in ~user\AppData\Roaming\MathWorks\MATLAB\R2013b (path may differ upon your version)
Rename this file to compopts.x32.bat (see later)
Run Matlab x64 and setup compiler options typing msbuild -setup
This will generate a compopts.bat file in ~user\AppData\Roaming\MathWorks\MATLAB\R2013b (!!Overwrites x32!!)
Rename this file to compopts.x64.bat (To workaround file overwrite)
EDIT Just tested ... In R2014b, Matlab does no longer overwrites same compots.bat file ... it now generates two separate MBUILD_C++_win64.xml and MBUILD_C++_win32.xml files (which is a good thing!).
Compilation in x32
Force your compilation script to point to ~matlabx32\bin\win32\mcc.exe and force mcc.exe to use previously saved compopts.x32.bat file using the -f option. Your command line should be something like:
~matlabx32\bin\win32\mcc.exe -f "compopts.x32.bat" ... other mcc options ...
Compilation in x64
Force your compilation script to point to ~matlabx64\bin\win64\mcc.exe and force mcc.exe to use previously saved compopts.x64.bat file using the -f option. Your command line should be something like:
~matlabx64\bin\win64\mcc.exe -f "compopts.x64.bat" ... other mcc options ...

GCC -D equivalent for iarbuild.exe

I have a build machine server I am maintaining which is using Makefiles infrastructure.
As part of that infrastructure, I'm passing a few arguments to the Makefile from the build machine (example: user, build-server name, and various build variables known only when compiling for a specific project).
Some of these variables are aggregated to the code using gcc -D directive
-DSOME_VAR=VAL
I've now been asked to migrate an Iar Project into my build system. That is not a problem in itself, only I can't find any way to introduce preprocessor defines using iarbuild.exe command line tool.
I guess I could use an existing H file and edit it before compiling (using sed for example), but that's an ugly hack I would rather avoid if I can.
How do I properly achieve this with IAR?
I recently solved this using a combination of option #2 and the -varfile argvarfile option to iarbuild.exe. For my case I am controlling the output of cpputest. I need easy to read outputs for IDE builds but junit formatted outputs for build server builds. Here's my setup as an example.
Create a global variable in the IDE. Tools->Configure Custom Argument Variables...
Select global tab. Create group JUNIT. Create variable USE_JUNIT. Set the value to 0.
In the Project->Options->C/C++ Compiler->Preprocessor section add an entry for
JUNIT_OUTPUT=$USE_JUNIT$
In the code use
#if JUNIT_OUTPUT == 1
#define FLAGS "-ojunit"
#else
#define FLAGS "-v"
#endif
Create a file called jUnitOut.txt and put the following into it.
<?xml version="1.0" encoding="iso-8859-1"?>
<iarUserArgVars>
<group active="true" name="JUNIT">
<variable>
<name>USE_JUNIT</name>
<value>1</value>
</variable>
</group>
</iarUserArgVars>
Call iarbuild.exe with the normal options plus -varfile jUnitOut.txt
Some observations
Regarding #1 you don't actually need to create a global variable but when you do IAR creates ...\AppData\Roaming\IAR Embedded Workbench\global.custom_argvars. This file must be present for iarbuild.exe to use the -varfile you provide. Also, you can create workspace variables as well. These are stored in a file in the local project directory. This file can be added to source control so global variables can be avoided. IDE builds use the global and workspace variables while iarbuild will use the -varfile
Regarding #4 I didn't find any documentation on how to format the argvarfile. So, I created a workspace variable in the IDE, found the file it created to store the variable and then cut/pasted from that file into my jUnitOut.txt
To my understanding iarbuild does not support passing such parameters directly.
There are two possibilities that were suggested by IAR support and that both work for me (using 7.40.2):
1) Use a preinclude file
Go to Project->Options->C/C++ Compiler->Preprocessor
Add a preinclude file (e.g. preinclude.h)
Now have your build script generate that preinclude file before starting iarbuild
2) Use "Defined symbols"
Go to Project->Options->C/C++ Compiler->Preprocessor
Add an option to "Defined symbols" and use environment variable, e.g. "SOMEVAR=$_SOMEVAL_$"
On the cmd line, set the environment variable, e.g. "set SOMEVAR=myvalue"
Run iarbuild
The 2nd method is little more elegant, but the build will fail if the environment variable is not set, so I'll probably go with the 1st method.
This may answer your question:
To see the command line parameters, enable the option IAR Embedded Workbench IDE > Tools > Options... > IDE Options > Messages > Show build messages > select 'All'.
which is part of the web page at:
http://supp.iar.com/Support/?Note=47884

how to get doxygen to produce call & caller graphs for c functions

I've spent some time reviewing the docs and going through my doxy config file from end to end. I cut doxygen loose on my config file and it produces documentation and indices for structs and cpp classes but I don't see call or caller graphs for the multitude of c functions in my source tree.
Can anybody tell me how to configure doxygen to produces these call and caller trees ? I do have graphviz installed.
You have to set HAVE_DOT, CALL_GRAPH and CALLER_GRAPH to YES.
Also make sure the path to dot is in your PATH variable.
If that still doesn't work, you might have to set EXTRACT_ALL and/or EXTRACT_STATIC, depending on your functions.
For MacOS users:
Install Doxygen and Graphviz as:
brew install doxygen
brew install graphviz
Go to your project folder, and from Terminal set to this path run
doxygen -g
A doxygen file will be generated, named as Doxyfile. Go ahead and open up this file in any editor and find these parameters and replace their values to YES at their locations:
HAVE_DOT = YES
EXTRACT_ALL = YES
EXTRACT_PRIVATE = YES
EXTRACT_STATIC = YES
CALL_GRAPH = YES
CALLER_GRAPH = YES
DISABLE_INDEX = YES
GENERATE_TREEVIEW = YES
RECURSIVE = YES
You can also set name of your project in this Doxyfile. Save the file and then run this command in the terminal:
doxygen Doxyfile
This will generate two more folders named as html and latex. Go to the html folder and open annotated.html to view all details of your project. You will also view png images of the call graphs embedded in the html that are relevant (to some functions/classes for example).
Setting the path to "dot" (/usr/local/bin/) via the "Expert" tab controls in the GUI did the trick!
doxywizard is also useful. It gives you all the options in a GUI. Selecting any option shows quick help about that option.
You might also be interested in COLLABORATION_GRAPH or GRAPHICAL_HIERARCHY.
Quite convenient.
I had the same problem for my C global functions. Enabling CLANG_ASSISTED_PARSING did help display callgraphs for some functions, yet not all of them.

Injecting mercurial changeset as version information in a C executable

I would like the executables for a project I am working on to have the latest mercurial changeset recorded so that when a user complains about buggy behavior, I can track which version they are using. Some of my executables are Python and others are compiled C. Is there a way to automate this, or can you point me to projects that exhibit solutions that I can look at?
I am using autoconf in my project... in case that makes the solution easier.
Thanks!
Setjmp
A common way to do this is with m4_esyscmd. For example, autoconf distributes a script in build-aux which generates a version number from the git repo and invokes AC_INIT as:
AC_INIT([GNU Autoconf], m4_esyscmd([build-aux/git-version-gen .tarball-version]),
[bug-autoconf#gnu.org])
You can often get away without distributing the script and do something simple like:
AC_INIT([Package name], m4_esyscmd([git describe --dirty | tr -d '\012']),
[bug-report-address])
Instead of git-describe, use whatever command you want to generate the version number. One important detail is that it should not have a trailing newline (hence the tr following git-describe).
A major drawback with this technique is that the version number is only generated when you run autoconf.
Add this to configure.ac:
AM_CONDITIONAL([IS_HG_REPO], [test -d "$srcdir/.hg"])
Add the following lines to Makefile.am:
if IS_HG_REPO
AM_CPPFLAGS = -DHGVERSION="\"$(PACKAGE) `hg parents --template 'hgid: {node|short}'`\""
else
AM_CPPFLAGS = -DHGVERSION=PACKAGE_STRING
endif
This will define HGVERSION as a string of the form APPNAME hgid: 24d0921ee4bd or APPNAME VERSION, if building from a release tarball.
See wiki page on versioning with make

Resources