I've built an R package which includes C/C++ code. I am now trying to test this package on win-builder. Unfortunately, the following error is returned in 00install.out
:
* installing *source* package 'mypackage' ...
** libs
running 'src/Makefile.win' ...
/usr/bin/make --directory=lib/mylib/
gcc -g -Wall -fPIC -c mycode.c
make[1]: gcc: Command not found
make[1]: *** [mycode.o] Error 127
make: *** [mylib] Error 2
Warning: running command 'make --no-print-directory -f "Makefile.win"' had status 2
ERROR: compilation failed for package 'mypackage'
* removing 'd:/RCompile/CRANguest/R-release/lib/mypackage'
Trying with gcc
, gcc.exe
, and cc
yielded similar results.
Accordingly, I set up a testing environment on a Windows virtual machine according to these instructions. Running R CMD INSTALL .
on the code from the command line within this environment resulted in the code compiling and the package installing without issue. (Running R CMD build .
also yielded no errors.)
What's up with win-builder, and how can I achieve compilation on it?
Or, more importantly, is being able to build the package on Windows sufficient, regardless of whether it worked on win-builder?
My Makefile.win
is as follows:
export CCOMP = gcc
export CPPCOMP = c++
export ADD_CC_FLAGS = -O3
APP_DIR = ./apps/myapp
LIB_DIR = ./lib/mylib
.PHONY: all $(APP_DIR) $(LIB_DIR)
all: $(APP_DIR) $(LIB_DIR)
$(APP_DIR) $(LIB_DIR): mylib
$(MAKE) --directory=$@
$(APP_DIR): $(LIB_DIR) mylib
mylib:
$(MAKE) --directory=lib/mylib
Inserting echo %PATH%
into the make file under the mylib
target yielded:
Makefile.win:24: *** missing separator. Stop.
答案 0 :(得分:3)
You get an obscure error here because you included a file Makefile.win
.
But the semantics of make
, if such a file is found, it will be used ... which is not what you want here. R builds its own Makefile.win
and you are supposed to only supply a snippet to be included -- which must be called Makevars.win
.
That is rule number one. Rules number two is to not included all the material you would include in a Makefile
-- as you would clobber what R already brings to the table. All this is in Writing R Extensions but could of course be clearer.
My pragmatic suggestion: take a package you know and like which has a working R build in win-builder, and modify it. You can test locally should you have access to an R system with Rtools etc pp.
Edit from OP:
I needed to compile an executable which relied on several libraries. The library codes were in src/libs
and the executable's code was in src/apps
. I ensured that running make
within each subdirectory worked and set src/apps/Makefile
to use relative paths to pull in the results of src/libs
. The only problem then, was getting the whole chain running. To do so, I created a file src/Makevars.win
which had the following structure:
.PHONY: all myprogram sublib1 sublib2
all: sublib1 sublib2 myprogram
myprogram: sublib1 sublib2
@(cd apps/myprogram && $(MAKE) CXX="$(CXX)" CC="$(CC)" CFLAGS="$(CFLAGS) $(CPICFLAGS)" AR="$(AR)" RANLIB="$(RANLIB)")
sublib1:
@(cd lib/sublib1 && $(MAKE) CXX="$(CXX)" CC="$(CC)" CFLAGS="$(CFLAGS) $(CPICFLAGS)" AR="$(AR)" RANLIB="$(RANLIB)")
sublib2:
@(cd lib/sublib2 && $(MAKE) CXX="$(CXX)" CC="$(CC)" CFLAGS="$(CFLAGS) $(CPICFLAGS)" AR="$(AR)" RANLIB="$(RANLIB)")
As I understand it, Makevars.win
gets embedded in a dynamically generated Makefile
that R produces. So, $(CC)
is actually referencing this hidden code.
(There are probably more clever ways to do this.)