Thread: Cmake - Autom. regenerate a file using an external tool and custom target upon "make"

  1. #1
    Registered User
    Join Date
    May 2008
    Posts
    11

    Cmake - Autom. regenerate a file using an external tool and custom target upon "make"

    Hi. I'm working on a project and I use cmake for generating "projects", that is, under Linux, a Makefile.

    I also use an external tool (re2c) to generate the scanner, and an included tool to generate the parser (lemon, part of sqlite).

    The problem is I need to "cmake" every time I change something in the grammar (lemon_parser.y) or in the scanner (scanner.re).
    I'd rather need them be regenerated by make itself.

    The cmake files are:
    ./CMakeLists.txt:

    Code:
    1 cmake_minimum_required(VERSION 2.6)
    2 project(Calc C)
    3 #set(CMAKE_USE_RELATIVE_PATHS ON FORCE)
    4 set(CMAKE_BUILD_TYPE Debug)
    5 #set(CMAKE_VERBOSE_MAKEFILE true)
    6 include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR}/parser)
    7
    8 IF ( ${CMAKE_SOURCE_DIR} EQUAL ${CMAKE_BINARY_DIR} AND NOT ${ACCEPT_SOURCE_DIR} )
    9 MESSAGE( FATAL "Please choose a different directory for building" )
    10 ENDIF( ${CMAKE_SOURCE_DIR} EQUAL ${CMAKE_BINARY_DIR} AND NOT ${ACCEPT_SOURCE_DIR} )
    11
    12 add_subdirectory(lemon)
    13 add_subdirectory(hash)
    14 add_subdirectory(parser)
    15 #memory safety
    16 #add_subdirectory(memory_safety)
    17
    18 add_executable(calc main.c)
    19 target_link_libraries(calc hash parser)
    ./parser/CMakeLists.txt
    Code:
    1 set(parser_odir "${CMAKE_CURRENT_BINARY_DIR}/")
    2 include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${parser_odir})
    3
    4 add_custom_command(
    5 OUTPUT "${parser_odir}lemon_parser.c" "${parser_odir}lemon_parser.h" "${parser_odir}lemon_parser.out"
    6 #COMMAND ${PROJECT_BINARY_DIR}/lemon/lemon d="${CMAKE_CURRENT_SOURCE_DIR}/lempar.c" "${CMAKE_CURRENT_BINARY_DIR}/lemon_parser.y"
    7 COMMAND ${PROJECT_BINARY_DIR}/lemon/lemon d="${CMAKE_CURRENT_SOURCE_DIR}/lempar.c" "${parser_odir}lemon_parser.y"
    8 DEPENDS lemon "${CMAKE_CURRENT_SOURCE_DIR}/lemon_parser.y"
    9 )
    10 #add_custom_target(lemon_parser)
    11 file(READ lemon_parser.y parser_content)
    12 file(WRITE "${parser_odir}lemon_parser.y" "${parser_content}")
    13
    14 add_custom_command(
    15 OUTPUT "${parser_odir}scanner.c"
    16 COMMAND re2c -i "${CMAKE_CURRENT_SOURCE_DIR}/scanner.re" > "${parser_odir}scanner.c"
    17 DEPENDS "${parser_odir}lemon_parser.h" "${CMAKE_CURRENT_SOURCE_DIR}/scanner.re"
    18 )
    19 #add_custom_target(re2c_scanner)
    20
    21 #add_custom_target(lemon_parser ALL DEPENDS "${parser_odir}lemon_parser.c" "${parser_odir}lemon_parser.h")
    22 add_library(parser STATIC "${parser_odir}lemon_parser.c" "${parser_odir}scanner.c" parser.c ast.c)
    and a file irrelevant to the problem:
    ./hash/CMakeLists.txt:
    Code:
    1 add_library(hash STATIC hash_table.c hash_functions.c)
    I suppose it's a trivial task for the experienced cmake user.

    Thanks in advance.
    Cheers.

  2. #2
    Registered User
    Join Date
    May 2008
    Posts
    11
    Solved. The solution was

    Code:
         1	set(parser_odir "${CMAKE_CURRENT_BINARY_DIR}/")
         2	include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${parser_odir})
         3	
         4	#The right way to me would be to use the commands (2) and (4)
         5	#but it seems one needs (1) and (3) instead, if regeneration
         6	#of the scanner.re and parser.y is desired with only a "make"
         7	#command.
         8	#
         9	#Why I think that would be the right way? Because commands
        10	#have output (in cmake terms) and targets don't.
        11	
        12	add_custom_target(lemon_parser
        13		COMMAND ${CMAKE_COMMAND} -E copy "lemon_parser.y" "${parser_odir}lemon_parser.y"
        14	#(1):
        15		COMMAND ${PROJECT_BINARY_DIR}/lemon/lemon d="${CMAKE_CURRENT_SOURCE_DIR}/lempar.c" "${parser_odir}lemon_parser.y"
        16		WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
        17		COMMENT "add_custom_target(lemon_parser)"
        18		)
        19	add_custom_command(OUTPUT "${parser_odir}lemon_parser.c"
        20	#(2):
        21	#	COMMAND ${PROJECT_BINARY_DIR}/lemon/lemon d="${CMAKE_CURRENT_SOURCE_DIR}/lempar.c" "${parser_odir}lemon_parser.y"
        22		COMMENT "add_custom_command(parser)"
        23		)
        24	
        25	add_custom_target(re2c_scanner
        26	#(3):
        27		COMMAND re2c -i "${CMAKE_CURRENT_SOURCE_DIR}/scanner.re" > "${parser_odir}scanner.c"
        28		COMMENT "add_custom_target(re2c_scanner)"
        29		)
        30	add_custom_command(OUTPUT "${parser_odir}scanner.c"
        31	#(4):
        32	#	COMMAND re2c -i "${CMAKE_CURRENT_SOURCE_DIR}/scanner.re" > "${parser_odir}scanner.c"
        33		COMMENT "add_custom_command(scanner)"
        34		)
        35	add_library(parser STATIC parser.c ast.c "${parser_odir}scanner.c" "${parser_odir}lemon_parser.c")
        36	add_dependencies(parser lemon_parser re2c_scanner)
        37	add_dependencies(lemon_parser lemon)
    Hopefully this will help someone else.

Popular pages Recent additions subscribe to a feed

Tags for this Thread