Can't compile libpd with emmake (Emscripten SDK) - llvm-clang

I'm trying to compile libpd to javascript or webassembly using emscripten sdk. According to some docs, if there is a Makefile, it can be compiled by using emmake make, (emconfigure is not used because there is no ./configure file), but I get the following error:
/home/ian/Documents/emsdk/emscripten/1.37.37/emcc.py -DPD -DHAVE_UNISTD_H -DUSEAPI_DUMMY -I./pure-data/src -I./libpd_wrapper -I./libpd_wrapper/util -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -fPIC -I"/usr/lib/jvm/default-java/include/linux" -DHAVE_LIBDL -ffast-math -funroll-loops -fomit-frame-pointer -O3 -DLIBPD_EXTRA -c -o pure-data/src/d_array.o pure-data/src/d_array.c
pure-data/src/d_array.c:523:2: error: No byte order defined
#error No byte order defined
^
1 error generated.
ERROR:root:compiler frontend failed to generate LLVM bitcode, halting
<integrado>: fallo en las instrucciones para el objetivo 'pure-data/src/d_array.o'
make: *** [pure-data/src/d_array.o] Error 1
Any ideas? Do you think is possible to compile this library?
UPDATE: After tweaking every complaining file as suggested in #zakki 's answer
I get another error:
libpd_wrapper/util/ringbuffer.c:18:12: fatal error: 'stdatomic.h' file not found
#include <stdatomic.h>
That file have this content:
#if __STDC_VERSION__ >= 201112L // use stdatomic if C11 is available
#include <stdatomic.h> // HERE IS WHERE ERROR GOES
#define SYNC_FETCH(ptr) atomic_fetch_or((_Atomic int *)ptr, 0)
#define SYNC_COMPARE_AND_SWAP(ptr, oldval, newval) \
atomic_compare_exchange_strong((_Atomic int *)ptr, &oldval, newval)
//Some other definitions that I didn't put here
I read some threads some time ago about this problem with C++11, how can i fix this?
UPDATE 2: After adding && !defined(__EMSCRIPTEN__) now is able to compile, but I'm getting this warning that I don't understand:
WARNING:root:Dynamic libraries (.so, .dylib, .dll) are currently not
supported by Emscripten. For build system emulation purposes,
Emscripten will now generate a static library file (.bc) with the
suffix '.so'. For best practices, please adapt your build system to
directly generate a static LLVM bitcode library by setting the output
suffix to '.bc.')

Emscripten has endian.h. So add defined(__EMSCRIPTEN__) to ifdef.
#if defined(__linux__) || defined(__CYGWIN__) || defined(__GNU__) || \
defined(ANDROID) || defined(__EMSCRIPTEN__)
#include <endian.h>
#endif
Second, it seems like Emscripten bug.
#if __STDC_VERSION__ >= 201112L && !defined(__EMSCRIPTEN__)

Related

A consistent example for using the C++ API of Pyarrow

I am trying to use the C++ API of Pyarrow. There is currently no example for it on the official documentation, and this is the best I am able to come up with for a simple thing:
#include <arrow/python/pyarrow.h>
#include <arrow/python/platform.h>
#include "arrow/python/init.h"
#include "arrow/python/datetime.h"
#include <iostream>
void MyFunction(PyObject * obj)
{
Py_Initialize();
std::cout << Py_IsInitialized() << std::endl;
int ret = arrow_init_numpy();
std::cout << ret << std::endl;
if (ret != 0) {
throw 0;
}
::arrow::py::internal::InitDatetime();
if(arrow::py::import_pyarrow() != 0)
{
std::cout << "problem initializing pyarrow" << std::endl;
throw 0;}
std::cout << "test" << std::endl;
Py_Finalize();
//return arrow::py::is_array(obj);
}
I am trying to compile it with
gcc -pthread -B /home/ziheng/anaconda3/envs/da/compiler_compat -Wl,--sysroot=/ -Wsign-compare -DNDEBUG -g -fwrapv -O0 -Wall -Wstrict-prototypes -fPIC -D_GLIBCXX_USE_CXX11_ABI=0 -I/home/ziheng/anaconda3/envs/da/lib/python3.7/site-packages/numpy/core/include -I/home/ziheng/anaconda3/envs/da/lib/python3.7/site-packages/pyarrow/include -I/home/ziheng/anaconda3/envs/da/include/python3.7m -c example.cpp -o example.o -std=c++11
g++ -pthread -shared -fPIC -B /home/ziheng/anaconda3/envs/da/compiler_compat -L/home/ziheng/anaconda3/envs/da/lib -Wl,-rpath=/home/ziheng/anaconda3/envs/da/lib -Wl,--no-as-needed -Wl,--sysroot=/ example.o -L/home/ziheng/anaconda3/envs/da/lib/python3.7/site-packages/pyarrow -l:libarrow.so.600 -l:libarrow_python.so.600 -l:libpython3.7m.so -o example.cpython-37m-x86_64-linux-gnu.so
The compilation works with no problems. However when I try to use ctypes to call the compiled .so file, like this:
from ctypes import *
lib = CDLL('example.cpython-37m-x86_64-linux-gnu.so')
lib._Z10MyFunctionP7_object(1)
I get segmentation fault at arrow_init_numpy, after Py_IsInitialized() prints 1.
When I run it through gdb, I get/tmp/build/80754af9/python_1614362349910/work/Python/ceval.c: No such file or directory.
If I try to compile my C code as a standalone executable, however, it works with no problems.
Can someone please help? Thank you.
First, the call to Py_Initialize() is superfluous. You are calling your code from within python and so, presumably, python has already been initialized. That would be needed if you were writing your own main and not a plugin-type library. Correspondingly, the call to Py_Finalize() is probably a bad idea.
Second, and more significant for the error at hand, is that you are using ctypes.CDLL (and not, for example, ctypes.PyDLL) which states (emphasis mine):
The returned function prototype creates functions that use the standard C calling convention. The function will release the GIL during the call. If use_errno is set to true, the ctypes private copy of the system errno variable is exchanged with the real errno value before and after the call; use_last_error does the same for the Windows error code.
And, finally, the Arrow initialization routines assume you are holding the GIL (this should probably be added to the documentation). So the easiest way to fix your program is probably to change CDLL to PyDLL:
from ctypes import *
lib = PyDLL('example.cpython-37m-x86_64-linux-gnu.so')
lib._Z10MyFunctionP7_object(1)

hardware/qcom/display-caf/msm8996/sdm/libs/core/drm/hw_info_drm.cpp:559:35: error: use of undeclared identifier 'QCOM'

I realize I need to define QCOM has the vendor somewhere, but which file / where is this typically declared?
I am getting the following exception while building the ROM for a lineageos project and need some help diagnosing and resolving the issue:
-MD -MF /home/lineageos/out/target/product/tb8504f/obj_arm/SHARED_LIBRARIES/libsdmcore_intermediates/drm/hw_info_drm.d -o /home/lineageos/out/target/product/tb8504f/obj_arm/SHARED_LIBRARIES/libsdmcore_intermediates/drm/hw_info_drm.o hardware/qcom/display-caf/msm8996/sdm/libs/core/drm/hw_info_drm.cpp"
hardware/qcom/display-caf/msm8996/sdm/libs/core/drm/hw_info_drm.cpp:559:35: error: use of undeclared identifier 'QCOM'
if (drm_format_modifier == (DRM_FORMAT_MOD_QCOM_COMPRESSED |
^
hardware/qcom/display-caf/msm8996/sdm/libs/core/drm/hw_info_drm.cpp:58:56: note: expanded from macro 'DRM_FORMAT_MOD_QCOM_COMPRESSED'
#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1)
^
hardware/qcom/display-caf/msm8996/sdm/libs/core/drm/hw_info_drm.cpp:560:11: error: use of undeclared identifier 'QCOM'
DRM_FORMAT_MOD_QCOM_DX | DRM_FORMAT_MOD_QCOM_TIGHT)) {
^
hardware/qcom/display-caf/msm8996/sdm/libs/core/drm/hw_info_drm.cpp:61:48: note: expanded from macro 'DRM_FORMAT_MOD_QCOM_DX'
#define DRM_FORMAT_MOD_QCOM_DX fourcc_mod_code(QCOM, 0x2)
^
Device tree:= https://github.com/darran-kelinske-fivestars/android_device_lenovo_tb8504f/tree/lineage-15.1
Vendor tree:= https://github.com/darran-kelinske-fivestars/android_vendor_lenovo_tb8504f/tree/lineage-15.1
Kernel source:= https://github.com/dazza5000/android_kernel_lenovo_msm8937/tree/tb8504f
ROM Source:= https://github.com/LineageOS/android
Command:
repo sync -j20 && source build/envsetup.sh && breakfast tb8504f && make -j20 | tee rom.log
Full log:
https://del.dog/ujizecehug
I don't know the long term fix for this issue, but my quick and dirty fix was to define the variable in both of the files that depend on it.
I went into the file hw_info_drm.cpp and added the following at the top:
#define QCOM 1

Cross compilation for MIPS architecture

I would like to run an app in a MIPS architecture (BCM6358). I have developed a "Hello World" app like this:
#include <stdio.h>
int main()
{
printf("Hello World" ) ;
return 0 ;
}
I have also compiled it like this:
# mips-linux-gnu-gcc -muclibc hallo.c
But when I've run ... it doesn't work:
# libc.so.6 aborted attempt to ... a.out!!
Of course, libc.so.6 doesn't exist in the MIPS box, but libc.so.0 does.
I have also compiled it like this:
# mips-linux-gnu-gcc -muclibc -mips32 -EB hallo.c -o hallo
However, the output is the same.
I don't know if "-muclibc" is working well because in my Ubuntu machine I don't find anything about libc.so.0 neither uclibc.
root#XXN:/# find / -name libc.so.* -print
/usr/mips-linux-gnu/lib/libc.so.6
/lib/i386-linux-gnu/libc.so.6
/lib/x86_64-linux-gnu/libc.so.6
root#XXN:/# find / -name *uclib* -print
Any idea?
Thanks, best regards.
Yes, the MIPS target has a libc.so and as:
libc.so.6 != uClibc
libc.so.6 == glibc
libc.so.0 == uClibc
I compile with -muclibc.
However, I got it!!! weeeeellll!!
What I have done is to install an old Codesourcery and compile it with static library like this:
# mips-linux-gnu-gcc -muclibc -mips32 -EB -static hallo.c -o hallo
Thanks, best regards.

Determining which gencode (compute_, arch_) values I need for nvcc - within CMake

I'm using CMake as a build system for my code, which involves CUDA. I was thinking of automating the task of deciding which compute_XX and arch_XX I need to to pass to my nvcc in order to compile for the GPU(s) on my current machine.
Is there a way to do this:
With the NVIDIA GPU deployment kit?
Without the NVIDIA GPU deployment kit?
Does CMake's FindCUDA help you in determining the values for these switches?
My strategy has been to compile and run a bash script that probes the card and returns the gencode for cmake. Inspiration came from University of Chicago's SLURM. To handle errors or multiple gpus or other circumstances, modify as necessary.
In your project folder create a file cudaComputeVersion.bash and ensure it is executable from the shell. Into this file put:
#!/bin/bash
# create a 'here document' that is code we compile and use to probe the card
cat << EOF > /tmp/cudaComputeVersion.cu
#include <stdio.h>
int main()
{
cudaDeviceProp prop;
cudaGetDeviceProperties(&prop,0);
int v = prop.major * 10 + prop.minor;
printf("-gencode arch=compute_%d,code=sm_%d\n",v,v);
}
EOF
# probe the card and cleanup
/usr/local/cuda/bin/nvcc /tmp/cudaComputeVersion.cu -o /tmp/cudaComputeVersion
/tmp/cudaComputeVersion
rm /tmp/cudaComputeVersion.cu
rm /tmp/cudaComputeVersion
And in your CMakeLists.txt put:
# at cmake-build-time, probe the card and set a cmake variable
execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/cudaComputeVersion.bash OUTPUT_VARIABLE GENCODE)
# at project-compile-time, include the gencode into the compile options
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS}; "${GENCODE}")
# this makes CMake all chatty and allows you to see that GENCODE was set correctly
set(CMAKE_VERBOSE_MAKEFILE TRUE)
cheers
You can use the cuda_select_nvcc_arch_flags() macro in the FindCUDA module for this without any additional scripts when using CMake 3.7 or newer.
include(FindCUDA)
set(CUDA_ARCH_LIST Auto CACHE STRING
"List of CUDA architectures (e.g. Pascal, Volta, etc) or \
compute capability versions (6.1, 7.0, etc) to generate code for. \
Set to Auto for automatic detection (default)."
)
cuda_select_nvcc_arch_flags(CUDA_ARCH_FLAGS ${CUDA_ARCH_LIST})
list(APPEND CUDA_NVCC_FLAGS ${CUDA_ARCH_FLAGS})
The above sets CUDA_ARCH_FLAGS to -gencode arch=compute_61,code=sm_61 on my machine, for example.
The CUDA_ARCH_LIST cache variable can be configured by the user to generate code for specific compute capabilites instead of automatic detection.
Note: the FindCUDA module has been deprecated since CMake 3.10. However, no equivalent alternative to the cuda_select_nvcc_arch_flags() macro appears to be provided yet in the latest CMake release (v3.14). See this relevant issue at the CMake issue tracker for further details.
A slight improvement over #orthopteroid's answer, which pretty much ensures a unique temporary file is generated, and only requires one instead of two temporary files.
The following goes into scripts/get_cuda_sm.sh:
#!/bin/bash
#
# Prints the compute capability of the first CUDA device installed
# on the system, or alternatively the device whose index is the
# first command-line argument
device_index=${1:-0}
timestamp=$(date +%s.%N)
gcc_binary=$(which g++)
gcc_binary=${gcc_binary:-g++}
cuda_root=${CUDA_DIR:-/usr/local/cuda}
CUDA_INCLUDE_DIRS=${CUDA_INCLUDE_DIRS:-${cuda_root}/include}
CUDA_CUDART_LIBRARY=${CUDA_CUDART_LIBRARY:-${cuda_root}/lib64/libcudart.so}
generated_binary="/tmp/cuda-compute-version-helper-$$-$timestamp"
# create a 'here document' that is code we compile and use to probe the card
source_code="$(cat << EOF
#include <stdio.h>
#include <cuda_runtime_api.h>
int main()
{
cudaDeviceProp prop;
cudaError_t status;
int device_count;
status = cudaGetDeviceCount(&device_count);
if (status != cudaSuccess) {
fprintf(stderr,"cudaGetDeviceCount() failed: %s\n", cudaGetErrorString(status));
return -1;
}
if (${device_index} >= device_count) {
fprintf(stderr, "Specified device index %d exceeds the maximum (the device count on this system is %d)\n", ${device_index}, device_count);
return -1;
}
status = cudaGetDeviceProperties(&prop, ${device_index});
if (status != cudaSuccess) {
fprintf(stderr,"cudaGetDeviceProperties() for device ${device_index} failed: %s\n", cudaGetErrorString(status));
return -1;
}
int v = prop.major * 10 + prop.minor;
printf("%d\\n", v);
}
EOF
)"
echo "$source_code" | $gcc_binary -x c++ -I"$CUDA_INCLUDE_DIRS" -o "$generated_binary" - -x none "$CUDA_CUDART_LIBRARY"
# probe the card and cleanup
$generated_binary
rm $generated_binary
and the following goes into CMakeLists.txt or a CMake module:
if (NOT CUDA_TARGET_COMPUTE_CAPABILITY)
if("$ENV{CUDA_SM}" STREQUAL "")
set(ENV{CUDA_INCLUDE_DIRS} "${CUDA_INCLUDE_DIRS}")
set(ENV{CUDA_CUDART_LIBRARY} "${CUDA_CUDART_LIBRARY}")
set(ENV{CMAKE_CXX_COMPILER} "${CMAKE_CXX_COMPILER}")
execute_process(COMMAND
bash -c "${CMAKE_CURRENT_SOURCE_DIR}/scripts/get_cuda_sm.sh"
OUTPUT_VARIABLE CUDA_TARGET_COMPUTE_CAPABILITY_)
else()
set(CUDA_TARGET_COMPUTE_CAPABILITY_ $ENV{CUDA_SM})
endif()
set(CUDA_TARGET_COMPUTE_CAPABILITY "${CUDA_TARGET_COMPUTE_CAPABILITY_}"
CACHE STRING "CUDA compute capability of the (first) CUDA device on \
the system, in XY format (like the X.Y format but no dot); see table \
of features and capabilities by capability X.Y value at \
https://en.wikipedia.org/wiki/CUDA#Version_features_and_specifications")
execute_process(COMMAND
bash -c "echo -n $(echo ${CUDA_TARGET_COMPUTE_CAPABILITY})"
OUTPUT_VARIABLE CUDA_TARGET_COMPUTE_CAPABILITY)
execute_process(COMMAND
bash -c "echo ${CUDA_TARGET_COMPUTE_CAPABILITY} | sed 's/^\\([0-9]\\)\\([0-9]\\)/\\1.\\2/;' | xargs echo -n"
OUTPUT_VARIABLE FORMATTED_COMPUTE_CAPABILITY)
message(STATUS
"CUDA device-side code will assume compute capability \
${FORMATTED_COMPUTE_CAPABILITY}")
endif()
set(CUDA_GENCODE
"arch=compute_${CUDA_TARGET_COMPUTE_CAPABILITY}, code=compute_${CUDA_TARGET_COMPUTE_CAPABILITY}")
set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -gencode ${CUDA_GENCODE} )

Tcl Expect "interact" command echos previous output from spawned rlwrap process

I have a feeling there is something obvious I'm missing, but my searches are coming up fruitless thus far.
I am trying to use a tcl/expect script to start up a tclsh interactive shell, add a procedure for easily reloading utilities for testing, and then return normal control to me.
So far, the one way I've discovered to make a tcl interactive shell "usable" is to start it with "rlwrap" so that I can use arrow keys, etc.
So I tried the following script and something about rlwrap is causing previous output to be dumped to stdout when the interact command is hit.
Is there something I can do to make this not happen?
Code:
package require Expect
puts "Tcl version : [info tclversion]"
puts "Expect version: [exp_version]"
log_user 0
spawn -noecho rlwrap tclsh
# Create procedure to easily reload utilites after changes have been made
expect "% "
send {
proc reload {} {
# Procedure to reload utility source easily for testing
}
}
# Source utilities
expect "% "
send "reload\r"
send_user "\nUse 'reload' procedure to re-source utility files\n\n"
log_user 1
interact
Output:
Tcl version : 8.4
Expect version: 5.43.0
Use 'reload' procedure to re-source utility files
proc reload {} {
# Procedure to reload utility source easily for testing
}
% reload
%
You can that for some reason it's echoing the proc definition and the entering of the reload command. This occurs as soon as interact occurs. If I replace interact with "exit" I do not see any of this output.
Of course the output I'm hope to see would be this:
Tcl version : 8.4
Expect version: 5.43.0
Use 'reload' procedure to re-source utility files
%
If you don't mind to compile a small C program yourself, you could use this:
#include <tcl.h>
#ifdef WIN32
#ifdef UNICODE
#define WIN32_UNICODE
#endif
#endif
int TclSHI_Main(Tcl_Interp*);
static int g_argc;
#ifdef WIN32_UNICODE
#define Tcl_NewStringObj Tcl_NewUnicodeObj
static wchar_t*** g_argv;
void wmain(int argc, wchar_t **argv) {
#else
static char*** g_argv;
void main(int argc, char **argv) {
#endif
g_argc = argc;
g_argv = &argv;
Tcl_FindExecutable(argv[0]);
Tcl_Main(1, argv, TclSHI_Main);
}
int TclSHI_Main(Tcl_Interp* interp) {
Tcl_Obj* lobj;
int i;
if (g_argc > 1) {
Tcl_SetVar2Ex(interp, "argv0", NULL, Tcl_NewStringObj((*g_argv)[1], -1), TCL_GLOBAL_ONLY);
}
lobj = Tcl_NewObj();
Tcl_IncrRefCount(lobj);
for (i = 2; i < g_argc; i++) {
Tcl_ListObjAppendElement(interp, lobj, Tcl_NewStringObj((*g_argv)[i], -1));
}
Tcl_SetVar2Ex(interp, "argv", NULL, lobj, TCL_GLOBAL_ONLY);
Tcl_DecrRefCount(lobj);
Tcl_SetVar2Ex(interp, "argc", NULL, Tcl_NewIntObj(g_argc - 2), TCL_GLOBAL_ONLY);
if (g_argc > 1) {
Tcl_Eval(interp, "source $argv0");
}
return TCL_OK;
}
I tested it on windows (CL) and linux (GCC).
To compile it with gcc I used gcc TclSH.c -o TclSHI -ltcl8.6
On windows I used Visual Studio.
It tells Tcl that it did not receive any arguments (Tcl_Main(1,...)), but populates the new interp with this arguments and sources the file. After this step it will always show the prompt (it never received any arguments, right?).
There is a small problem with your expect solution, if you specify any arguments, Tcl would execute that script, and never show the prompt.
Also note that I'm a novice C programmer, so this solution might not be bullet proof.
What you want to do is to wait for an unambiguous marker that indicates that the subordinate process is ready.
# ... your script as above ...
expect "% "
#### NEW STUFF STARTS ####
send "reload;puts READY\r"
expect "READY\r"
# Note that we need to fake the prompt; c'est la vie
send_user "\nUse 'reload' procedure to re-source utility files\n\n% "
# Now start doing things!
log_user 1
interact
Or at least that works when I try with a subordinate process, but I wasn't using rlwrap in the mix so that might change thingsā€¦