Skip to content

Commit

Permalink
Port to OSX + Cmake support
Browse files Browse the repository at this point in the history
Initial CMake support and port to OSX.

OSX does not have memrchr and rawmemchr so had to include implementations of those
  • Loading branch information
JoakimSoderberg committed Oct 28, 2015
1 parent c0dd2bb commit ba96f22
Show file tree
Hide file tree
Showing 2 changed files with 261 additions and 0 deletions.
193 changes: 193 additions & 0 deletions CMakeLists.txt
@@ -0,0 +1,193 @@
cmake_minimum_required (VERSION 2.8)
project(libnmea C)

option(NMEA_BUILD_STATIC_LIB "Build static libnmea" ON)
option(NMEA_BUILD_SHARED_LIB "Build shared libnmea" ON)
option(NMEA_BUILD_EXAMPLES "Build examples" ON)
option(NMEA_EXAMPLES_LINK_STATIC "Link examples statically" OFF)
option(NMEA_UNIT_TESTS "Build unit tests" ON)
option(NMEA_UNIT_TESTS_LINK_STATIC "Link unit tests statically" OFF)
option(NMEA_WITH_MEMCHECK "Run unit tests in valgrind" ON)

if (NOT NMEA_BUILD_STATIC_LIB AND NOT NMEA_BUILD_SHARED_LIB)
message(FATAL_ERROR "You must build either shared or static lib, or both")
endif()

if (NOT NMEA_BUILD_SHARED_LIB)
set(NMEA_EXAMPLES_LINK_STATIC ON)
set(NMEA_UNIT_TESTS_LINK_STATIC ON)
endif()

if (NOT NMEA_BUILD_STATIC_LIB)
message("Linking examples/unit tests to shared lib since NMEA_BUILD_STATIC_LIB is turned off")
set(NMEA_EXAMPLES_LINK_STATIC OFF)
set(NMEA_UNIT_TESTS_LINK_STATIC OFF)
endif()

# Set some nicer output dirs.
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)

# This is the location of the parser libraries
set(NMEA_PLUGIN_DIRECTORY ${PROJECT_BINARY_DIR}/parsers/)

set(NMEA_SRC
src/nmea/nmea.c
src/nmea/parser.c)

set(NMEA_HDR
src/nmea/nmea.h
src/nmea/parser.h
src/nmea/parser_types.h)

source_group("Headers" FILES ${NMEA_HDR})
source_group("Source" FILES ${NMEA_SRC})

if (NMEA_BUILD_STATIC_LIB)
add_library(nmea STATIC ${NMEA_SRC})
target_link_libraries(nmea dl)
install(TARGETS nmea DESTINATION lib)
endif()

if (NMEA_BUILD_SHARED_LIB)
if (POLICY CMP0042)
cmake_policy(PUSH)
cmake_policy(SET CMP0042 OLD)
endif()

add_library(nmea_shared SHARED ${NMEA_SRC})
target_link_libraries(nmea_shared dl)

if (UNIX)
set_target_properties(nmea_shared PROPERTIES OUTPUT_NAME nmea)
endif()

install(TARGETS nmea_shared DESTINATION lib)

if (POLICY CMP0042)
cmake_policy(POP)
endif()
endif()

# Build parsers.
file(GLOB PARSERS_SRCS
RELATIVE "${PROJECT_SOURCE_DIR}"
"${PROJECT_SOURCE_DIR}/src/parsers/*.c")
list(REMOVE_ITEM PARSERS_SRCS src/parsers/parse.c)

source_group("Parser Sources" FILES ${PARSERS_SRCS})

foreach(PARSER_SRC ${PARSERS_SRCS})
get_filename_component(PARSER_NAME ${PARSER_SRC} NAME_WE)
add_library(${PARSER_NAME} SHARED ${PARSER_SRC} src/parsers/parse.c)

# Copy parser plugins to separate cmake build directory.
set_target_properties(${PARSER_NAME} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${NMEA_PLUGIN_DIRECTORY})

# Install to where we expect this to be on the system (hard coded).
# Otherwise using absolute paths like this is not the CMake way.
install(TARGETS ${PARSER_NAME} DESTINATION /usr/lib/nmea/)
endforeach()

# Find parser headers as well.
file(GLOB PARSERS_HDRS
RELATIVE "${PROJECT_SOURCE_DIR}"
"${PROJECT_SOURCE_DIR}/src/parsers/*.h")
list(REMOVE_ITEM PARSERS_HDRS parse.h)
list(APPEND ${NMEA_PUB_HDR} ${PARSERS_HDRS})

# Install headers.
install(FILES src/nmea/nmea.h DESTINATION include)
install(FILES ${PARSERS_HDRS} DESTINATION include/nmea)

# And copy headers to build dir.
configure_file(src/nmea/nmea.h ${PROJECT_BINARY_DIR}/include/nmea.h COPYONLY)
foreach (HDR ${PARSERS_HDRS})
get_filename_component(HDR_NAME ${HDR} NAME_WE)
message("${HDR}")
configure_file(${HDR} ${PROJECT_BINARY_DIR}/include/nmea/${HDR_NAME}.h COPYONLY)
endforeach()

include_directories("${PROJECT_BINARY_DIR}/include/")

if (NMEA_BUILD_EXAMPLES)
# Find all example sources.
file(GLOB EXAMPLE_SRCS
RELATIVE "${PROJECT_SOURCE_DIR}"
"${PROJECT_SOURCE_DIR}/examples/*.c")

foreach (EXAMPLE_SRC ${EXAMPLE_SRCS})
get_filename_component(EXAMPLE_NAME ${EXAMPLE_SRC} NAME_WE)

add_executable(${EXAMPLE_NAME} ${EXAMPLE_SRC})

if (NMEA_EXAMPLES_LINK_STATIC)
target_link_libraries(${EXAMPLE_NAME} nmea)
else()
target_link_libraries(${EXAMPLE_NAME} nmea_shared)
endif()
endforeach()
endif()

if (NMEA_UNIT_TESTS)
ENABLE_TESTING()

# Find test sources.
file(GLOB TEST_SRCS
RELATIVE "${PROJECT_SOURCE_DIR}"
"${PROJECT_SOURCE_DIR}/tests/test_*.c")

# Find valgrind if we're supposed to check for leaks when
# running the unit tests.
if (NMEA_WITH_MEMCHECK)
find_program(VALGRIND_PROGRAM NAMES valgrind)

if (NOT EXISTS ${VALGRIND_PROGRAM})
message(WARNING "Valgrind not found! Tests will be run without memory check. Turn this warning off by installing valgrind or settings -DNMEA_WITH_MEMCHECK=OFF")
set(NMEA_WITH_MEMCHECK OFF)
else()
message("Found valgrind: ${VALGRIND_PROGRAM}")
endif()
endif()

#
# Lib unit tests.
#
add_executable(utests tests/test_lib.c)

if (NMEA_UNIT_TESTS_LINK_STATIC)
target_link_libraries(utests nmea)
else()
target_link_libraries(utests nmea_shared)
endif()

#
# Parse unit tests.
#
add_executable(utests-parse src/parsers/parse.c tests/test_parse.c)

#
# NMEA unit tests.
#
add_executable(utests-nmea src/nmea/parser.c tests/test_nmea_helpers.c)
target_link_libraries(utests-nmea dl)

set(TESTS utests utests-parse utests-nmea)

foreach(TEST_NAME ${TESTS})
message("${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}")
if (NMEA_WITH_MEMCHECK)
add_test("${TEST_NAME}_memchk" ${VALGRIND_PROGRAM} --gen-suppressions=all --error-exitcode=5 --leak-check=full ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME})

set_property(TEST ${TEST_NAME}_memchk PROPERTY ENVIRONMENT NMEA_PARSER_PATH=${NMEA_PLUGIN_DIRECTORY})
else()
add_test("${TEST_NAME}" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME})

# We must set this so we can find the plugins in the Cmake build dir when testing.
set_property(TEST ${TEST_NAME} PROPERTY ENVIRONMENT NMEA_PARSER_PATH=${NMEA_PLUGIN_DIRECTORY})
endif()
endforeach()
endif()

68 changes: 68 additions & 0 deletions src/nmea/nmea.c
Expand Up @@ -2,6 +2,74 @@
#include "parser.h"
#include "parser_types.h"


#ifdef __APPLE__

#include <limits.h>

/* $OpenBSD: memrchr.c,v 1.2 2007/11/27 16:22:12 martynas Exp $ */
/*
* Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $FreeBSD: head/lib/libc/string/memrchr.c 178051 2008-04-10 00:12:44Z delphij $
*/


/*
* Reverse memchr()
* Find the last occurrence of 'c' in the buffer 's' of size 'n'.
*/
void *
memrchr(const void *s, int c, size_t n)
{
const unsigned char *cp;

if (n != 0) {
cp = (unsigned char *)s + n;
do {
if (*(--cp) == (unsigned char)c)
return((void *)cp);
} while (--n != 0);
}
return(NULL);
}

void *rawmemchr(const void *src, int c)
{
#define SS (sizeof(size_t))
#define ALIGN (sizeof(size_t)-1)
#define ONES ((size_t)-1/UCHAR_MAX)
#define HIGHS (ONES * (UCHAR_MAX/2+1))
#define HASZERO(x) (((x)-ONES) & ~(x) & HIGHS)

long n = LONG_MAX;
const unsigned char *s = src;
c = (unsigned char)c;
for (; ((uintptr_t)s & ALIGN) && n && *s != c; s++, n--);
if (n && *s != c) {
const size_t *w;
size_t k = ONES * c;
for (w = (const void *)s; n>=SS && !HASZERO(*w^k); w++, n-=SS);
for (s = (const void *)w; n && *s != c; s++, n--);
}
return n ? (void *)s : 0;
}

#endif /* __APPLE__ */


/**
* Check if a value is supplied and set.
*
Expand Down

0 comments on commit ba96f22

Please sign in to comment.