Search code examples
ccmakenfctdm-mingwlib-nfc

libnfc cmake header file compilation error


Am programming for NFC using the libnfc library in the C language. Am using the TDM-GCC MinGW Compiler and the CMAKE open source build system which I installed following this tutorial for building/compiling the code. I am trying to compile my program which includes/imports a header file having a source file. A part of the header file (card_objects.h) is:

#ifndef CARD_OBJECTS_H_
#define CARD_OBJECTS_H_
... //other code

int setApplicationID(uint8_t *rapdu, char tag[], int currentPos);
#endif

A part of the source code file (card_objects.c) is:

#include "card_objects.h"
... //other code

int setApplicationID(uint8_t *rapdu, char tag[], int currentPos)
{
    ... //other code
    return currentPos;
}

Both files are in the include_dir/ directory at the current path relative to the main file. I have called the header file in the main program file as follows:

#include "include_dir/card_objects.h"

... //othercode

int main(int argc, const char *argv[])
{
    .... //other code
    currentPos = setApplicationID(rapdu, "Application ID (AID): ", currentPos);
    ... //other code
}

when I try to compile the above program on my computer, i get the following error:

"... main_file.c:200: undefined reference to 'setApplicationID'"

Can anyone figure out what I could have done wrong? Keep in mind I have some other header files with no source files, just variable definitions, which are being compiled with no problem. This is the only header file-source file import and it's not working. Anyone see a problem?


Solution

  • You CMakeLists.txt file is incorrect.

    Here is your original:

    SET(EXAMPLES-SOURCES
      main_file
      tests/test_progs
    )
    
    INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../libnfc)
    INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include_dir) #this is where the two files are located
    
    # Examples
    FOREACH(source ${EXAMPLES-SOURCES})
      SET (TARGETS ${source}.c)
    
      IF(WIN32)
        SET(RC_COMMENT "${PACKAGE_NAME} example")
        SET(RC_INTERNAL_NAME ${source})
        SET(RC_ORIGINAL_NAME ${source}.exe)
        SET(RC_FILE_TYPE VFT_APP)
        CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/../contrib/win32/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/../windows/${source}.rc @ONLY)
        LIST(APPEND TARGETS ${CMAKE_CURRENT_BINARY_DIR}/../windows/${source}.rc)
      ENDIF(WIN32)
    
      ADD_EXECUTABLE(${source} ${TARGETS})
      TARGET_LINK_LIBRARIES(${source} nfc)
      TARGET_LINK_LIBRARIES(${source} nfcutils)
      INSTALL(TARGETS ${source} RUNTIME DESTINATION bin COMPONENT examples)
    ENDFOREACH(source)
    
    #install required libraries
    IF(WIN32)
      INCLUDE(InstallRequiredSystemLibraries)
      CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/cmake/FixBundle.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/FixBundle.cmake @ONLY)
      INSTALL(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/FixBundle.cmake)
    ENDIF(WIN32)
    
    IF(NOT WIN32)
      # Manuals for the examples
      FILE(GLOB manuals "${CMAKE_CURRENT_SOURCE_DIR}/*.1")
      INSTALL(FILES ${manuals} DESTINATION ${SHARE_INSTALL_PREFIX}/man/man1 COMPONENT manuals)
    ENDIF(NOT WIN32)
    

    In the FOREACH(source ${EXAMPLES-SOURCES}) section you create two targets, each one only has a single c file, so you end up with SET( TARGETS main_file.c ) in the first iteration and SET( TARGETS tests/test_progs.c) on the second iteration.

    card_objects.c is not referenced anywhere in the CMakeLists.txt file so it will never get built into any executable, hence you get an undefined reference to code that isn't being built...

    You should also add a cmake_minimum_required and project call to the CMakeLists.txt file too.

    Perhaps for example you need to use SET( TARGETS ${source}.c card_objects.c )