przekazanie stringa z flagi kompilatora do programu w unit testach

0

Witam
W unit testach potrzebuję takiej funkcjonalności. W Cmaku robię:

set(CMAKE_CXX_FLAGS "-DBIN_PATH=${EXECUTABLE_OUTPUT_PATH} ${CMAKE_CXX_FLAGS}")

i chciałbym w programie C++ w unit testach użyć:

#define convert_flag_to_string(s) str(s)
#define str(s) std::string(#s)

std::cout << "path to configuration directory: " << convert_flag_to_string(BIN_PATH)  << std::endl;

No i problem jest taki że w pewnym środowisku gdzie jest sdka mi to nie działa, jak w ścieżce występuje keyword "linux" to mi kurde zamienia to na el "l".
Czyli np. dla takiego debugowego kejsa:

set(CMAKE_CXX_FLAGS "-DBIN_PATH=${EXECUTABLE_OUTPUT_PATH} ${CMAKE_CXX_FLAGS}")
SET(VAR_A "aa 1inux bb")
SET(VAR_B "aa linux bb ")
SET(VAR_C "aa kinux bb")
set(CMAKE_CXX_FLAGS "-DKIN_PATH=${VAR_A} ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "-DLIN_PATH=${VAR_B} ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "-DMIN_PATH=${VAR_C} ${CMAKE_CXX_FLAGS}")

otrzymuję w programie:

std::cout << convert_flag_to_string(KIN_PATH)  pokazuje keyword "aa 1inux bb"   //expected
std::cout << convert_flag_to_string(LIN_PATH)  pokazuje keyword "aa l bb"       //WTF???
std::cout << convert_flag_to_string(MIN_PATH)  pokazuje keyword "aa kinux bb"   //expected

Nie rozumiem czemu jak w stringu występuje keyword "linux" to na poziomie programu otrzymuję literkę el "l". To jest jakaś magia. Przez to utki mi nie działają bo mi nie znajduje ścieżki do konfiguracji. Czy to znaczy że w #define convert_flag_to_string trzeba coś poprawić?

Na poziomie programu musze mieć bezwzględną ścieżkę, takie coś aby założyć że folder jest w tej samej lokalizacji co binarka z utkami a więc użyć "./" to nie zawsze zadziała z tymi utkami, stąd próbuję przekazać poprzez flagę kompilacji tą bezwględną ścieżkę.

użycie target_compile_definition i tam przekazanie flagi też nie pomaga, jest taki sam rezultat, jeszcze w poniedziałek spróbuję w cmaku użyć configure_file, wtedy nie muszę define'a convert_flag_to_string używać, ale mega dziwny kejs z tą zamianą słowa "linux" na l.

2
fvg napisał(a):

Witam
W unit testach potrzebuję takiej funkcjonalności. W Cmaku robię:

set(CMAKE_CXX_FLAGS "-DBIN_PATH=${EXECUTABLE_OUTPUT_PATH} ${CMAKE_CXX_FLAGS}")

Takie modyfikowanie zmiennych cmake to jest zła praktyka!
Na dodatek dodajesz tam -DBIN_PATH=${EXECUTABLE_OUTPUT_PATH} co cmake same kontroluje za pomocą zmiennych: CMAKE_ARCHIVE_OUTPUT_DIRECTORY, CMAKE_LIBRARY_OUTPUT_DIRECTORY, CMAKE_RUNTIME_OUTPUT_DIRECTORY.

Do definiowania makr z poziomu cmake jest target_compile_definitions:

target_compile_definitions(TwojTargetUnitTest 
    PRIVATE 
        KIN_PATH "${VAR_A}"
        LIN_PATH "${VAR_B}"
        MIN_PATH "${VAR_C}"        
)

Do modyfikowania flag budowania powinno używać się target_compile_options.
Jest na to faja sztuczka:

add_library(my_compile_options INTERFACE)
target_compile_options(my_compile_options
    INTERFACE
        -Wall -Wextra -pedantic
)

...

target_link_library(TwojTargetUnitTest PRIVATE my_compile_options)

Pytanie cierpi od problemu XY. Co konkretnie jest twoim celem?

1

Nie wiem czy dobrze rozumiem, chcesz mieć ścieżkę w której aktualnie znajduje się twój program? Nie możesz użyć std::filesystem i sobie wyciągnąć? No a załadować przypadki testowe z zwykłego pliku/jsona po prostu, albo jak chcesz flagi to argv?

1

Gdyby podstawiało jedynkę, powiedziałbym że chodzi o wbudowane makro z gcc. Ale skoro el, to nie wiem.

Z obejść oprócz flag są jeszcze zmienne środowiskowe - std::getenv.

4

Dobra chyba załapałem o co ci chodzi, chcesz przenieś zawartość zmiennych cmake do kodu programu.
Od tego jest configure_file.

Tu masz demo jak to zrobić ConfigureCMake.zip:

cmake_minimum_required(VERSION 3.25)

project(CustomMacros VERSION 1.0.0 LANGUAGES CXX)

SET(CMAKE_CXX_STANDARD 17)
SET(CMAKE_CXX_STANDARD_REQUIRED YES)
SET(VAR_A "aa 1inux bb")
SET(VAR_B "aa linux bb ")
SET(VAR_C "aa kinux bb")

configure_file(project_constants.h.in project_constants.h ESCAPE_QUOTES)

add_executable(test_app main.cpp project_constants.h project_constants.h.in)
target_include_directories(test_app PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")

project_constants.h.in

/**
 * file generated form project_constants.h.in 
 */

#ifndef PROJECT_CONSTANTS_H
#define PROJECT_CONSTANTS_H

#include <string_view>

constexpr std::string_view  KIN_PATH{ "@VAR_A@" };
constexpr std::string_view  LIN_PATH{ "@VAR_B@" };
constexpr std::string_view  MIN_PATH{ "@VAR_C@" };

#endif // PROJECT_CONSTANTS_H

Działa jak należy.

1 użytkowników online, w tym zalogowanych: 0, gości: 1