diff --git a/CMakeLists.txt b/CMakeLists.txt index 2dffc94d..377f65cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -222,6 +222,15 @@ if (COOLPROP_DEBIAN_PACKAGE) install (FILES ${CMAKE_SOURCE_DIR}/include/CoolPropLib.h DESTINATION "${CMAKE_INSTALL_PREFIX}/usr/include") endif() +if (COOLPROP_VXWORKS_LIBRARY_MODULE OR COOLPROP_VXWORKS_LIBRARY) + list(APPEND APP_SOURCES "${CMAKE_SOURCE_DIR}/src/CoolPropLib.cpp") + add_executable(${app_name} ${APP_SOURCES}) + set_target_properties (${app_name} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -DEXTERNC") + add_dependencies (${app_name} generate_headers) + install (TARGETS ${app_name} DESTINATION shared_library/VxWorks) + install (FILES ${CMAKE_SOURCE_DIR}/include/CoolPropLib.h DESTINATION shared_library) +endif() + if (COOLPROP_32BIT_SHARED_LIBRARY_LINUX_MODULE OR COOLPROP_32BIT_SHARED_LIBRARY_LINUX) if(!UNIX) message(FATAL_ERROR "COOLPROP_32BIT_SHARED_LIBRARY_LINUX_MODULE can only be used on linux host") diff --git a/Web/coolprop/wrappers/Labview/index.rst b/Web/coolprop/wrappers/Labview/index.rst index 104dd7c1..4543f5ac 100644 --- a/Web/coolprop/wrappers/Labview/index.rst +++ b/Web/coolprop/wrappers/Labview/index.rst @@ -32,6 +32,13 @@ User-Compiled Binaries VxWorks ******* +Using the toolchain +------------------- + +To compile:: + + cmake ../.. -DCOOLPROP_VXWORKS_LIBRARY_MODULE=ON -DCMAKE_TOOLCHAIN_FILE=../../dev/cmake/Toolchains/powerpc-vxworks-crio.cmake -DCMAKE_CXX_FLAGS="-D__powerpc__" + If you want to compile binaries for PowerPC architecture (like the VXWorks target), follow these instructions to set up a toolchain Use pre-built binaries from FirstForge diff --git a/dev/cmake/Scripts/powerpc-wrs-vxworks-munch b/dev/cmake/Scripts/powerpc-wrs-vxworks-munch new file mode 100755 index 00000000..e1a0c453 --- /dev/null +++ b/dev/cmake/Scripts/powerpc-wrs-vxworks-munch @@ -0,0 +1,11 @@ +#!/bin/bash +TOOL_DIR="/usr/powerpc-wrs-vxworks" +TCL_SCRIPT="$WIND_BASE/host/resource/hutils/tcl/munch.tcl" +OUTPUT_FILE=$1 +NM_EXE="powerpc-wrs-vxworks-nm" + +shift 1 + +#sed is in the pipeline here in order to allow LTO +"$NM_EXE" "$@" | tclsh "$TCL_SCRIPT" -c ppc | sed 's/extern void\(.*\);/extern void \1 __attribute__((externally_visible));/' > "$OUTPUT_FILE" + diff --git a/dev/cmake/Scripts/powerpc-wrs-vxworks-stripsyms b/dev/cmake/Scripts/powerpc-wrs-vxworks-stripsyms new file mode 100755 index 00000000..0be5c484 --- /dev/null +++ b/dev/cmake/Scripts/powerpc-wrs-vxworks-stripsyms @@ -0,0 +1,13 @@ +#!/bin/sh + +TMPDIR="/tmp" +OBJCOPY_EXE="powerpc-wrs-vxworks-objcopy" +NM_EXE="powerpc-wrs-vxworks-nm" +OBJ=$1 + +shift 1 + +$NM_EXE "$@" | cut -d ' ' -f 3 | sed '/^$/d' > $TMPDIR/$$.syms +$OBJCOPY_EXE --localize-symbols=$TMPDIR/$$.syms $OBJ + +rm $TMPDIR/$$.syms diff --git a/dev/cmake/Toolchains/powerpc-vxworks-crio.cmake b/dev/cmake/Toolchains/powerpc-vxworks-crio.cmake index b0f752f0..df73f24a 100644 --- a/dev/cmake/Toolchains/powerpc-vxworks-crio.cmake +++ b/dev/cmake/Toolchains/powerpc-vxworks-crio.cmake @@ -1,24 +1,166 @@ # run with cmake -DCMAKE_TOOLCHAIN_FILE=... # the name of the target operating system +# Based on http://www.cmake.org/Wiki/CMake_Cross_Compiling -set(CMAKE_SYSTEM_NAME Linux) -# -####################################### -# which compilers to use for C and C++ -####################################### -set(CMAKE_C_COMPILER powerpc-wrs-vxworks-gcc) -set(CMAKE_CXX_COMPILER powerpc-wrs-vxworks-g++) -# -# -####################################### -# Where to look for target binaries -####################################### +set(CMAKE_SYSTEM_NAME Generic) +INCLUDE(CMakeForceCompiler) +### CONFIGURATION ### -# -# adjust the default behaviour of the FIND_XXX() commands: -# search headers and libraries in the target environment, search -# programs in the host environment +if (${WIN32}) + GET_FILENAME_COMPONENT(WIN_INSTALLDIR + "[HKEY_LOCAL_MACHINE\\Software\\FIRST\\FRCToolchain;INSTALLDIR]" + ABSOLUTE CACHE) + if (NOT "${WIN_INSTALLDIR}" STREQUAL "") + set(TOOL_INST_DIR "${WIN_INSTALLDIR}\\mingw") + set(TOOLCHAIN_PREFIX "${TOOL_INST_DIR}\\powerpc-wrs-vxworks") + set(TOOLCHAIN_C_COMPILER powerpc-wrs-vxworks-gcc) + set(TOOLCHAIN_CXX_COMPILER powerpc-wrs-vxworks-g++) + set(TOOLCHAIN_IS_GCCDIST false) + else() + message(FATAL_ERROR "Your configuration is not supported") + endif() + set(SCRIPT_SUFFIX ".bat") +else() + # Assume usual configuration + set(TOOLCHAIN_PREFIX /usr/powerpc-wrs-vxworks) + set(TOOLCHAIN_IS_GCCDIST false) + set(TOOLCHAIN_C_COMPILER powerpc-wrs-vxworks-gcc) + set(TOOLCHAIN_CXX_COMPILER powerpc-wrs-vxworks-g++) + set(SCRIPT_SUFFIX "") +endif() + +set(STRIPSYMS "${CMAKE_SOURCE_DIR}/dev/cmake/Scripts/powerpc-wrs-vxworks-stripsyms${SCRIPT_SUFFIX}") #gccdist ignore +set(MUNCH "${CMAKE_SOURCE_DIR}/dev/cmake/Scripts/powerpc-wrs-vxworks-munch${SCRIPT_SUFFIX}") #see README + +### CONFIGURATION BELOW SHOULD NOT NEED TO BE CHANGED ### + +set(WIND_BASE "$ENV{WIND_BASE}") +set(CMAKE_INSTALL_PREFIX "${TOOLCHAIN_PREFIX}") +set(CMAKE_FIND_ROOT_PATH "${TOOLCHAIN_PREFIX}") +set(VXWORKS_USE_SOFT_FLOAT false) + +CMAKE_FORCE_C_COMPILER("${TOOLCHAIN_C_COMPILER}" GNU) +CMAKE_FORCE_CXX_COMPILER("${TOOLCHAIN_CXX_COMPILER}" GNU) +set(CMAKE_LIBRARY_PATH_FLAG -L) + +### TOOLCHAIN SPECIFIC CONFIGURATION ### +if(${TOOLCHAIN_IS_GCCDIST}) + ### CONFIGURATION FOR GCCDIST ONLY ### + set(DKM_LINK_SCRIPT "${WIND_BASE}/target/h/tool/gnu/ldscripts/link.OUT") +else() + ### CONFIGURATION FOR NON-GCCDIST TOOLCHAINS ONLY ### + #locations of libraries so we can use nm to find their symbols + set(VXWORKS_LIBSTDCXX "${TOOLCHAIN_PREFIX}/lib/libstdc++.a") + set(VXWORKS_LIBSUPCXX "${TOOLCHAIN_PREFIX}/lib/libsupc++.a") + #libgcc's location changes based on gcc, so ask compiler where it is + execute_process(COMMAND "${TOOLCHAIN_C_COMPILER}" -print-libgcc-file-name OUTPUT_VARIABLE VXWORKS_LIBGCC) + + #the above command leaves a newline at the end of VXWORKS_LIBGCC. + #This triggers a bug in cmake's link script execution which will + #segfault because it sees a blank line and passes an empty string to + #execvp(). For now, workaround: use regex to strip trailing newline + string(REGEX REPLACE "(\r?\n)+$" "" VXWORKS_LIBGCC "${VXWORKS_LIBGCC}") + + #link flags for standard libraries + set(VXWORKS_STDLIB_LINK " -lsupc++ -lstdc++ -lgcc") + #TODO: Do we want libsupc++? + + set(DKM_LINK_SCRIPT "${TOOLCHAIN_PREFIX}/share/ldscripts/dkm.ld") +endif() +### END TOOLCHAIN SPECIFIC CONFIGURATION ### + +### END CONFIGURATION ### + +# (embedded) targets without operating system usually don't support shared libraries +SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE) +# is this true? We can add a dependency on another kernel module, but it's crufty + +# To help the find_xxx() commands, set at least the following so CMAKE_FIND_ROOT_PATH +# works at least for some simple cases: +SET(CMAKE_SYSTEM_INCLUDE_PATH /include ) +SET(CMAKE_SYSTEM_LIBRARY_PATH /lib ) +SET(CMAKE_SYSTEM_PROGRAM_PATH /bin ) +SET(CMAKE_SYSTEM_PREFIX_PATH / ) + +# search for programs in the build host directories set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +# for libraries and headers in the target directories set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -# \ No newline at end of file + +#System Headers +if(${TOOLCHAIN_IS_GCCDIST}) + set(SYSTEM_INCLUDES "-isystem ${WIND_BASE}/target/h -isystem ${WIND_BASE}/target/h/wrn/coreip") +else() + #modern build toolchains do not presently require additional includes +endif() + +#build flags +set(CPU PPC603) +set(TOOL_FAMILY gnu) +set(TOOL gnu) +set(ARCH_SPEC "-mcpu=603 -mstrict-align -mlongcall") + +if (${VXWORKS_USE_SOFT_FLOAT}) + set(ARCH_SPEC "${ARCH_SPEC} -msoft_float") +endif() + +#Set CFLAGS, LDFLAGS +#Note that we use -nostdlib and then link with the standard library +set(VXWORKS_COMPILE_FLAGS "${ARCH_SPEC} -nostdlib -Wall ${SYSTEM_INCLUDES} -DCPU=${CPU} -DTOOL_FAMILY=${TOOL_FAMILY} -DTOOL=${TOOL} -D_WRS_KERNEL") +set(VXWORKS_DKM_LINK_FLAGS "-nostdlib -r -Wl,-X -static") #should be equivalent to -nostdlib -Wl,-X,-r -static but I don't want to mess... +set(VXWORKS_DKM_LINK_SCRIPT_FLAG "-T \"${DKM_LINK_SCRIPT}\"") + +#Set toolchain definitions +set(CMAKE_C_COMPILE_OBJECT " -c -o ${VXWORKS_COMPILE_FLAGS}") +#CXX: Use c++11 by default now +set(CMAKE_CXX_COMPILE_OBJECT " -c -o ${VXWORKS_COMPILE_FLAGS}") +set(CMAKE_C_CREATE_STATIC_LIBRARY " cr " " ") +set(CMAKE_CXX_CREATE_STATIC_LIBRARY " cr " " ") +set(CMAKE_C_LINK_EXECUTABLE " -o ${VXWORKS_DKM_LINK_FLAGS} ${VXWORKS_DKM_LINK_SCRIPT_FLAG}") + +#link rules for C++: +#TODO: This will NOT work on win32! +if(${TOOLCHAIN_IS_GCCDIST}) +# Do a partial link. +# - The first line compiles the partial image - NOTE: we link static libraries at this point so that all of +# the symbols that are pulled into the module (and only those symbols) will be munched in the next step +# - The second line "munches" the executable to generate a file (_ctdt.c) that contains all of the +# static constructors and destructors in an array so that the kernel can call them at the appropriate times. +# - The third line compiles the ctor/dtor file. +# - The fourth line links the partial image together with the ctor/dtor object to create the finished executable +# - The last line cleans up all these generated files (which will have to be regenerated later anyway) +# +# NOTE: We don't link the standard library here as we'll get the kernel's copy when we get loaded in + set(CMAKE_CXX_LINK_EXECUTABLE + " ${VXWORKS_DKM_LINK_FLAGS} -o _PartialImage.out " + "${MUNCH} _ctdt.c _PartialImage.out" + " -c _ctdt.c -o _ctdt.c.o ${VXWORKS_COMPILE_FLAGS}" + " _PartialImage.out _ctdt.c.o -o ${VXWORKS_DKM_LINK_FLAGS} ${VXWORKS_DKM_LINK_SCRIPT_FLAG}" + " -E remove _PartialImage.out _ctdt.c _ctdt.c.o" + ) +else() +# Here's the crazy part... +# - The first line compiles the partial image - NOTE: notice we also link the standard library at this point +# - We munch the executable, which now contains the standard library as well +# - The third line compiles the ctor/dtor file as above. +# - The fourth line links the partial image together with the ctor/dtor object to create another partial image +# - The fifth line localizes the symbols from the misc. standard libraries. This is needed because if they are global +# symbols then we'll get conflicts with the kernel's standard libraries as we share address space. This is +# what sucks about sharing address space with the kernel... +# - The last line cleans up again. +# +# NOTE: We need to link in our own standard library, both to get its features and because there might be some conflicts +# in what symbols are defined, inline functions, and other internals between the kernel's stdlib (which is a whole +# major version old!) and the one we have. Even if its just the headers, something might break. The gccdist link +# command might work, but I don't recommend it. + set(CMAKE_CXX_LINK_EXECUTABLE + " ${VXWORKS_DKM_LINK_FLAGS} -o _PartialImage.out ${VXWORKS_STDLIB_LINK}" + "${MUNCH} _ctdt.c _PartialImage.out" + " -c _ctdt.c -o _ctdt.c.o ${VXWORKS_COMPILE_FLAGS}" + " _PartialImage.out _ctdt.c.o -o ${VXWORKS_DKM_LINK_FLAGS} ${VXWORKS_DKM_LINK_SCRIPT_FLAG}" + "${STRIPSYMS} \"${VXWORKS_LIBSTDCXX}\" \"${VXWORKS_LIBSUPCXX}\" \"${VXWORKS_LIBGCC}\"" + " -E remove _PartialImage.out _ctdt.c _ctdt.c.o" + ) +endif() + diff --git a/include/PlatformDetermination.h b/include/PlatformDetermination.h index a6f1952b..8181a204 100644 --- a/include/PlatformDetermination.h +++ b/include/PlatformDetermination.h @@ -10,6 +10,8 @@ # define __ISAPPLE__ #elif __linux || __unix || __posix # define __ISLINUX__ +#elif __powerpc__ +# define __ISPOWERPC__ #else # pragma error #endif diff --git a/src/Backends/REFPROP/REFPROPMixtureBackend.cpp b/src/Backends/REFPROP/REFPROPMixtureBackend.cpp index e79a5227..d454c4d9 100644 --- a/src/Backends/REFPROP/REFPROPMixtureBackend.cpp +++ b/src/Backends/REFPROP/REFPROPMixtureBackend.cpp @@ -26,14 +26,17 @@ surface tension N/m */ #include "CoolPropTools.h" -#if defined(__ISWINDOWS__) - #include - HINSTANCE RefpropdllInstance=NULL; - char refpropPath[] = ""; +#if defined(__powerpc__) + void *RefpropdllInstance=NULL; + char refpropPath[] = "/opt/refprop"; #elif defined(__ISLINUX__) #include void *RefpropdllInstance=NULL; char refpropPath[] = "/opt/refprop"; +#elif defined(__ISWINDOWS__) + #include + HINSTANCE RefpropdllInstance=NULL; + char refpropPath[] = ""; #elif defined(__ISAPPLE__) #include void *RefpropdllInstance=NULL; diff --git a/src/SpeedTest.cpp b/src/SpeedTest.cpp index 1f0e145a..96c9b446 100644 --- a/src/SpeedTest.cpp +++ b/src/SpeedTest.cpp @@ -6,6 +6,11 @@ #include +// A hack to make powerpc happy since sysClkRateGet not found +#if defined(__powerpc__) + #define CLOCKS_PER_SEC 1000 +#endif + namespace CoolProp{ void compare_REFPROP_and_CoolProp(std::string fluid, CoolProp::input_pairs inputs, double val1, double val2, std::size_t N, double d1, double d2)