How to visualize Halide camera pipeline / generate HTML output of how Halide compiles? - halide

I've tried adding the following line to the bottom of camera_pipe_generator.cpp to output how Halide compiles into a .html file, but I'm not sure what I'm doing wrong:
processed.compile_to_lowered_stmt("camera_pipe_debugging_trial.html", {}, HTML);
I think my second argument is wrong, but what should I pass in here?
Or is there a different way for me to visualize the schedule? This post seems to suggest a visualizer for Halide exists. Are there any resources available on how to use it?
Thank you!
Edit: I've tried running the command
../../tools/gengen.sh -c c++ -lcurses -l ../../lib/libHalide.a -o tmp/ -e html -s camera_pipe_generator.cpp target=host
However, that resulted in the following error:
Undefined symbols for architecture x86_64:
"_del_curterm", referenced from:
llvm::sys::Process::FileDescriptorHasColors(int) in libHalide.a(llvm_460_Process.cpp.o)
"_set_curterm", referenced from:
llvm::sys::Process::FileDescriptorHasColors(int) in libHalide.a(llvm_460_Process.cpp.o)
"_setupterm", referenced from:
llvm::sys::Process::FileDescriptorHasColors(int) in libHalide.a(llvm_460_Process.cpp.o)
"_tigetnum", referenced from:
llvm::sys::Process::FileDescriptorHasColors(int) in libHalide.a(llvm_460_Process.cpp.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Which I think might be related to running on mac OSX 10.12.3?
Final edit: Added option '-lcurses' to the gengen.sh file and it worked!

To visualize your Halide code to a MPEG file, the following is needed:
Halide filter compiled to AOT binary
Source code to exercise AOT binary
Bash shell script to build and execute HalideTraceViz
All of the above assets in the same folder
Regarding point 4, I'm sure this could altered, but for the trials I had, this was the only way I was able to get things working; anyone who can share their input on that last point is welcome to do so.
1: Halide filter compiled to AOT binary
I used the brighten filter listed on the halide-lang.org tutorial site to create the below listed filter and compile it to a usable binary:
http://halide-lang.org/tutorials/tutorial_lesson_10_aot_compilation_generate.html
#include "Halide.h"
#include <iostream>
namespace
{
auto input = Halide::ImageParam(Halide::type_of< uint8_t >(), 2, std::string{"input_image"});
auto offset = Halide::Param< uint8_t >{"offset"};
} // anonymous namespace
auto create_filter() -> Halide::Func
{
auto x = Halide::Var{"x"};
auto y = Halide::Var{"y"};
auto brighten = Halide::Func{"filter_output"};
brighten(x, y) = input(x, y) + offset;
return brighten;
}
auto schedule_filter(Halide::Func filter_ref) { filter_ref.vectorize(x, 16).parallel(y); }
auto create_aot_binary()
{
auto args = std::vector< Halide::Argument >{input, offset};
brighten.compile_to_file("brighten", args);
}
int main(int argc, const char* argv[])
{
printf("brighten filter AOT binary generator\n");
auto brighten = create_filter();
schedule_filter(brighten);
create_aot_binary();
return 0;
}
2. Source code to exercise AOT binary
#include "brighten.h" // header file created by aot generator in step 1
#include <cassert>
#include <vector>
namespace
{
constexpr auto width = 16 * 4;
constexpr auto height = 16 * 4;
} // anonymous namespace
auto create_input_image() -> std::vector< uint8_t >
{
auto image = std::vector< uint8_t >(width * height, 0);
for (auto y = 0; y < width; y++)
{
for (auto x = 0; x < height; x++)
{
const auto val = x ^ (y + 1);
const auto index = y * height + x;
image[index] = val;
}
}
return image;
}
auto create_buffer_t_with_data(const std::vector< uint8_t >& image) -> buffer_t
{
auto buff = buffer_t{0};
buff.host = image.data();
buff.stride[0] = 1;
buff.stride[1] = width;
buff.extent[0] = width;
buff.extent[1] = height;
buff.elem_size = 1;
}
int main(int argc, const char* argv[])
{
printf("brighten filter exercise\n");
auto input_image = create_input_image();
assert(input_image.size() != 0);
auto input_buf = create_buffer_t_with_data(input_image);
auto output_image = std::vector< uint8_t >(width * height, 0);
assert(output_image.size() != 0);
auto output_buf = create_buffer_t_with_data(output_image);
const auto offset = 1;
auto error = brighten(&input_buf, offset, &output_buf);
(void)error;
return 0;
}
3. Bash shell script to build and execute HalideTraceViz
Now, here is is the bash shell script, where I:
Build the HalideTraceViz.cpp code
Build the AOT generator and filter exerciser app
Copy the binaries into one directory
Call the apps with special parameters that are used for passing data to the HalideTraceViz app
#!/bin/bash
set -e
set -u
function build_binaries()
{
printf "${FUNCNAME[0]}\n"
printf "Building HalideTraceViz\n"
xcodebuild -project visualize_brighten.xcodeproj -scheme HalideTraceViz CONFIGURATION_BUILD_DIR=build/Debug -configuration "Debug" clean build
printf "Building generate_brighten_aot\n"
xcodebuild -project visualize_brighten.xcodeproj -scheme generate_brighten_aot CONFIGURATION_BUILD_DIR=build/Debug -configuration "Debug" clean build
printf "Generating AOT in order to build exercise app\n"
cd build/Debug
HL_TRACE=3 ./generate_brighten_aot
cd $CURRENT_PATH
printf "Building app to exercise brighten filter\n"
xcodebuild -project visualize_brighten.xcodeproj -scheme exercise_brighten_aot CONFIGURATION_BUILD_DIR=build/Debug -configuration "Debug" clean build
cd $CURRENT_PATH
}
function copy_binaries()
{
printf "${FUNCNAME[0]}\n"
if [[ -d $CURRENT_PATH/halide_visualizer ]]; then
rm -Rv $CURRENT_PATH/halide_visualizer
fi
mkdir $CURRENT_PATH/halide_visualizer
cp -Rv $CURRENT_PATH/build/Debug $CURRENT_PATH/halide_visualizer/Debug
}
function visualize_function()
{
printf "${FUNCNAME[0]}\n"
local BLANK=0
local DIMENSIONS=1
local ZOOM=8
local COST=4
local STRIDE0="1 0"
local STRIDE1="0 1"
local FFMPEG_BIN_PATH="YOU_HAVE_TO_DOWNLOAD_THIS_BIN_AND_SET_THE_PATH_HERE"
cd $CURRENT_PATH/halide_visualizer/Debug
echo "About to start visualizing brighten filter"
HL_TRACE=3 ./generate_brighten_aot && \
HL_TRACE_FILE=/dev/stdout ./exercise_brighten_aot | \
$CURRENT_PATH/build/Debug/HalideTraceViz -s 1024 516 -t 1 -d 100 \
-f brighten:input_image 0 255 $BLANK $ZOOM $COST 0 0 $STRIDE0 $STRIDE1 |\
$FFMPEG_BIN_PATH/ffmpeg -r 30 -f rawvideo -pix_fmt bgra -s 1024X516 -i - -y -pix_fmt yuv420p $CURRENT_PATH/movies/brighten_schedule.mp4
cd $CURRENT_PATH
}
main()
{
printf "${FUNCNAME[0]}\n"
CURRENT_PATH=$PWD
build_binaries
copy_binaries
visualize_function
printf "All done\n"
}
printf "Starting ${0##*/}\n"
main
A couple of things to note:
I used Xcode for compiling the projects, but obviously, you can use any tool you are comfortable with
HalideTraceViz comes with it's own cmake file in "Halide/util/"; that folder is part of the Halide git repo
For the bash shell script code, you will have to adjust the folder paths to work with your development setup
All the code that you see listed above was just created now, so I can't guarantee that it works as is :)
Hopefully this helps you get started; if you have any questions, let me know.

toIn the apps/camera_pipe directory, the following command line will generate the HTML stmt file into /tmp/camera_pipe.html:
../../tools/gengen.sh -c c++ -l ../../lib/libHalide.a -o /tmp/ -e html -s camera_pipe_generator.cpp target=host

Related

Use libp11 on Windows environment

I want to install all I need to use libp11 and use libp11.
What is my environment and needs:
I work on Windows 10, 64 bits.
I add package with pacman linux command on my mingw32 terminal (msys64 version of 2022/09/04).
I work on a Qt Creator editor and I have a .pro file to configure my Qt project.
I want to develop a C++ module for my application which use libp11 to get the Yubikey bin number and decrypt file.
Why I use a mingw32 terminal and not the mingw64, because, for the moment, the project is always in develop in QT 4.8.
What I do:
I read the README file and follow the installation step of the INSTALL file (first I follow the MinGW / MSYS chapter, then I follow the MSYS2 chapter.)
I do much more, but I don't remember every thing and I go in many wrong ways.
My problems and questions
I try to follow the examples find in GitHub.
I help me with the site cpp.hotexemples.com to find the second parameter for the PKCS11_CTX_load function. I find the st_engine_ctx structure on this project.
The project file:
TEMPLATE = app
CONFIG += console c++17
CONFIG -= app_bundle
CONFIG += qt
LIBS += \
-lp11 \
-lssl \
-lcrypto
SOURCES += \
TestYubikey.cpp \
main.cpp
HEADERS += \
TestYubikey.h
The header file:
#ifndef TESTYUBIKEY_H
#define TESTYUBIKEY_H
#include <libp11.h>
#include <cstdio>
#include <cstring>
#include <openssl/err.h>
#include <openssl/crypto.h>
#include <openssl/objects.h>
#include <openssl/engine.h>
#include <openssl/ui.h>
/* Engine configuration */
/* The PIN used for login. Cache for the ctx_get_pin function.
* The memory for this PIN is always owned internally,
* and may be freed as necessary. Before freeing, the PIN
* must be whitened, to prevent security holes.
*/
struct st_engine_ctx
{
char *pin = nullptr;
size_t pin_length = 0;
int verbose = 0;
char *module = nullptr;
char *init_args = nullptr;
UI_METHOD *ui_method = nullptr;
void *callback_data = nullptr;
int force_login = 0;
/* Engine initialization mutex */
#if OPENSSL_VERSION_NUMBER >= 0x10100004L && !defined(LIBRESSL_VERSION_NUMBER)
CRYPTO_RWLOCK *rwlock = nullptr;
#else
int rwlock;
#endif
/* Current operations */
PKCS11_CTX *pkcs11_ctx = nullptr;
PKCS11_SLOT *slot_list = nullptr;
unsigned int slot_count = 0;
};
class TestYubikey
{
public:
TestYubikey();
};
#endif // TESTYUBIKEY_H
The source file:
//libp11 is a wrapper library for PKCS#11 modules with OpenSSL interface
#include "TestYubikey.h"
#include <iostream>
TestYubikey::TestYubikey()
{
// Create a new libp11 context
PKCS11_CTX *ctx = PKCS11_CTX_new();
std::cout << "ctx = " << ctx << std::endl;
/* load pkcs #11 module */
int rc = PKCS11_CTX_load(ctx, "C:\\msys64\\mingw32\\lib\\engines-1_1\\pkcs11.dll"); //I test with "libpkcs11.dll" and "pkcs11.dll" too.
std::cout << "rc = " << rc << std::endl;
if (rc == -1)
{
std::cout << "Loading pkcs11 engine failed";
unsigned long error_code = ERR_get_error();
const char* error_detail = ERR_reason_error_string(error_code);
std::cout << " (" << error_code << ") : " << std::string(error_detail) << std::endl;
}
else
{
std::cout << "Loading pkcs11 engine worked !" << std::endl;
}
}
My output console show:
11:59:27: Starting C:/Users/jgomez/Documents/build-SandBox-Desktop_Qt_4_8_7_MinGW_32_bit-Release/release/SandBox.exe...
ctx = 0x2ca8f50
rc = -1
Loading pkcs11 engine failed (0) : terminate called after throwing an instance of 'std::logic_error'
what(): basic_string: construction from null is not valid
11:59:29: C:/Users/jgomez/Documents/build-SandBox-Desktop_Qt_4_8_7_MinGW_32_bit-Release/release/SandBox.exe exited with code 3
My problem:
rc = -1
Solution :
use the Dll called opensc-pkcs11.dll provided with OpenSC project and it should work.
( https://github.com/OpenSC/OpenSC , after installing , it should be found here by default C:\Program Files (x86)\OpenSC Project\OpenSC\pkcs11)
Explantation :
I have encountered the same problem, and after messing around with the files I figured out that this error due the PKCS11_CTX_Load function.
PKCS11_CTX_Load , tries to load the pkcs11.dll , and then tries getting the address of "c_get_function_list" from this dll, which fails since it doesn't have that function.

Does Adams and Mullapudi autoschedulers support specializations?

The Adams and Mullapudi autoschedulers often generate schedules which include the vectorize and split primitives with constant parameters on them. These schedules do not work for all array sizes fed to the compiled Halide library as shown in the example below.
For the example below try array size of 3 (fails with out of bounds error) and 4 (passes).
Then in the Generator class comment the vectorization schedule and uncomment the split one. Then try array size 7 (fails with out of bounds error) and 8 (passes).
Notice that if the array is not compatible with the split/vectorization parameters it can go out of bounds.
If the Mullapudi and Adams add specializations into the generated schedule to filter out incompatible sizes then this problem would not have happened. Maybe also if the split/vectorization somehow can be parameterized, but maybe that is not a good option.
Do the Mullapudi or Adams autoschedulers support the specialization for cases like this or is there plan to support it?
SchBugGen.cpp file:
#include "Halide.h"
#include <stdio.h>
using namespace Halide;
class SchBugGen : public Halide::Generator <SchBugGen> {
public:
Input<Buffer<double>> aIn1{"aIn1", 1};
Output<Buffer<double>> aOut1{"aOut1", 1};
void generate() {
aOut1(d1) = aIn1(d1) * 2;
}
void schedule() {
Var d2("d2");
// Default schedule
aOut1.vectorize(d1, 4);
// aOut1.split(d1, d1, d2, 8);
}
private:
Var d1{"d1"};
};
HALIDE_REGISTER_GENERATOR(SchBugGen, SchBugGenerator)
bugRepro.cpp file:
#include <stdio.h>
#include <stdlib.h>
#include "schBugFun.h"
#include "HalideBuffer.h"
void printOut(double aOut1[], int aLen) {
printf("Out = {");
for (int i = 0; i < aLen; i++) {
printf("%0.0lf ", aOut1[i]);
}
printf("}\n");
}
void initArrs(double aIn1[], int aIn1Size) {
for (int i = 0; i < aIn1Size; i++) {
aIn1[i] = 10;
}
}
int main() {
// For vectorization of size 4 try fl = 3 and 4. The former asserts, the later does not.
// For split of size 8 try fl = 7 and 8. The former asserts, the later does not.
const int fl = 3;
double in1[fl];
double out1[fl] = {};
initArrs(in1, fl);
Halide::Runtime::Buffer<const double> inHBuff(in1, fl);
Halide::Runtime::Buffer<double> outHBuff(out1, fl);
schBugFun(inHBuff, outHBuff);
printOut(out1, fl);
return 0;
}
// Use these commands to compile the code above:
Do this only once:
set PATH=<HALIDE_BIN_PATH>:$PATH
set LD_LIBRARY_PATH=<HALIDE_BIN_PATH>
Compile Halide generator class:
g++ -std=c++17 -g -I <HALIDE_INCLUDE_PATH> -L <HALIDE_BIN_PATH> -lHalide -lpthread -ldl - rdynamic -fno-rtti -Wl,-rpath,<HALIDE_BIN_PATH> SchBugGen.cpp <HALIDE_INCLUDE_PATH>/GenGen.cpp -o schBugLibGen
Create Halide library by running compiled generator without schedule:
./schBugLibGen -f schBugFun -g SchBugGenerator -e static_library,h,assembly,bitcode,cpp,html,cpp_stub,stmt,o,schedule target=host auto_schedule=false -o .
Compile test harness:
g++ -std=c++17 schBugFun.o -I <HALIDE_INCLUDE_PATH> -L <HALIDE_BIN_PATH> -lHalide -lpthread -ldl -rdynamic -fno-rtti -Wl,-rpath,<HALIDE_BIN_PATH> -O3 -g bugRepro.cpp -o out
Run the program:
./out
Thanks,
Ivan
This issue was also captured here: https://github.com/halide/Halide/issues/3104
And is expected to be addressed here: https://github.com/halide/Halide/issues/6847
Note in issue 6847 these two points:
• There must be a way to ensure that schedules are resilient to varying bounds; it's currently common to get a scheduler that will work for the "estimated" size, but will OOB on smaller/etc sizes. This is unacceptable for production work. (Adams2019 autoscheduler can produce schedules that aren't bounds-resilient #5070, Autoscheduled code doesn't work on buffers smaller than estimates #3953, Adams2019 autoscheduler generates incorrect code #4512)
• Consider whether/how to add support for specialize() to the autoscheduler. (Specializing the auto-schedule #3104)

How do I install primer3 on windows?

Problem:
I need to install Primer3, a widely used bio tool that finds allows one to design primers.
Attempts at resolution:
I have attempted to follow their instructions for a Windows installation to no avail as it does not seem provide enough information. I not a experienced programmer by any means. So far I've also referenced this stack overflow post about a similar issue and tried to follow the suggested answer. I also briefly looked at a thread in their github repository, though I can't really understand what they are saying in it. Nothing seems to work so far as the output I get from my command terminal (the mingw32 version) is this:
C:\Users\mqian\Desktop\CGIProject\primer3-2.4.0\primer3-2.4.0\test>mingw32-make
TESTOPTS=--windows
cd ..\src & mingw32-make
mingw32-make[1]: Entering directory 'C:/Users/mqian/Desktop/CGIProject/primer3-2
.4.0/primer3-2.4.0/src'
g++ -c -g -Wall -D__USE_FIXED_PROTOTYPES__ -O2 masker.c
masker.c:8:22: fatal error: sys/mman.h: No such file or directory
compilation terminated.
Makefile:226: recipe for target 'masker.o' failed
mingw32-make[1]: *** [masker.o] Error 1
mingw32-make[1]: Leaving directory 'C:/Users/mqian/Desktop/CGIProject/primer3-2.
4.0/primer3-2.4.0/src'
Makefile:94: recipe for target 'makeexes' failed
mingw32-make: *** [makeexes] Error 2
and if I just try to run a make in the src folder:
C:\Users\mqian\Desktop\CGIProject\primer3-2.4.0\primer3-2.4.0\src>mingw32-make
g++ -c -g -Wall -D__USE_FIXED_PROTOTYPES__ -O2 masker.c
masker.c:8:22: fatal error: sys/mman.h: No such file or directory
compilation terminated.
Makefile:226: recipe for target 'masker.o' failed
mingw32-make: *** [masker.o] Error 1
Is it something that I missing in terms of a software or package needed? Is their makefile bugged? Any help would be appreciated.
P.S. here is a link to their download site on sourceforge. I am using version 2.4.0.
I was able to build it like this on Windows (replace /usr/local with the path where you want to install):
Build mman-win32 from https://github.com/witwall/mman-win32/releases under MSYS2 using:
./configure --prefix=/usr/local --cc=gcc --enable-static --enable-shared &&
make &&
mkdir -p /usr/local/include/mman-win32/sys /usr/local/lib &&
cp -f *.h /usr/local/include/mman-win32/sys/ &&
cp -f *.a /usr/local/lib/ &&
echo Success
Then build primer3 from https://github.com/primer3-org/primer3/releases:
mv src/masker.c src/masker.c.bak
cat > src/masker.c << EOF
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define GETLINE_BUFLEN 128
static ssize_t getline(char** lineptr, size_t* n, FILE* stream)
{
char* bufptr;
char* p;
ssize_t size;
int c;
if (!lineptr || !n || !stream)
return -1;
bufptr = *lineptr;
size = *n;
c = fgetc(stream);
if (c == EOF)
return -1;
if (!bufptr) {
if ((bufptr = (char*)malloc(GETLINE_BUFLEN)) == NULL)
return -1;
size = GETLINE_BUFLEN;
}
p = bufptr;
while (c != EOF) {
if ((p - bufptr) > (size - 1)) {
size = size + GETLINE_BUFLEN;
if ((bufptr = (char*)realloc(bufptr, size)) == NULL)
return -1;
}
*p++ = c;
if (c == '\n') {
break;
}
c = fgetc(stream);
}
*p++ = 0;
*lineptr = bufptr;
*n = size;
return p - bufptr - 1;
}
EOF
cat src/masker.c.bak >> src/masker.c
make -Csrc install PREFIX=/usr/local CC_OPTS="-I/usr/local/include/mman-win32" LDLIBS="-Wl,--as-needed -lmman" &&
echo Success

How do I use the clang static analyzer with msbuild on Windows?

The binary windows installer for clang includes scan-build but when you run it with msbuild nothing happens. Even if I do something like:
"C:\Program Files\LLVM\bin\scan-build.bat" "C:\Program Files\LLVM\bin\clang.exe" test.cpp
I get something like:
scan-build: Using 'C:\Program Files\LLVM\bin\clang.exe' for static analysis
scan-build: Removed Directory '....'
scan-build: No Bugs found
Where test.cpp is:
void DivideByZero(int z){
if (z == 0) {
int x = 1 / z;
}
}
int main() {
int *i = nullptr;
*i = 42;
DivideByZero(0);
}
If I use the following I get some warnings:
"C:\Program Files\LLVM\bin\clang.exe" --analyze test.cpp
So back to my question. How does one get this to work with MSBUild? What is scan-build actually doing and should I use it or --analyze? What is the difference?

getline on MacOSX 10.6 crashing C compiler?

I'm having a really hard time getting an R library installed that requires some compilation in C. I'm using a Mac OSX Snow Leopard machine and trying to install this R package (here).
I've looked at the thread talking about getline on macs and have tried a few of these fixes, but nothing is working! I'm a newbie and don't know any C, so that may be why! Can anyone give me some tips on how I could modify files in this package to get it to install?? Anyhelp would be pathetically appreciated! Here's the error I'm getting:
** libs
** arch - i386
g++ -arch i386 -I/Library/Frameworks/R.framework/Resources/include -I/Library/Frameworks/R.framework/Resources/include/i386 -I/usr/local/include -D_FASTMAP -DMAQ_LONGREADS -fPIC -g -O2 -c bed2vector.C -o bed2vector.o
In file included from /usr/include/c++/4.2.1/backward/strstream:51,
from bed2vector.C:8:
/usr/include/c++/4.2.1/backward/backward_warning.h:32:2: warning: #warning This file includes at least one deprecated or antiquated header. Please consider using one of the 32 headers found in section 17.4.1.2 of the C++ standard. Examples include substituting the <X> header for the <X.h> header for C++ includes, or <iostream> instead of the deprecated header <iostream.h>. To disable this warning use -Wno-deprecated.
bed2vector.C: In function ‘int get_a_line(FILE*, BZFILE*, int, std::string&)’:
bed2vector.C:74: error: no matching function for call to ‘getline(char**, size_t*, FILE*&)’
make: *** [bed2vector.o] Error 1
chmod: /Library/Frameworks/R.framework/Resources/library/spp/libs/i386/*: No such file or directory
ERROR: compilation failed for package 'spp'
The easiest solution is probably to add a static definition for getline() to bed2vector.c. This might be good enough:
/* PASTE AT TOP OF FILE */
#include <stdio.h> /* flockfile, getc_unlocked, funlockfile */
#include <stdlib.h> /* malloc, realloc */
#include <errno.h> /* errno */
#include <unistd.h> /* ssize_t */
extern "C" ssize_t getline(char **lineptr, size_t *n, FILE *stream);
/* PASTE REMAINDER AT BOTTOM OF FILE */
ssize_t
getline(char **linep, size_t *np, FILE *stream)
{
char *p = NULL;
size_t i = 0;
if (!linep || !np) {
errno = EINVAL;
return -1;
}
if (!(*linep) || !(*np)) {
*np = 120;
*linep = (char *)malloc(*np);
if (!(*linep)) {
return -1;
}
}
flockfile(stream);
p = *linep;
for (int ch = 0; (ch = getc_unlocked(stream)) != EOF;) {
if (i > *np) {
/* Grow *linep. */
size_t m = *np * 2;
char *s = (char *)realloc(*linep, m);
if (!s) {
int error = errno;
funlockfile(stream);
errno = error;
return -1;
}
*linep = s;
*np = m;
}
p[i] = ch;
if ('\n' == ch) break;
i += 1;
}
funlockfile(stream);
/* Null-terminate the string. */
if (i > *np) {
/* Grow *linep. */
size_t m = *np * 2;
char *s = (char *)realloc(*linep, m);
if (!s) {
return -1;
}
*linep = s;
*np = m;
}
p[i + 1] = '\0';
return ((i > 0)? i : -1);
}
This doesn't handle the case where the line is longer than the maximum value that ssize_t can represent. If you run into that case, you've likely got other problems.
Zeroth question: Have you considered using a package manager like fink or MacPorts rather than compiling yourself? I know that fink has an R package.
First question: How is the R build managed? Is there a ./configure? If so have you looked at the options to it? Does it use make? Scons? Some other dependency manager?
Second question: Have you told the build system that you are working on a Mac? Can you specify that you don't have a libc with native getline?
If the build system doesn't support Mac OS---but I image that R's does---you are probably going to have to download the standalone version, and hack the build to include it. How exactly you do that depends on the build system. And you may need to hack the source some.

Resources