The (R) program I'm writing is at one point able to write C source code files containing OpenMP instructions in order to speed up the resulting program (these files mainly contain a set of differential equations whose results are written to an array - as these steps can be executed independently, I thought it to be a good idea to parallelize them using omp sections). As the files generated this way are supposed to be used in another part of my program I also use R to compile them using system(R CMD SHLIB...) at runtime, as this approach seemed to have the advantage that, using R CMD SHLIB, no specific compiler would need to be imposed on the user.
The problem I'm now facing is that I can't pass the -fopenmp (or -openmp) compiler directive to R CMD SHLIB and it is not possible to use a Makevars file providing additional compiler flags (or ideally $SHLIB_OPENMP_CFLAGS) when not building an R package - which I'm not doing in this case, so R CMD SHLIB compiles the file I give it. Without OpenMP paralellization, however, as I see no way how to pass the according flags to SHLIB in this situation.
Is there any possibility to use R CMD SHLIB for this task anyway or will I have to sacrifice portability by internally specifying a compiler for OpenMP compilation?
You can also do it in R with:
system("R CMD COMPILE filename.c CFLAGS=-fopenmp")
system("R CMD SHLIB filename.o")
If you must use R CMD SHLIB as opposed to a Makefile or package, I think you want to modify an environment variable such as PKG_CPPFLAGS or PKG_CXXFLAGS, which you can from inside R via Sys.setenv().
R itself now uses OpenMP and the compiler option you desire is available on recent R systems:
edd#max:~$ grep OPENMP /etc/R/Makeconf
SHLIB_OPENMP_CFLAGS = -fopenmp
SHLIB_OPENMP_CXXFLAGS = -fopenmp
SHLIB_OPENMP_FCFLAGS = -fopenmp
SHLIB_OPENMP_FFLAGS = -fopenmp
edd#max:~$
That's from a standard R 2.15.1 on a Debian / Ubuntu system.
Related
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.
I am trying to call a C code from Julia v0.6.2, Windows 10.
Here is the C code I compiled into a DLL with Cygwin gcc.
int timesTwo(int x) {
return 2*x;
}
The compile commands:
gcc -c mydll.c
gcc -shared -o mydll.dll mydll.o
I tested the DLL with a test C program and it works. Then I tried to call it with Julia using an absolute path to the DLL.
using Base.Libdl
x = Int32(2)
mylib = dlopen("C:\\Users\\pedro\\Documents\\codigos\\exampleDLL\\C\\mydll.dll")
ccall((:timesTwo, mylib), Int32, (Int32,), x)
Then the Julia's Workspace is restarted (all variables become undefined as soon as I use the command dlopen).
What is happening and how can I solve it?
Update
That must be a windows issue. Could not reproduce in an Ubuntu distro.
I would try to use the same compiler that Julia uses (with the -fPIC flag) to build your DLL. On Windows, julia is actually build with the
Cygwin-to-MinGW cross-compiler:
https://github.com/JuliaLang/julia/blob/master/README.windows.md#cygwin-to-mingw-cross-compiling
Can you install the mingw64-x86_64-gcc-core package (for just the C compiler) and use the x86_64-w64-mingw32-gcc compiler command (instead of gcc) ?
Use the -fPIC switch to generate the position independent code. Plus, you might be lying to Julia unless your int is defined as int32 on the specific platform. To be sure, you need to change ccall((:timesTwo, mylib), Int32, (Int32,), x) to ccall((:timesTwo, mylib), Cint, (Cint,), x). Finally, to make the code work for any operating system, please consider replacing mylib = dlopen("C:\\Users\\pedro\\Documents\\codigos\\exampleDLL\\C\\mydll.dll") to const mylib = dlopen(joinpath(pwd(), "mydll.dll")). const is there for efficiency reasons, joinpath is OS-agnostic, meaning that it will add forward slash for *nix-based systems. Later on, when you want to change the library to .so, for instance, you should not deal with slashes, too.
I have been able to write simple R extensions in C by doing the following:
writing a C function
compiling it using R CMD SHLIB "function name.c"
using dyn.load("functionname.so") in R
Now, I have written some more advanced C functions that use the igraph library. However, the compiling command above (R CMD SHLIB) does not recognize #include<igraph.h>. Is there a way to adapt the R CMD SHLIB command so that it will find the igraph library? When I compile my C code regularly, I use the following compile command to include igraph:
gcc -I MY_IGRAPH_DIR/install/include/igraph -L MY_IGRAPH_DIR/install/lib myfunction.c -o myfunction
I realize that to pass more than just an integer vector to C I will want to explore sexp and .Call. Currently, I am just trying to get small functions to work so that I have a place to start. Also, I prefer C and am trying to avoid RCPP.
I am constructing an R package where I have few third party C functions which use GSL and OpenMP, and I then call these from R using wrappers made with Rcpp (which just modify some arguments and call the appropriate C function). Everything works fine in my Windows machine, but I am not sure how to define the Makevars.win and Makevars file in a portable way. My Makevars.win looks like this:
## This assumes that the LIB_GSL variable points to working GSL libraries
PKG_CPPFLAGS=-I$(LIB_GSL)/include -I../inst/include
PKG_LIBS=-L$(LIB_GSL)/lib/x64 -lgsl -lgslcblas $(SHLIB_OPENMP_CFLAGS)
PKG_CFLAGS=$(SHLIB_OPENMP_CFLAGS)
It is basically copied from various sources. Like said, this compiles in my computer (using toolchain of from Rtools), and if I remove PKG_CFLAGS=$(SHLIB_OPENMP_CFLAGS) I can also compile without OpenMP (for some reason I don't understand I get error if I remove OpenMP flag in PKG_LIBS).
My Makevars file looks identical, but I don't have access to Unix platforms so I am not sure how to deal with that side. My guess is that I need to replace LIB_GSL with something?
EDIT:
Okay, I think I finally understand how configure etc. works and was able to get everything working.
My Makevars.win:
## This assumes that the LIB_GSL variable points to working GSL libraries
PKG_CPPFLAGS=-I$(LIB_GSL)/include -I../inst/include
PKG_LIBS="-L$(LIB_GSL)/lib/$(R_ARCH)" -lgsl -lgslcblas $(SHLIB_OPENMP_CFLAGS)
PKG_CFLAGS=$(SHLIB_OPENMP_CFLAGS)
My Makevars.in:
GSL_CFLAGS = #GSL_CFLAGS#
GSL_LIBS = #GSL_LIBS#
PKG_LIBS=$(GSL_LIBS) $(SHLIB_OPENMP_CFLAGS)
PKG_CFLAGS=$(GSL_CFLAGS) $(SHLIB_OPENMP_CFLAGS)
And my configure.ac:
AC_INIT([testpackage], 0.0.1)
## Use gsl-config to find arguments for compiler and linker flags
##
## Check for non-standard programs: gsl-config(1)
AC_PATH_PROG([GSL_CONFIG], [gsl-config])
## If gsl-config was found, let's use it
if test "${GSL_CONFIG}" != ""; then
# Use gsl-config for header and linker arguments
GSL_CFLAGS=`${GSL_CONFIG} --cflags`
GSL_LIBS=`${GSL_CONFIG} --libs`
else
AC_MSG_ERROR([gsl-config not found, is GSL installed?])
fi
# Now substitute these variables in src/Makevars.in to create src/Makevars
AC_SUBST(GSL_CFLAGS)
AC_SUBST(GSL_LIBS)
AC_OUTPUT(src/Makevars)
I then run autoconf in testpackage directory in order to get configure file, which in turn converts Makevars.in to Makevars when running R CMD INSTALL.
There are a few CRAN packages using the GSL, and/or our RcppGSL bindings. Here is what I do in one of these (my RcppZiggurat package):
PKG_CPPFLAGS = -I. -I../inst/include
## Use the R_HOME indirection to support installations of multiple R version
PKG_LIBS = `$(R_HOME)/bin/Rscript -e "RcppGSL:::LdFlags()"`
That is the entire /src/Makevars. You can trivially add the same OpenMP variable from R. This does of course create a dependency on RcppGSL (as I already use it in RcppZiggurat). Else you can look into the R/init.R of RcppGSL and see how it tries to talk to gsl-config and store those values. You can do the same in src/Makevars -- it is just basic Make usage and nothing Rcpp specific.
I'm running Mathematica 8 on a MacOSX, trying to compile even the simplest program to C. Anything having to do with C simply doesn't work in Mathematica. I have GCC 4.2 installed; I've even reinstalled it multiple times with XCode. Here's what I'm doing and the errors I'm getting:
First, I always evaluate the command
Needs["CCompilerDriver`"]
If I set the compilation target to C,
c = Compile[ {{x}}, x^2 + Sin[x^2], CompilationTarget -> "C"];
I get an error that reads: Compile::nogen : A library could not be created from the compiled function.
If I try to create a library,
demoFile = FileNameJoin[{$CCompilerDirectory,"SystemFiles","CSource","createDLL_demo.c"}];
lib = CreateLibrary[{demoFile},"testLibrary"]
I get an message $Failed. Wolfram says that this is because I don't have a C compiler installed. I find that hard to believe because when I run
CCompilers[]
It tells me that I've got GCC installed: {{"Name" -> "GCC",
"Compiler" -> CCompilerDriver'GCCCompiler`GCCCompiler,
"CompilerInstallation" -> "/usr/bin", "CompilerName" -> Automatic}}
What's more, terminal says I have GCC installed too!! Any help would be appreciated. I'd really like to compile Mathematica to C.
In this answer I'll collect some debugging steps for similar problems, for future reference. Feel free to edit/improve them.
If compiling to C code does not work from Mathematica 8,
Check that you have a supported C compiler installed and it works (the obvious).
Note that the compiler does not necessarily have to be in the PATH, at least on Windows/Visual Studio it doesn't.
Check that Mathematica recognizes the compiler
<< CCompilerDriver`
CCompilers[]
will list the compilers known to Mathematica.
Check what commands Mathematica executes to compile the generated C code:
Compiler`$CCompilerOptions = {"ShellCommandFunction" -> Print};
Compile[{{x}}, x^2, CompilationTarget -> "C"];
Note that with "ShellCommandFunction" -> Print the commands will not be executed, so you'll need to re-set Compiler`$CCompilerOptions to {} after this step is complete to allow command execution again.
Check the output/errors from the compiler:
Compiler`$CCompilerOptions = {"ShellOutputFunction" -> Print};
Compile[{{x}}, x^2, CompilationTarget -> "C"];
These last two steps will hopefully give you enough clues to proceed. With this information you can check if the correct library / include paths are passed to the compiler (in the case of gcc/icc, look at the -L option which specifies library paths and the -I option which specifies include paths). Then check if the required include and library files are present at those paths.
If you get Compile::nogen, you can see the compiler output by setting ShellOutputFunction->Print right in the Compile expression:
c = Compile[ {{x}}, x^2 + Sin[x^2],
CompilationTarget -> {"C", "ShellOutputFunction"->Print}];
In general, this is how you can pass options to the underlying CreateLibrary call, by changing CompilationTarget->"C" to CompilationTarget->{"C", options}. Setting Compiler`$CCompilerOptions works too, but this technique has the advantage of not setting a global variable.
It is a shame that the only error you are seeing is $Failed, that's not terribly helpful; I wonder if perhaps there are some file or directory permissions problems?
I'm running on linux not Mac so I am not sure if my setup is "close enough" or not. On my machine your Compile command succeeds and generates a file .Mathematica/ApplicationData/CCompilerDriver/BuildFolder/blackie-desktop-5077/compiledFunction1.so in my home directory. Is there any way you can find a .Mathematica directory associated with your userid, and see if it exists and is writeable by mathematica?
Also, you could check to see if "gcc" is or is not being accessed by checking the file access time of /usr/bin/gcc before and after your call to Compile. From an operating system shell you can do ls -lu /usr/bin/gcc or from Mathematica perhaps Import["!ls -lu /usr/bin/gcc", "Text"]